Repository navigation
fix: parse PostgreSQL DROP CAST, DROP OPERATOR and DROP TRANSFORM - #2896
Merged
manticore-projects merged 1 commit intoNov 5, 2026
Conversation
DROP CAST (source AS target), DROP OPERATOR op (left, right) and DROP TRANSFORM FOR type LANGUAGE lang failed in every dialect. pg_dump --clean writes them for every cast, operator and transform, so such a dump could not be parsed as a script. Drop.ObjectType gains CAST, OPERATOR and TRANSFORM, and their targets are typed: getCast() is a CastSignature, getOperators() holds an OperatorSignature per operator, with the operator reference COMMENT ON OPERATOR uses and null as the NONE marker of a missing operand, and getTransform() is a TransformSignature. toString() and the deparser render them through the same appendTo(), and they carry AST nodes spanning their source. Oracle's DROP OPERATOR name keeps a plain name. With the PostgreSQL dialect DROP OPERATOR and DROP TRANSFORM require their signatures, and a signature is followed only by CASCADE or RESTRICT. Signed-off-by: minleejae <mmj9808@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follows #2884, which added the PostgreSQL object types of several words to
DROP. The three object types here are named by types rather than by a name, so they need their own target models.Purpose
PostgreSQL names a cast, an operator and a transform by types rather than by a plain name:
All three fail to parse on
masterin every dialect:CASTis not aDROPobject type, and afterDROP OPERATORandDROP TRANSFORMthe parser expects object names, so===orFORis a syntax error.pg_dump --cleanwrites these statements for every cast, operator and transform in a database, so such a dump fails as a script at its firstDROP TRANSFORM,DROP CASTorDROP OPERATOR.Syntax reference: PostgreSQL 18 DROP CAST, DROP OPERATOR, DROP TRANSFORM.
Current design (As-is)
Dropkeeps its targets as typed lists:RoutineReferenceitems for FUNCTION, PROCEDURE, ROUTINE and AGGREGATE (getRoutines()),UserAccountitems for USER, ROLE, GROUP and OWNED BY (getAccounts()), and plainTablenames for everything else.getNames()derives read-only names from the routines and accounts.Drop()readsCASTnowhere, and readsOPERATORandTRANSFORMas a generic identifier with object typeOTHER, followed by a name list and loose trailing words. SoDROP OPERATOR fooandDROP TRANSFORM hstore LANGUAGE plpython3uparse with the PostgreSQL dialect, although PostgreSQL reports both as syntax errors.COMMENT ONalready reads the same three references intoCommentTarget:CAST (source AS target),OPERATOR [schema.]op (left | NONE, right | NONE)through the sharedPostgreSqlOperatorReference()andExtensionOperatorType()productions, andTRANSFORM FOR type LANGUAGE lang.Target design (To-be)
Drop.ObjectTypegainsCAST,OPERATORandTRANSFORM.DropTargets()reads their targets into three new value types innet.sf.jsqlparser.statement, next toRoutineReference:CastSignature: source and targetColDataType, rendered(source AS target);Drop.getCast().OperatorSignature: theExclusionOperatorreference thatCOMMENT ON OPERATORand exclusion constraints use, and the left and right operandColDataType, where null is theNONEmarker of a missing operand;Drop.getOperators()holds one per operator.TransformSignature: theColDataTypeand the language, renderedFOR type LANGUAGE lang;Drop.getTransform().NONE-or-type operands reuse theCOMMENT ON OPERATORproductions, including its rule that one operand must be a type.(NONE, NONE)and a single operand are rejected, as in PostgreSQL'soper_argtypes.getNames()also derives the operator names (public.===); a cast or transform has no name.toString()andDropDeParserrender the targets through the sameappendTo(). The signatures carry AST nodes spanning their source, likeMaintenanceTargetandUtilityOption.DROP OPERATORtakes the signature form when an operator symbol, or a schema, a dot and a symbol, follows. Otherwise it keeps a plain name, which is Oracle'sDROP OPERATOR [schema.]operator. With the PostgreSQL dialect a plain name afterDROP OPERATORorDROP TRANSFORMis rejected, since PostgreSQL reports it as a syntax error. A cast, transform or operator signature can be followed only byCASCADEorRESTRICT.Public method signatures are retained.
getObjectType()reportsOPERATORorTRANSFORMfor the name formsDROP OPERATOR nameandDROP TRANSFORM name, where it reportedOTHER. A catalog-qualified operator (db.schema.===) is still rejected: the shared operator reference takes one schema, as inCOMMENT ON OPERATOR.CommentTargetandExtensionObjectkeep their own fields for the same references; they could move to the new types in a separate change.Validation
DropSignatureTargetTestadds 19 statements. Each is checked againsttoString()and the deparser, parsed again, parsed with and without the PostgreSQL dialect and inside a script, and has no tables. Further tests check the cast, operator and transform fields and their edits, the source span of each signature, how the target kinds replace each other, Oracle'sDROP OPERATOR nameand other identifiers that start with an operator character or a quote, schemas namedclassorfamily, 26 rejected forms, and apg_dump --clean --if-existsstyle script.ASTNodeCoverageTestwalks three of the statements, andDropValidatorTestvalidates them for PostgreSQL. Onmaster(4a970a34e) all 19 statements fail, and 3 of the 26 rejected forms parse (DROP OPERATOR foo,DROP TRANSFORM foo,DROP TRANSFORM hstore LANGUAGE plpython3u).A
pg_dump --clean --if-existsstyle script with a transform, a cast, two operators and the objects they use (29 statements, fromSETthroughCOMMENT ON OPERATOR) fails onmasterat its firstDROP TRANSFORMand parses with this change.Java 17 Gradle
check: 12,691 tests, 0 failures, 25 skipped. Grammar ambiguity, formatting (Spotless ratchet againstupstream/master), Checkstyle, PMD, SpotBugs and JaCoCo pass.Compared with
master(4a970a34e) on the DDL/DCL survey corpora and the non-DDL corpora: no case is fixed, regressed or changed, since the corpora have noDROP CAST,DROP OPERATORorDROP TRANSFORM; the rendered statements and AST dumps are identical.The statements of the tests were run against PostgreSQL 18.3 (37 accepted and 28 rejected forms). Every form the parser accepts with the PostgreSQL dialect is accepted by the server's grammar, and every form it rejects is a syntax error there.
DROP OPERATOR ! (bigint, NONE)passes the grammar and fails only when the operator is looked up, since PostgreSQL 14 removed postfix operators;DROP OPERATOR IF EXISTS ! (bigint, NONE)succeeds with a notice. The catalog-qualifiedDROP OPERATOR a.b.=== (int, int)is accepted by the server's grammar (it then fails with "cross-database references are not implemented") and stays rejected here, as noted above.AI assistance: prepared with Claude Code.