AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Peg Parser New Statement

skill-mondaycom-duckdb-claude-peg-parser-new-statement · by mondaycom

Add a new SQL statement type to DuckDB's PEG parser. Use when the user asks to add, implement, or support parsing for a new SQL statement or syntax (e.g. CREATE TRIGGER, DROP TRIGGER, CREATE MATERIALIZED VIEW) in the PEG parser.

No reviews yet
0 installs
14 views
0.0% view→install

Install

$ agentstack add skill-mondaycom-duckdb-claude-peg-parser-new-statement

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-mondaycom-duckdb-claude-peg-parser-new-statement)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Peg Parser New Statement? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Add a New Statement to the PEG Parser

Add $ARGUMENTS to DuckDB's PEG parser. The PEG parser lives in extension/autocomplete/ and runs as a parser override extension before the legacy Postgres parser.

Choose your path based on the statement form:

  • CREATE-form (e.g. CREATE TRIGGER, CREATE MATERIALIZED VIEW) → follow Shared Steps, then Part A
  • DROP-form (e.g. DROP TRIGGER) → follow Shared Steps, then Part B

Shared Step 1 — Add the catalog type

In src/include/duckdb/common/enums/catalog_type.hpp, add:

XXX_ENTRY = ,

In src/common/enums/catalog_type.cpp, add to both CatalogTypeToString and CatalogTypeFromString.


Shared Step 2 — Add enums (if needed)

Create src/include/duckdb/common/enums/xxx_type.hpp for any new enums specific to this statement, then regenerate:

python3 scripts/generate_enum_util.py

Part A: CREATE-form statements

A1 — Define the grammar

Create extension/autocomplete/grammar/statements/create_xxx.gram.

Wire the new statement into CreateStatementVariation in create_table.gram:

CreateStatementVariation  Copy() const override;
    string ToString() const override;
    DUCKDB_API void Serialize(Serializer &serializer) const override;
    DUCKDB_API static unique_ptr Deserialize(Deserializer &deserializer);
};

} // namespace duckdb

Implementation: src/parser/parsed_data/create_xxx_info.cpp

  • Constructor: CreateXxxInfo() : CreateInfo(CatalogType::XXX_ENTRY, INVALID_SCHEMA) {}
  • Copy(): call CopyProperties(*result) then copy each field
  • ToString(): reconstruct the SQL string

If a field is a unique_ptr (not SelectStatement), it cannot be auto-serialized. Store the SQL text alongside it:

string sql_body_text;          // serialized
unique_ptr sql_body; // runtime only

Add to src/parser/parsed_data/CMakeLists.txt:

create_xxx_info.cpp

A3 — Add serialization config

In src/include/duckdb/storage/serialization/create_info.json, add:

{
  "class": "CreateXxxInfo",
  "base": "CreateInfo",
  "enum": "XXX_ENTRY",
  "includes": ["duckdb/parser/parsed_data/create_xxx_info.hpp"],
  "members": [
    { "id": 200, "name": "field_name", "type": "string" },
    { "id": 201, "name": "my_enum",    "type": "MyEnumType" },
    { "id": 202, "name": "my_bool",    "type": "bool" }
  ]
}

Supported types: string, bool, int64_t, uint64_t, vector, unique_ptr, any registered enum. SQLStatement* is not supported — use string instead.

python3 scripts/generate_serialization.py

A4 — Write the transformer

Create extension/autocomplete/transformer/transform_create_xxx.cpp.

See the Transformer patterns section below for how to handle indexing, choices, optionals, lists, enums, and nested statements.

Add to extension/autocomplete/transformer/CMakeLists.txt:

transform_create_xxx.cpp

A5 — Register the transformer

In extension/autocomplete/transformer/peg_transformer_factory.cpp:

  1. Add a RegisterCreateXxx() function and call it from the constructor (keep alphabetical order):
void PEGTransformerFactory::RegisterCreateXxx() {
    REGISTER_TRANSFORM(TransformCreateXxxStmt);
    // ... all sub-rules
}
  1. Add new enum mappings to RegisterEnums().

