tobymao / sqlglot

Python SQL Parser and Transpiler
https://sqlglot.com/
MIT License
6.82k stars 720 forks source link

`create constraint trigger` cannot be parsed #2538

Closed sweigert closed 1 year ago

sweigert commented 1 year ago

Hi,

I'm trying to parse the output of pg_dump with sqlglot. Some tables in our DB have constraint triggers to only execute the triggers when specific columns are updated. However, sqlglot fails to parse them correctly:

Fully reproducible code snippet

import sqlglot
sqlglot.parse_one('CREATE CONSTRAINT TRIGGER my_trigger AFTER INSERT OR DELETE OR UPDATE OF col_a, col_b ON public.my_table DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION do_sth();', read='postgres')

Output

---------------------------------------------------------------------------
ParseError                                Traceback (most recent call last)
[/Users/stefan/waku/dbtest/test.ipynb](https://file+.vscode-resource.vscode-cdn.net/Users/stefan/waku/dbtest/test.ipynb) Cell 10 line 1
----> [1](vscode-notebook-cell:/Users/stefan/waku/dbtest/test.ipynb#X31sZmlsZQ%3D%3D?line=0) sqlglot.parse_one('CREATE CONSTRAINT TRIGGER my_trigger AFTER INSERT OR DELETE OR UPDATE OF col_a, col_b ON my_table DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION do_sth();', read='postgres')

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:126](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:126), in parse_one(sql, read, dialect, into, **opts)
    [124](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:124)     result = dialect.parse_into(into, sql, **opts)
    [125](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:125) else:
--> [126](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:126)     result = dialect.parse(sql, **opts)
    [128](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:128) for expression in result:
    [129](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/__init__.py:129)     if not expression:

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/dialects/dialect.py:320](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/dialects/dialect.py:320), in Dialect.parse(self, sql, **opts)
    [319](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/dialects/dialect.py:319) def parse(self, sql: str, **opts) -> t.List[t.Optional[exp.Expression]]:
--> [320](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/dialects/dialect.py:320)     return self.parser(**opts).parse(self.tokenize(sql), sql)

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1004](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1004), in Parser.parse(self, raw_tokens, sql)
    [990](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:990) def parse(
    [991](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:991)     self, raw_tokens: t.List[Token], sql: t.Optional[str] = None
    [992](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:992) ) -> t.List[t.Optional[exp.Expression]]:
    [993](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:993)     """
    [994](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:994)     Parses a list of tokens and returns a list of syntax trees, one tree
    [995](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:995)     per parsed SQL statement.
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
   [1002](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1002)         The list of the produced syntax trees.
   [1003](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1003)     """
-> [1004](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1004)     return self._parse(
   [1005](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1005)         parse_method=self.__class__._parse_statement, raw_tokens=raw_tokens, sql=sql
   [1006](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1006)     )

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1070](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1070), in Parser._parse(self, parse_method, raw_tokens, sql)
   [1067](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1067) self._tokens = tokens
   [1068](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1068) self._advance()
-> [1070](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1070) expressions.append(parse_method(self))
   [1072](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1072) if self._index < len(self._tokens):
   [1073](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1073)     self.raise_error("Invalid expression [/](https://file+.vscode-resource.vscode-cdn.net/) Unexpected token")

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1254](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1254), in Parser._parse_statement(self)
   [1251](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1251)     return None
   [1253](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1253) if self._match_set(self.STATEMENT_PARSERS):