In extension/autocomplete/include/transformer/peg_transformer.hpp:

  1. Add void RegisterCreateXxx(); with the other RegisterCreate* declarations.
  2. Add a static declaration for each transform function.
  3. If you have a custom intermediate struct, create it in extension/autocomplete/include/ast/xxx_info.hpp and include it from the header.

A6 — Handle excluded rules

Rules used only as boolean flags (e.g. `ForEachRow TransformDropXxxStmt(PEGTransformer &transformer, ParseResult &pr) { auto &listpr = pr.Cast(); // 'DROP' 'XXX' IfExists? QualifiedName // [0] [1] [2] [3] auto result = makeuniq(); result->type = CatalogType::XXXENTRY; result->ifexists = listpr.Child(2).HasResult(); auto qname = transformer.Transform(listpr.Child(3)); result->name = qname.name; result->schema = qname.schema; return result; }


See the **Transformer patterns** section below for handling other grammar constructs.

Add to `extension/autocomplete/transformer/CMakeLists.txt`:
```cmake
transform_drop_xxx.cpp

B3 — Register the transformer

In extension/autocomplete/transformer/peg_transformer_factory.cpp:

  1. Add a RegisterDropXxx() function and call it from the constructor (keep alphabetical order):
void PEGTransformerFactory::RegisterDropXxx() {
    REGISTER_TRANSFORM(TransformDropXxxStmt);
    // ... all sub-rules
}

In extension/autocomplete/include/transformer/peg_transformer.hpp:

  1. Add void RegisterDropXxx(); with the other RegisterDrop* declarations.
  2. Add a static declaration for each transform function.

B4 — Handle excluded rules

Same as A6 — add boolean-flag-only rules to EXCLUDED_RULES in scripts/generate_peg_transformer.py.


B5 — Add binder stub

In src/planner/binder/statement/bind_drop.cpp, add before the default throw:

case CatalogType::XXX_ENTRY:
    throw NotImplementedException("DROP XXX is not yet supported");

B6 — Write tests

Create test/sql/xxx/drop_xxx_parse.test. Required boilerplate:

require autocomplete

statement ok
call enable_peg_parser();

Syntax error tests must match a specific error message (see A8 for the rationale and pattern).

To find the exact error message:

echo "call enable_peg_parser(); DROP XXX bad syntax;" | build/debug/duckdb

B7 — Verify coverage and format

# All rules must be FOUND, ENUM, or EXCLUDED — no MISSING
python3 scripts/generate_peg_transformer.py | grep -A30 "File: drop_xxx"

# Reformat changed files
make format-main

Grammar reference

Key grammar syntax:

  • 'KEYWORD' — case-insensitive literal
  • Rule1 / Rule2 — ordered choice (first match wins)
  • Rule? — optional, Rule* / Rule+ — repeat
  • List(D) — comma-separated list (defined in common.gram)
  • Parens(D)D wrapped in parentheses
  • Statement — any full DuckDB SQL statement
  • QualifiedName[catalog.]schema.name identifier
  • IfNotExists — already defined, no transformer needed
  • IfExists — already defined, no transformer needed

Critical: never use List(...) directly inline in a rule — it has no transformer and will crash at runtime. Always wrap it in a named rule:

# WRONG:
MyRule (list_pr.Child(0).result);

Optionals (?): use OptionalParseResult::HasResult():

bool if_not_exists = list_pr.Child(1).HasResult();

Lists: use ExtractParseResultsFromList then loop:

auto items = ExtractParseResultsFromList(list_pr.Child(0));
for (auto &item : items) {
    result.push_back(transformer.Transform(item));
}

Enums: register in RegisterEnums(), then use TransformEnum:

// registration:
RegisterEnum("RuleName", MyEnum::VALUE);
// transformer:
return transformer.TransformEnum(list_pr.Child(0).result);

Nested statement:

auto body = transformer.Transform>(list_pr.Child(N));

Reference implementations

  • CreateView — simplest CREATE-form: create_view.gram + transform_create_view.cpp
  • CreateSequence — enum options + repeated sub-rules: create_sequence.gram + transform_create_sequence.cpp
  • CreateTrigger — choices, column list, nested statement body: create_trigger.gram + transform_create_trigger.cpp

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.