-> [1254](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1254)     return self.STATEMENT_PARSERS[self._prev.token_type](self)
   [1256](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1256) if self._match_set(Tokenizer.COMMANDS):
   [1257](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1257)     return self._parse_command()

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:555](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:555), in Parser.<lambda>(self)
    [486](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:486) COLUMN_OPERATORS = {
    [487](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:487)     TokenType.DOT: None,
    [488](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:488)     TokenType.DCOLON: lambda self, this, to: self.expression(
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
    [517](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:517)     ),
    [518](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:518) }
    [520](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:520) EXPRESSION_PARSERS = {
    [521](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:521)     exp.Cluster: lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
    [522](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:522)     exp.Column: lambda self: self._parse_column(),
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
    [546](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:546)     "JOIN_TYPE": lambda self: self._parse_join_parts(),
    [547](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:547) }
    [549](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:549) STATEMENT_PARSERS = {
    [550](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:550)     TokenType.ALTER: lambda self: self._parse_alter(),
    [551](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:551)     TokenType.BEGIN: lambda self: self._parse_transaction(),
    [552](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:552)     TokenType.CACHE: lambda self: self._parse_cache(),
    [553](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:553)     TokenType.COMMIT: lambda self: self._parse_commit_or_rollback(),
    [554](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:554)     TokenType.COMMENT: lambda self: self._parse_comment(),
--> [555](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:555)     TokenType.CREATE: lambda self: self._parse_create(),
    [556](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:556)     TokenType.DELETE: lambda self: self._parse_delete(),
    [557](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:557)     TokenType.DESC: lambda self: self._parse_describe(),
    [558](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:558)     TokenType.DESCRIBE: lambda self: self._parse_describe(),
    [559](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:559)     TokenType.DROP: lambda self: self._parse_drop(),
    [560](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:560)     TokenType.INSERT: lambda self: self._parse_insert(),
    [561](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:561)     TokenType.KILL: lambda self: self._parse_kill(),
    [562](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:562)     TokenType.LOAD: lambda self: self._parse_load(),
    [563](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:563)     TokenType.MERGE: lambda self: self._parse_merge(),
    [564](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:564)     TokenType.PIVOT: lambda self: self._parse_simplified_pivot(),
    [565](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:565)     TokenType.PRAGMA: lambda self: self.expression(exp.Pragma, this=self._parse_expression()),
    [566](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:566)     TokenType.ROLLBACK: lambda self: self._parse_commit_or_rollback(),
    [567](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:567)     TokenType.SET: lambda self: self._parse_set(),
    [568](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:568)     TokenType.UNCACHE: lambda self: self._parse_uncache(),
    [569](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:569)     TokenType.UPDATE: lambda self: self._parse_update(),
    [570](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:570)     TokenType.USE: lambda self: self.expression(
    [571](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:571)         exp.Use,
    [572](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:572)         kind=self._match_texts(("ROLE", "WAREHOUSE", "DATABASE", "SCHEMA"))
    [573](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:573)         and exp.var(self._prev.text),
    [574](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:574)         this=self._parse_table(schema=False),
    [575](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:575)     ),
    [576](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:576) }
    [578](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:578) UNARY_PARSERS = {
    [579](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:579)     TokenType.PLUS: lambda self: self._parse_unary(),  # Unary + is handled as a no-op
    [580](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:580)     TokenType.NOT: lambda self: self.expression(exp.Not, this=self._parse_equality()),
    [581](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:581)     TokenType.TILDA: lambda self: self.expression(exp.BitwiseNot, this=self._parse_unary()),
    [582](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:582)     TokenType.DASH: lambda self: self.expression(exp.Neg, this=self._parse_unary()),
    [583](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:583) }
    [585](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:585) PRIMARY_PARSERS = {
    [586](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:586)     TokenType.STRING: lambda self, token: self.expression(
    [587](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:587)         exp.Literal, this=token.text, is_string=True
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
    [609](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:609)     TokenType.SESSION_PARAMETER: lambda self, _: self._parse_session_parameter(),
    [610](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:610) }

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1422](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1422), in Parser._parse_create(self)
   [1411](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1411)         self._match(TokenType.R_PAREN)
   [1412](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1412)         clone = self.expression(
   [1413](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1413)             exp.Clone,
   [1414](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1414)             this=clone,
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
   [1419](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1419)             copy=copy,
   [1420](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1420)         )
-> [1422](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1422) return self.expression(
   [1423](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1423)     exp.Create,
   [1424](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1424)     comments=comments,
   [1425](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1425)     this=this,
   [1426](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1426)     kind=create_token.text,
   [1427](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1427)     replace=replace,
   [1428](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1428)     unique=unique,
   [1429](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1429)     expression=expression,
   [1430](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1430)     exists=exists,
   [1431](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1431)     properties=properties,
   [1432](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1432)     indexes=indexes,
   [1433](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1433)     no_schema_binding=no_schema_binding,
   [1434](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1434)     begin=begin,
   [1435](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1435)     end=end,
   [1436](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1436)     clone=clone,
   [1437](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1437) )

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1134](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1134), in Parser.expression(self, exp_class, comments, **kwargs)
   [1132](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1132) instance = exp_class(**kwargs)
   [1133](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1133) instance.add_comments(comments) if comments else self._add_comments(instance)
-> [1134](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1134) return self.validate_expression(instance)

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1154](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1154), in Parser.validate_expression(self, expression, args)
   [1152](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1152) if self.error_level != ErrorLevel.IGNORE:
   [1153](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1153)     for error_message in expression.error_messages(args):
-> [1154](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1154)         self.raise_error(error_message)
   [1156](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1156) return expression

File [/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1114](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1114), in Parser.raise_error(self, message, token)
   [1102](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1102) error = ParseError.new(
   [1103](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1103)     f"{message}. Line {token.line}, Col: {token.col}.\n"
   [1104](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1104)     f"  {start_context}\033[4m{highlight}\033[0m{end_context}",
ref='/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:0'>0</a>;32m   (...)
   [1110](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1110)     end_context=end_context,
   [1111](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1111) )
   [1113](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1113) if self.error_level == ErrorLevel.IMMEDIATE:
-> [1114](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1114)     raise error
   [1116](https://file+.vscode-resource.vscode-cdn.net/opt/homebrew/lib/python3.11/site-packages/sqlglot/parser.py:1116) self.errors.append(error)

ParseError: Required keyword: 'this' missing for <class 'sqlglot.expressions.Create'>. Line 1, Col: 25.
  CREATE CONSTRAINT TRIGGER my_trigger AFTER INSERT OR DELETE OR UPDATE OF col_a, col_b ON my_table DEFERRABLE INITIALLY DEFERR

Let me know if I'm doing anything obvious wrong. I can parse the line with

sqlglot.parse_one('CREATE CONSTRAINT TRIGGER my_trigger AFTER INSERT OR DELETE OR UPDATE OF col_a, col_b ON my_table DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION do_sth();', read='postgres', error_level=ErrorLevel.IGNORE)

but then the command is incomplete:

(CREATE kind: CONSTRAINT, exists: False)
sweigert commented 1 year ago

Thanks for the quick response 👍