Repository: melin/superior-sql-parser Branch: branch-4.0 Commit: ca42eea29ca1 Files: 274 Total size: 2.4 MB Directory structure: gitextract_hvwwon62/ ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml ├── superior-appjar-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── job/ │ │ │ └── antlr4/ │ │ │ ├── AppJarLexer.g4 │ │ │ └── AppJarParser.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── appjar/ │ │ ├── AbstractJarParser.kt │ │ ├── AppJarAntlr4Visitor.kt │ │ ├── AppJarHelper.kt │ │ └── AppJarInfo.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── appjar/ │ │ └── AppJarParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-arithmetic-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── antlr4/ │ │ │ └── arithmetic/ │ │ │ └── Arithmetic.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── arithmetic/ │ │ ├── AbstractArithParser.kt │ │ ├── ArithmeticAntlr4Visitor.kt │ │ ├── ArithmeticHelper.kt │ │ └── Data.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── arithmetic/ │ │ └── ArithmetricParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-common-parser/ │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── common/ │ │ └── antlr4/ │ │ ├── AntlrCaches.java │ │ ├── Origin.java │ │ ├── ParseErrorListener.java │ │ ├── ParseException.java │ │ ├── ParserUtils.java │ │ └── UpperCaseCharStream.java │ └── kotlin/ │ └── io/ │ └── github/ │ └── melin/ │ └── superior/ │ └── common/ │ ├── AlterActionType.kt │ ├── PrivilegeType.kt │ ├── SQLParserException.kt │ ├── SqlType.kt │ ├── StatementType.kt │ ├── TableType.kt │ ├── relational/ │ │ ├── AnalyzeTable.kt │ │ ├── DefaultStatement.kt │ │ ├── FunctionId.kt │ │ ├── ProcedureId.kt │ │ ├── SchemaId.kt │ │ ├── Statement.kt │ │ ├── TableId.kt │ │ ├── abs/ │ │ │ ├── AbsDatabaseStatement.kt │ │ │ └── AbsTableStatement.kt │ │ ├── alter/ │ │ │ ├── AlterAction.kt │ │ │ ├── AlterActions.kt │ │ │ ├── AlterDatabase.kt │ │ │ ├── AlterDatabaseActions.kt │ │ │ ├── AlterMaterializedView.kt │ │ │ ├── AlterTable.kt │ │ │ ├── AlterView.kt │ │ │ ├── DeltaAlterActions.kt │ │ │ └── IcebergAlterActions.kt │ │ ├── common/ │ │ │ ├── AddResourceStatement.kt │ │ │ ├── CallProcedure.kt │ │ │ ├── CancelExport.kt │ │ │ ├── CommentStatement.kt │ │ │ ├── DescModel.kt │ │ │ ├── ListResourceStatement.kt │ │ │ ├── ReSetStatement.kt │ │ │ ├── RefreshMaterializedView.kt │ │ │ ├── RemoveResourceStatement.kt │ │ │ ├── SetStatement.kt │ │ │ ├── ShowStatement.kt │ │ │ ├── SyncStatement.kt │ │ │ └── UseStatement.kt │ │ ├── create/ │ │ │ ├── CreateCatalog.kt │ │ │ ├── CreateDatabase.kt │ │ │ ├── CreateFunction.kt │ │ │ ├── CreateMaterializedView.kt │ │ │ ├── CreateProcedure.kt │ │ │ ├── CreateSchema.kt │ │ │ ├── CreateTable.kt │ │ │ ├── CreateTableAsSelect.kt │ │ │ ├── CreateTableLike.kt │ │ │ └── CreateView.kt │ │ ├── delta/ │ │ │ ├── OptimizeTable.kt │ │ │ └── VacuumTable.kt │ │ ├── dml/ │ │ │ ├── DeleteTable.kt │ │ │ ├── InsertFiles.kt │ │ │ ├── InsertMode.kt │ │ │ ├── InsertMultiTable.kt │ │ │ ├── InsertTable.kt │ │ │ ├── MergeTable.kt │ │ │ ├── QueryStmt.kt │ │ │ └── UpdateTable.kt │ │ ├── drop/ │ │ │ ├── DropCatalog.kt │ │ │ ├── DropDatabase.kt │ │ │ ├── DropFunction.kt │ │ │ ├── DropMaterializedView.kt │ │ │ ├── DropProcedure.kt │ │ │ ├── DropSchema.kt │ │ │ ├── DropSequence.kt │ │ │ ├── DropTable.kt │ │ │ └── DropView.kt │ │ ├── enums.kt │ │ ├── io/ │ │ │ ├── AlterLoadTable.kt │ │ │ ├── CancelLoadTable.kt │ │ │ ├── ExportTable.kt │ │ │ └── LoadTable.kt │ │ └── table/ │ │ ├── ColumnRel.kt │ │ ├── RepairTable.kt │ │ └── TruncateTable.kt │ ├── type/ │ │ ├── AbsDataTimeType.kt │ │ ├── AbsNumericType.kt │ │ ├── AbsStringType.kt │ │ ├── AbsType.kt │ │ └── Type.kt │ └── util/ │ ├── CommonUtils.kt │ └── DateUtils.kt ├── superior-dameng-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── dameng/ │ │ │ └── antlr4/ │ │ │ ├── DmSqlLexer.g4 │ │ │ └── DmSqlParser.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── dameng/ │ │ ├── AbstractSqlParser.kt │ │ ├── DmSqlAntlr4Visitor.kt │ │ └── DmSqlHelper.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── dameng/ │ │ ├── DmSqlParserDdlTest.kt │ │ ├── DmSqlParserDmlTest.kt │ │ └── DmSqlProcedureParserTest.kt │ └── resources/ │ ├── insert.sql │ └── log4j2.xml ├── superior-flink-parser/ │ ├── README.md │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── flink/ │ │ │ └── antlr4/ │ │ │ ├── FlinkSqlLexer.g4 │ │ │ └── FlinkSqlParser.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── flink/ │ │ ├── AbstractSqlParser.kt │ │ ├── FlinkSqlAntlr4Visitor.kt │ │ └── FlinkSqlHelper.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── flink/ │ │ ├── FlinkCheckSql.kt │ │ ├── FlinkSqlParserDdlTest.kt │ │ └── FlinkSqlParserDmlTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-mysql-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── mysql/ │ │ │ └── antlr4/ │ │ │ ├── MySqlLexer.g4 │ │ │ └── MySqlParser.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── mysql/ │ │ ├── AbstractSqlParser.kt │ │ ├── MySqlAntlr4Visitor.kt │ │ ├── MySqlHelper.kt │ │ └── type/ │ │ ├── JsonType.kt │ │ ├── datetime.kt │ │ ├── numeric.kt │ │ └── string.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── mysql/ │ │ ├── MySqlParserDdlTest.kt │ │ ├── MySqlParserDmlTest.kt │ │ └── MySqlProcedureParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-oracle-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── oracle/ │ │ │ └── antlr4/ │ │ │ ├── OracleLexer.g4 │ │ │ └── OracleParser.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── oracle/ │ │ │ └── antlr4/ │ │ │ ├── OracleLexerBase.java │ │ │ └── OracleParserBase.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── oracle/ │ │ ├── AbstractSqlParser.kt │ │ ├── OracleSqlAntlr4Visitor.kt │ │ └── OracleSqlHelper.kt │ └── test/ │ ├── java/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── oracle/ │ │ ├── OracleProcessParserTest.kt │ │ ├── OracleSqlParserDdlTest.kt │ │ └── OracleSqlParserDmlTest.kt │ └── resources/ │ ├── insert.sql │ └── log4j2.xml ├── superior-postgres-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── postgre/ │ │ │ └── antlr4/ │ │ │ ├── PostgreSqlLexer.g4 │ │ │ └── PostgreSqlParser.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── postgre/ │ │ │ └── antlr4/ │ │ │ ├── LexerDispatchingErrorListener.java │ │ │ ├── ParserDispatchingErrorListener.java │ │ │ ├── PostgreSqlLexerBase.java │ │ │ └── PostgreSqlParserBase.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── postgre/ │ │ ├── AbstractSqlParser.kt │ │ ├── PostgreSqlAntlr4Visitor.kt │ │ ├── PostgreSqlHelper.kt │ │ ├── relational/ │ │ │ └── CreatePartitionTable.kt │ │ └── type/ │ │ ├── BooleanType.kt │ │ ├── JsonType.kt │ │ ├── datetime.kt │ │ ├── numeric.kt │ │ └── string.kt │ └── test/ │ ├── java/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── postgre/ │ │ ├── PostgreSqlParserDdlTest.kt │ │ ├── PostgreSqlParserDmlTest.kt │ │ └── PostgreSqlProcessParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-presto-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── presto/ │ │ │ └── antlr4/ │ │ │ └── PrestoSqlBase.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── presto/ │ │ │ └── CaseInsensitiveStream.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── presto/ │ │ ├── AbstractSqlParser.kt │ │ ├── PrestoSqlAntlr4Visitor.kt │ │ └── PrestoSqlHelper.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── presto/ │ │ └── PrestoSqlParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-redshift-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── redshift/ │ │ │ └── antlr4/ │ │ │ ├── RedshiftLexer.g4 │ │ │ └── RedshiftParser.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── redshift/ │ │ │ └── antlr4/ │ │ │ ├── LexerDispatchingErrorListener.java │ │ │ ├── ParserDispatchingErrorListener.java │ │ │ ├── RedshiftLexerBase.java │ │ │ └── RedshiftParserBase.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── postgre/ │ │ ├── AbstractSqlParser.kt │ │ ├── RedshiftSqlAntlr4Visitor.kt │ │ ├── RedshiftSqlHelper.kt │ │ ├── relational/ │ │ │ └── CreatePartitionTable.kt │ │ └── type/ │ │ ├── BooleanType.kt │ │ ├── JsonType.kt │ │ ├── datetime.kt │ │ ├── numeric.kt │ │ └── string.kt │ └── test/ │ ├── java/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── postgre/ │ │ ├── RedshiftSqlParserDdlTest.kt │ │ ├── RedshiftSqlParserDmlTest.kt │ │ └── RedshiftSqlProcessParserTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-spark-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── spark/ │ │ │ └── antlr4/ │ │ │ ├── SparkSqlLexer.g4 │ │ │ ├── SparkSqlParser.g4 │ │ │ ├── SparkStreamSqlLexer.g4 │ │ │ └── SparkStreamSqlParser.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── spark/ │ │ │ └── SparkSqlPostProcessor.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── spark/ │ │ ├── AbstractSparkStreamSqlParser.kt │ │ ├── AbstractSqlParser.kt │ │ ├── SparkSqlAntlr4Visitor.kt │ │ ├── SparkSqlHelper.kt │ │ ├── SparkStreamSqlAntlr4Visitor.kt │ │ ├── SparkStreamSqlHelper.kt │ │ └── relational/ │ │ ├── CallHelp.kt │ │ ├── CreateFileView.kt │ │ ├── CreateTempViewUsing.kt │ │ ├── DataTunnelExpr.kt │ │ ├── DataTunnelHelp.kt │ │ ├── DistCpExpr.kt │ │ ├── LoadData.kt │ │ ├── MergeFileData.kt │ │ ├── RefreshStatement.kt │ │ └── cache.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── spark/ │ │ ├── DeltaSqlExtensionsTest.kt │ │ ├── IcebergSqlExtensionsTest.kt │ │ ├── SparkSqlParserTest.kt │ │ └── SparkStreamSqlParserTest.kt │ └── resources/ │ ├── demo.sql │ └── log4j2.xml ├── superior-sqlserver-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── sqlserver/ │ │ │ └── antlr4/ │ │ │ ├── SqlServerLexer.g4 │ │ │ └── SqlServerParser.g4 │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── sqlserver/ │ │ ├── AbstractSqlParser.kt │ │ ├── SqlServerAntlr4Visitor.kt │ │ └── SqlServerHelper.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── sqlserver/ │ │ ├── SqlServerParserDdlTest.kt │ │ └── SqlServerParserDmlTest.kt │ └── resources/ │ └── log4j2.xml ├── superior-starrocks-parser/ │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── antlr4/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── starrocks/ │ │ │ └── antlr4/ │ │ │ ├── StarRocksLexer.g4 │ │ │ └── StarRocksParser.g4 │ │ ├── java/ │ │ │ └── io/ │ │ │ └── github/ │ │ │ └── melin/ │ │ │ └── superior/ │ │ │ └── parser/ │ │ │ └── starrocks/ │ │ │ ├── NodePosition.java │ │ │ ├── ParsingException.java │ │ │ ├── PostProcessListener.java │ │ │ └── SqlModeHelper.java │ │ └── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── starrocks/ │ │ ├── AbstractSqlParser.kt │ │ ├── StarRocksAntlr4Visitor.kt │ │ ├── StarRocksHelper.kt │ │ └── relational/ │ │ ├── AlterRoutineLoad.kt │ │ ├── CancelRefreshMaterializedView.kt │ │ ├── CreateRoutineLoad.kt │ │ ├── DropTask.kt │ │ ├── PauseRoutineLoad.kt │ │ ├── ResumeRoutineLoad.kt │ │ ├── StopRoutineLoad.kt │ │ └── SubmitTask.kt │ └── test/ │ ├── kotlin/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── starrocks/ │ │ ├── StarRocksSqlParserDdlTest.kt │ │ ├── StarRocksSqlParserDmlTest.kt │ │ ├── StarRocksSqlParserLoadAndExportTest.kt │ │ └── StarRocksSqlParserRoutineLoadTest.kt │ └── resources/ │ └── log4j2.xml └── superior-trino-parser/ ├── pom.xml └── src/ ├── main/ │ ├── antlr4/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── trino/ │ │ └── antlr4/ │ │ └── TrinoSqlBase.g4 │ ├── java/ │ │ └── io/ │ │ └── github/ │ │ └── melin/ │ │ └── superior/ │ │ └── parser/ │ │ └── trino/ │ │ └── CaseInsensitiveStream.java │ └── kotlin/ │ └── io/ │ └── github/ │ └── melin/ │ └── superior/ │ └── parser/ │ └── trino/ │ ├── AbstractSqlParser.kt │ ├── TrinoSqlAntlr4Visitor.kt │ └── TrinoSqlHelper.kt └── test/ ├── kotlin/ │ └── io/ │ └── github/ │ └── melin/ │ └── superior/ │ └── parser/ │ └── trino/ │ └── TrinoSqlParserTest.kt └── resources/ └── log4j2.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Created by .ignore support plugin (hsz.mobi) target .idea superior-sql-parser.iml metastore_db derby.log .DS_Store gen *.tokens *.iml ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2022 Ververica Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ ## 介绍 基于 antlr4 的多种数据库SQL解析器,获取SQL中元数据,可用于数据平台产品中的多个场景:ddl语句提取元数据、sql 权限校验、表级血缘、sql语法校验等场景。支持spark、flink、gauss、starrocks、Oracle、MYSQL、Postgresql,sqlserver,、db2等 ```xml io.github.melin.superior superior-[spark|presto|mysql|oracle|...]-parser 4.0.22 ``` ## Build ``` export GPG_TTY=$(tty) mvn clean deploy -Pdeploy ``` ### API 每个数据库SQL 提供 Helper 类,Helper 方法提供四个方法: ```agsl 1. parseStatement(String sql) // 解析单个完整sql a. ddl: 获取ddl 详细信息。例如:数据库执行完ddl以后,解析ddl,获取到相关信息,同步到元数据信息。 b. dml: 获取sql中使用到的表,用于构建表级血缘,或者校验表权限。 2. parseMultiStatement(String sql) // 解析多个完整sql,支持空格、换行、分号分隔 3. splitSql(String sql) // sql 文本包含多个完整sql,方法用于分隔sql语句,支持空格、换行、分号分隔 4. checkSqlSyntax(String sql) // 验证单个完整sql语法是否正确 5. sqlKeywords() // 获取sql 关键字,主要用于sql editor 关键字提示 ``` ## Example ```kotlin // Spark SQL val sql = "select bzdys, bzhyyh, bzdy, week, round((bzdy-bzdys)*100/bzdys, 2) " + "from (select lag(bzdy) over (order by week) bzdys, bzhyyh, bzdy, week " + "from (select count(distinct partner_code) bzhyyh, count(1) bzdy, week from tdl_dt2x_table)) limit 111" val statement = SparkSQLHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("tdl_dt2x_table", statement.inputTables.get(0).tableName) Assert.assertEquals(111, statement.limit) } else { Assert.fail() } // Spark Jar val sql = """ set spark.shuffle.compress=true;set spark.rdd.compress=true; set spark.driver.maxResultSize=3g; set spark.serializer=org.apache.spark.serializer.KryoSerializer; set spark.kryoserializer.buffer.max=1024m; set spark.kryoserializer.buffer=256m; set spark.network.timeout=300s; examples-jar-with-dependencies.jar imei_test.euSaveHBase gaea_offline:account_mobile sh md shda.interest_radar_mobile_score_dt 20180318 /xiaoyong.fu/sh/mobile/loan 400 '%7B%22job_type%22=' --jar """; val statementDatas = JobTaskHelper.parseStatement(sql) Assert.assertEquals(8, statementDatas.size) var statementData = statementDatas.get(7) var statement = statementData.statement if (statement is JobData) { Assert.assertEquals(StatementType.JOB, statement.statementType) Assert.assertEquals("createHfile-1.2-SNAPSHOT-jar-with-dependencies.jar", statement.resourceName) Assert.assertEquals("imei_test.euSaveHBase", statement.className) Assert.assertEquals("/xiaoyong.fu/sh/mobile/loan", statement.params?.get(5)) Assert.assertEquals("400", statement.params?.get(6)) Assert.assertEquals("%7B%22job_type%22=", statement.params?.get(7)) Assert.assertEquals("--jar", statement.params?.get(8)) } else { Assert.fail() } // MySQL val sql = "insert into bigdata.user select * from users a left outer join address b on a.address_id = b.id" val statement = MySQLHelper.parseStatement(sql) if(statement is QueryStmt) { Assert.assertEquals(StatementType.INSERT_SELECT, statement.statementType) Assert.assertEquals("bigdata", statement.outpuTables.get(0).databaseName) Assert.assertEquals("user", statement.outpuTables.get(0).tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } // Postgres val sql = """ select a.* from datacompute1.datacompute.dc_job a left join datacompute1.datacompute.dc_job_scheduler b on a.id=b.job_id """.trimIndent() val statement = PostgreSQLHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } ``` ## 支持数据库 1. [MySQL](https://github.com/antlr/grammars-v4/tree/master/sql/mysql) 2. [PrestoSQL](https://github.com/prestosql/presto/tree/master/presto-parser/src/main/antlr4/io/prestosql/sql/parser) 3. [PostgreSQL](https://github.com/pgcodekeeper/pgcodekeeper/tree/master/apgdiff/antlr-src) 4. [Spark 3.x](https://github.com/apache/spark/tree/master/sql/catalyst/src/main/antlr4/org/apache/spark/sql/catalyst/parser) 5. [Sql Server](https://github.com/antlr/grammars-v4/tree/master/sql/tsql) 6. [StarRocks](https://github.com/StarRocks/starrocks/tree/main/fe/fe-core/src/main/java/com/starrocks/sql/parser) 7. [Oracle](https://github.com/antlr/grammars-v4/tree/master/sql/plsql) 8. [OceanBase](https://github.com/oceanbase/odc/tree/main/libs/ob-sql-parser) 9. [Flink SQL / Flink CDC SQL](https://github.com/DTStack/dt-sql-parser/tree/main/src/grammar/flinksql) ## 相关项目 1. https://gitee.com/melin/bee 2. https://github.com/melin/sqlflow/ 字段血缘解析 3. https://github.com/melin/superior-sql-formatter spark sql 代码格式化 4. https://github.com/melin/datatunnel spark 数据同步工具 5. https://github.com/melin/flink-jobserver 6. https://github.com/melin/spark-jobserver ================================================ FILE: pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 pom Superior SQL Parser Superior SQL Parser superior-common-parser superior-arithmetic-parser superior-appjar-parser superior-spark-parser superior-mysql-parser superior-postgres-parser superior-trino-parser superior-presto-parser superior-sqlserver-parser superior-flink-parser superior-oracle-parser superior-dameng-parser superior-starrocks-parser superior-redshift-parser 8 8 UTF-8 true 2.3.20 4.9.3 2.0.17 2.25.3 3.20.0 2.21.0 org.antlr antlr4-runtime ${antlr4.version} org.jetbrains.kotlin * org.jetbrains.kotlin kotlin-stdlib ${kotlin.version} org.apache.commons commons-lang3 ${commons-lang3.version} com.google.guava guava 33.4.0-jre provided junit junit 4.13.2 test commons-io commons-io ${commons-io.version} test org.slf4j slf4j-api ${slf4j.version} org.apache.logging.log4j log4j-core ${log4j.version} test org.apache.logging.log4j log4j-slf4j-impl ${log4j.version} test org.apache.maven.plugins maven-javadoc-plugin 3.12.0 true 1024 UTF-8 protected true false none bundle-sources jar package org.apache.maven.plugins maven-surefire-plugin 3.5.4 org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} true compile compile process-sources ${project.basedir}/src/main/kotlin ${project.basedir}/src/main/java ${project.build.directory}/generated-sources/antlr4 test-compile test-compile ${project.basedir}/src/test/kotlin ${project.basedir}/src/test/java org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 UTF-8 default-compile none default-testCompile none java-compile compile compile java-test-compile testCompile test-compile org.antlr antlr4-maven-plugin ${antlr4.version} true antlr antlr4 generate-sources org.apache.maven.plugins maven-release-plugin forked-path false -Psonatype-oss-release org.apache.maven.plugins maven-source-plugin 3.4.0 true true true attach-sources jar deploy org.apache.maven.plugins maven-gpg-plugin sign-artifacts sign verify org.sonatype.central central-publishing-maven-plugin 0.10.0 true superior-sql-parser-${project.version} central true https://github.com/melin/superior-sql-parser The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo melin libinsong1204@gmail.com https://github.com/melin/superior-sql-parser scm:git:https://github.com/melin/superior-sql-parser.git scm:git:https://github.com/melin/superior-sql-parser.git https://github.com/melin/superior-sql-parser gitee https://github.com/melin/superior-sql-parser/issues ================================================ FILE: superior-appjar-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-appjar-parser superior-appjar-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-appjar-parser/src/main/antlr4/io/github/melin/superior/parser/job/antlr4/AppJarLexer.g4 ================================================ lexer grammar AppJarLexer; channels { DCSTREAMCOMMENT, ERRORCHANNEL } // SKIP SPACE: [ \t\r\n]+ -> channel(HIDDEN); SPEC_MYSQL_COMMENT: '/*!' .+? '*/' -> channel(DCSTREAMCOMMENT); COMMENT_INPUT: '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: ( ('-- ' | '#') ~[\r\n]* ('\r'? '\n' | EOF) | '--' ('\r'? '\n' | EOF) ) -> channel(HIDDEN); SET: 'SET'; RESET: 'RESET'; STAR: '*'; DIVIDE: '/'; MODULE: '%'; PLUS: '+'; MINUS: '-'; // Operators. Comparation EQUAL_SYMBOL: '='; GREATER_SYMBOL: '>'; LESS_SYMBOL: '<'; EXCLAMATION_SYMBOL: '!'; // Operators. Bit BIT_NOT_OP: '~'; BIT_OR_OP: '|'; BIT_AND_OP: '&'; BIT_XOR_OP: '^'; // Constructors symbols DOT: '.'; LR_BRACKET: '('; RR_BRACKET: ')'; COMMA: ','; SEMI: ';'; DOT_ID: '.' ID_LITERAL; ID: ID_LITERAL; REVERSE_QUOTE_ID: '`' ~'`'+ '`'; STRING_LITERAL: DQUOTA_STRING | SQUOTA_STRING; fragment ID_LITERAL: [A-Z_$0-9,:-]*; fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"'; fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\''; ERROR_RECONGNIGION: . -> channel(ERRORCHANNEL); ================================================ FILE: superior-appjar-parser/src/main/antlr4/io/github/melin/superior/parser/job/antlr4/AppJarParser.g4 ================================================ parser grammar AppJarParser; options { tokenVocab=AppJarLexer; } rootx : jobTasks? EOF ; jobTasks : (jobTask SEMI | emptyStatement)* (jobTask (SEMI)? | emptyStatement) ; jobTask : setStatement | resetStatement | jobStatement ; jobStatement : resourceNameExpr classNameExpr paramsExpr? ; resourceNameExpr : ID (DOT_ID)* | fileDir ; classNameExpr : ID (DOT_ID)* ; paramsExpr : paramExpr (paramExpr)* ; paramExpr : ID (DOT_ID)* | fileDir | ID DOT_ID* ('/' '/'? ID DOT_ID*)* | STRING_LITERAL ; fileDir : '/' ID DOT_ID* ('/' (ID DOT_ID* | '*'))* '/'? ; setStatement : SET keyExpr EQUAL_SYMBOL value=valueExpr ; resetStatement : RESET keyExpr ; keyExpr : ID (DOT_ID)* ; valueExpr : word (word)* ; word : ID | DOT_ID | SET | RESET | STAR | DIVIDE | MODULE | PLUS | MINUS | EQUAL_SYMBOL | GREATER_SYMBOL | LESS_SYMBOL | EXCLAMATION_SYMBOL | BIT_NOT_OP | BIT_OR_OP | BIT_AND_OP | BIT_XOR_OP | LR_BRACKET | RR_BRACKET | COMMA | STRING_LITERAL ; emptyStatement : SEMI ; ================================================ FILE: superior-appjar-parser/src/main/kotlin/io/github/melin/superior/parser/appjar/AbstractJarParser.kt ================================================ package io.github.melin.superior.parser.appjar import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.job.antlr4.AppJarParser import java.util.concurrent.atomic.AtomicReference object AbstractJarParser { private val parserCaches = AtomicReference(AntlrCaches(AppJarParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: AppJarParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(AppJarParser._ATN)) } } ================================================ FILE: superior-appjar-parser/src/main/kotlin/io/github/melin/superior/parser/appjar/AppJarAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.appjar import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.common.ReSetStatement import io.github.melin.superior.common.relational.common.SetStatement import io.github.melin.superior.parser.job.antlr4.AppJarParser import io.github.melin.superior.parser.job.antlr4.AppJarParserBaseVisitor import org.apache.commons.lang3.StringUtils /** Created by binsong.li on 2018/3/31 下午1:44 */ class AppJarAntlr4Visitor : AppJarParserBaseVisitor() { private var command: String? = null private val jobStmts = ArrayList() override fun visitJobTask(ctx: AppJarParser.JobTaskContext): Statement { val jobStmt = super.visitJobTask(ctx) val sql = source(ctx) jobStmt.setSql(sql) jobStmts.add(jobStmt) return jobStmt } override fun visitJobStatement(ctx: AppJarParser.JobStatementContext): Statement { val resourceName = ctx.resourceNameExpr().text val className = ctx.classNameExpr().text val params: ArrayList = arrayListOf() if (ctx.paramsExpr() != null) { ctx.paramsExpr().children.forEach { item -> val param = item as AppJarParser.ParamExprContext var value = source(param) if (StringUtils.startsWith(value, "/")) { // 解决连续多个文件路径,不能正确解析 value = replaceWhitespace(value) params.addAll(StringUtils.split(value, " ")) } else { value = CommonUtils.cleanQuote(value) params.add(value) } } } return AppJarInfo(resourceName, className, params) } override fun visitSetStatement(ctx: AppJarParser.SetStatementContext): Statement { val key = ctx.keyExpr().text val value = CommonUtils.cleanQuote(source(ctx.value)) return SetStatement(key, value) } override fun visitResetStatement(ctx: AppJarParser.ResetStatementContext): Statement { val key = ctx.keyExpr().text return ReSetStatement(key) } private fun replaceWhitespace(str: String): String { val len = str.length if (len > 0) { val dest = CharArray(len) var destPos = 0 for (i in 0 until len) { val c = str[i] if (!Character.isWhitespace(c)) { dest[destPos++] = c } else { dest[destPos++] = ' ' } } return String(dest, 0, destPos) } return str } fun getJobStmts(): ArrayList { return jobStmts } fun setCommand(command: String) { this.command = command } } ================================================ FILE: superior-appjar-parser/src/main/kotlin/io/github/melin/superior/parser/appjar/AppJarHelper.kt ================================================ package io.github.melin.superior.parser.appjar import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.job.antlr4.AppJarLexer import io.github.melin.superior.parser.job.antlr4.AppJarParser import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by binsong.li on 2018/3/31 下午1:47 */ object AppJarHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until AppJarLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = AppJarLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): ArrayList { val trimCmd = StringUtils.trim(command) val charStream = UpperCaseCharStream(CharStreams.fromString(trimCmd)) val lexer = AppJarLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = AppJarParser(tokenStream) AbstractJarParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.interpreter.predictionMode = PredictionMode.SLL val cmdVisitor = AppJarAntlr4Visitor() cmdVisitor.setCommand(trimCmd) try { try { // first, try parsing with potentially faster SLL mode cmdVisitor.visit(parser.jobTasks()) return cmdVisitor.getJobStmts() } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL cmdVisitor.visit(parser.jobTasks()) return cmdVisitor.getJobStmts() } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(trimCmd) } } finally { val releaseAntlrCache = System.getenv(RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractJarParser.refreshParserCaches() } } } } ================================================ FILE: superior-appjar-parser/src/main/kotlin/io/github/melin/superior/parser/appjar/AppJarInfo.kt ================================================ package io.github.melin.superior.parser.appjar import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class AppJarInfo(val resourceName: String, val className: String, val params: List?) : Statement() { override val statementType = StatementType.APP_JAR override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-appjar-parser/src/test/kotlin/io/github/melin/superior/parser/appjar/AppJarParserTest.kt ================================================ package io.github.melin.superior.parser.appjar import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.common.ReSetStatement import io.github.melin.superior.common.relational.common.SetStatement import org.junit.Assert import org.junit.Test /** Created by binsong.li on 2018/3/31 下午1:59 */ class AppJarParserTest { @Test fun setConfigTest1() { val sql = """ set flink.test = 'hello world'; set flink.test = setsd,sd,resr; set flink.test = hello world; set flink.test = hello-world; set flink.test = hello $\{usename} test; #set flink.test = hello comment; set flink.test = hello 'test' world; set flink.test = hello "test" world; set flink.test = hdfs://user/hive; set flink.test = 12,12; set flink.test = 3.45; set flink.test = ibdex.json; reset flink.test; set flink.test = dw.eset_sdfe_sd; set flink.test = demo.test; set flink.test = dsd(id)%=2; tet_test-demo_1.23-sdfd.jar com.example.Demo1 param1 param2 'hello \n world' 'hdfs://user/hive' '{"user": "binsong.li", address: "hangzhou" }' /user/jars/* --jars /user/jars/flink.jar """ val statements = AppJarHelper.parseStatement(sql) Assert.assertEquals(16, statements.size) var statement = statements.get(0) if (statement is SetStatement) { Assert.assertEquals(StatementType.SET, statement.statementType) Assert.assertEquals("flink.test", statement.key) Assert.assertEquals("hello world", statement.value) } else { Assert.fail() } var setCount = 0 statements.filter { it.statementType == StatementType.SET }.forEach { setCount = setCount + 1 } Assert.assertEquals(14, setCount) statement = statements.get(11) if (statement is ReSetStatement) { Assert.assertEquals(StatementType.RESET, statement.statementType) Assert.assertEquals("flink.test", statement.key) } else { Assert.fail() } statement = statements.get(15) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("tet_test-demo_1.23-sdfd.jar", statement.resourceName) Assert.assertEquals("com.example.Demo1", statement.className) Assert.assertEquals(8, statement.params?.size) Assert.assertEquals("/user/jars/*", statement.params?.get(5)) } else { Assert.fail() } } @Test fun setConfigTest2() { val sql = "demo.jar com.example.Demo 'hello \"test\" world' param2 \n param3" val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(1, statementDatas.size) val statement = statementDatas.get(0) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("demo.jar", statement.resourceName) Assert.assertEquals("com.example.Demo", statement.className) Assert.assertEquals(3, statement.params?.size) Assert.assertEquals("hello \"test\" world", statement.params?.get(0)) Assert.assertEquals("param3", statement.params?.get(2)) } else { Assert.fail() } } @Test fun setConfigTest3() { val sql = """ set spark.yarn.queue=newoffline; set spark.sql.autoBroadcastJoinThreshold=40485760; set spark.executor.memory=8g; set spark.sql.hive.convertMetastoreParquet=true ; set spark.driver.maxResultSize=4g; set spark.driver.memory=10g; set spark.psi.ds=20180312; set spark.psi.dstTable=dw.index_psi_dt; set spark.psi.dims=idnumber; set spark.psi.num=0; set spark.psi.parNum=2; set spark.indexPSI.type=2; set spark.metrics.indexFile=index-mobile.json; psi_new_calculate_metrics-1.1-SNAPSHOT-jar-with-dependencies.jar com.example.dw.psi.StartDCJob 1,3,sd,qw """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(14, statementDatas.size) val statement = statementDatas.get(13) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals( "psi_new_calculate_metrics-1.1-SNAPSHOT-jar-with-dependencies.jar", statement.resourceName ) Assert.assertEquals("com.example.dw.psi.StartDCJob", statement.className) Assert.assertEquals("1,3,sd,qw", statement.params?.get(0)) } else { Assert.fail() } } @Test fun setConfigTest4() { val sql = """ set spark.yarn.queue=newoffline; set spark.dynamicAllocation.maxExecutors=100; set spark.driver.maxResultSize=30g; set spark.driver.memory=15g; set spark.executor.instances=80; set spark.executor.cores=5; set spark.executor.memory=30g; set spark.sql.shuffle.partitions=5000; set spark.shuffle.io.maxRetries=60; set spark.shuffle.io.retryWait=60s; set spark.metrics.indexFile=index-mobile.json; set spark.metrics.indexInputTable=dw.dwa_mobile_model_dt; set spark.metrics.indexOutputTable=dw.app_mdl_mobile_index_dt; set spark.metrics.indexWaitFullPartition=true; set spark.metrics.indexHashWhere=abs(hash(mobile))%4=3; new_calculate_metrics-100-SNAPSHOT-jar-with-dependencies.jar com.example.dw.index.StartDCJob IndexOffline 2018-03-18 """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(16, statementDatas.size) val statement = statementDatas.get(15) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("new_calculate_metrics-100-SNAPSHOT-jar-with-dependencies.jar", statement.resourceName) Assert.assertEquals("com.example.dw.index.StartDCJob", statement.className) Assert.assertEquals("2018-03-18", statement.params?.get(1)) } else { Assert.fail() } } @Test fun setConfigTest5() { val sql = """ set spark.shuffle.compress=true;set spark.rdd.compress=true; set spark.driver.maxResultSize=3g; set spark.serializer=org.apache.spark.serializer.KryoSerializer; set spark.kryoserializer.buffer.max=1024m; set spark.kryoserializer.buffer=256m; set spark.network.timeout=300s; createHfile-1.2-SNAPSHOT-jar-with-dependencies.jar imei_test.euSaveHBase gaea_offline:account_mobile sh md shda.interest_radar_mobile_score_dt 20180318 /xiaoyong.fu/sh/mobile/loan 400 '%7B%22job_type%22=' --jar """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(8, statementDatas.size) val statement = statementDatas.get(7) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("createHfile-1.2-SNAPSHOT-jar-with-dependencies.jar", statement.resourceName) Assert.assertEquals("imei_test.euSaveHBase", statement.className) Assert.assertEquals("/xiaoyong.fu/sh/mobile/loan", statement.params?.get(5)) Assert.assertEquals("400", statement.params?.get(6)) Assert.assertEquals("%7B%22job_type%22=", statement.params?.get(7)) Assert.assertEquals("--jar", statement.params?.get(8)) } else { Assert.fail() } } @Test fun setConfigTest6() { val sql = """ set spark.toMysql.url=jdbc:mysql://192.168.40.110:3306/data_quality;set spark.toMysql.user=dq; set spark.toMysql.password=0nlpSvpgC5leeKuw; set spark.screenJob.screenType=3; set spark.screenJob.test=true; set spark.screenTool.srcTable=default.activity_flat; set spark.toMysql.tableName=province; set spark.toMysql.field=creditProvinceAmountJson,creditForeignAmount,creditCityAmountJson,zhejiangFraud,fraudProvinceAmountJson; province-1.0-SNAPSHOT-jar-with-dependencies.jar com.example.screen_dc.ScreenJob /xiaoyong.fu/2017-22-03/sh/mobile/loan/ --write-private-test; province-1.0-SNAPSHOT-jar-with-dependencies.jar com.example.screen_dc.ScreenJob /xiaoyong.fu/2017-22-03/sh/mobile/loan/ --write-private-test """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(10, statementDatas.size) val statement = statementDatas.get(9) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("province-1.0-SNAPSHOT-jar-with-dependencies.jar", statement.resourceName) Assert.assertEquals("com.example.screen_dc.ScreenJob", statement.className) Assert.assertEquals("/xiaoyong.fu/2017-22-03/sh/mobile/loan/", statement.params?.get(0)) Assert.assertEquals("--write-private-test", statement.params?.get(1)) } else { Assert.fail() } } @Test fun setConfigTest7() { val sql = """ raph.edgesSNAPSHOT.eventType.jar com.example.graph.PhoenixCSVWriterJob graph_csv_s_2 /user/datacompute/bigdata/data/shuoyi.zhao/graph_csv_s_2/2018/12/day_12 /user/datacompute/bigdata/data/shuoyi.zhao/graph_csv_s_new_2/Loan/2018/12/day_12 500 Loan hdfs://192.168.40.37,hdfs://192.168.39.133 hdfs://192.168.40.37,hdfs://192.168.39.130; """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(1, statementDatas.size) val statement = statementDatas.get(0) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("raph.edgesSNAPSHOT.eventType.jar", statement.resourceName) Assert.assertEquals("com.example.graph.PhoenixCSVWriterJob", statement.className) Assert.assertEquals("hdfs://192.168.40.37,hdfs://192.168.39.130", statement.params?.get(6)) } else { Assert.fail() } } @Test fun setConfigTest8() { val sql = """ set spark.app.name=sparkAppName; set spark.memory.storageFraction=0.1; set spark.memory.fraction=0.95; set spark.memory.useLegacyMode=true; set master=yarn-cluster; /user/pontus_2.1/pontus-core-2.1.0-SNAPSHOT-fat.jar com.example.pontus.core.Engine customCmd "-j{'readerFields':[{'field':'uuid','type':'string'},{'field':'rule_detail','type':'string'}],'resourceSetting':{'spark.driver.memory':'2g','spark.pontus.writer.mapper':'2'},'reader':{'databaseName':'afraudtech','connectionType':'hive','table':'antifraud_rule_result'},'writerFields':[{'transform':'uuid','field':'uuid','type':'varchar(32)'},{'filter':'where id=\'test\'','transform':'rule_detail','field':'policy_recommendation','type':'text'}],'writer':{'dataSourceId':'364','connectionAttr':'jdbc:mysql://192.168.74.136:3306/athena','password':'6ydJDezPBLBuco+sCV6QL6XsdTN/ShtYIz1Gi3TVusw=','writeMode':'UPSERT','userName':'athena','connectionType':'mysql','table':'edison_warning_result'}}" --jars /user/pontus_2.1/* """ val statementDatas = AppJarHelper.parseStatement(sql) Assert.assertEquals(6, statementDatas.size) val statement = statementDatas.get(5) if (statement is AppJarInfo) { Assert.assertEquals(StatementType.APP_JAR, statement.statementType) Assert.assertEquals("/user/pontus_2.1/pontus-core-2.1.0-SNAPSHOT-fat.jar", statement.resourceName) Assert.assertEquals("com.example.pontus.core.Engine", statement.className) Assert.assertEquals(4, statement.params?.size) val config = """ -j{'readerFields':[{'field':'uuid','type':'string'},{'field':'rule_detail','type':'string'}],'resourceSetting':{'spark.driver.memory':'2g','spark.pontus.writer.mapper':'2'},'reader':{'databaseName':'afraudtech','connectionType':'hive','table':'antifraud_rule_result'},'writerFields':[{'transform':'uuid','field':'uuid','type':'varchar(32)'},{'filter':'where id=\'test\'','transform':'rule_detail','field':'policy_recommendation','type':'text'}],'writer':{'dataSourceId':'364','connectionAttr':'jdbc:mysql://192.168.74.136:3306/athena','password':'6ydJDezPBLBuco+sCV6QL6XsdTN/ShtYIz1Gi3TVusw=','writeMode':'UPSERT','userName':'athena','connectionType':'mysql','table':'edison_warning_result'}} """ Assert.assertEquals(config.trim(), statement.params?.get(1)) } else { Assert.fail() } } } ================================================ FILE: superior-appjar-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-arithmetic-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-arithmetic-parser superior-arithmetic-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-arithmetic-parser/src/main/antlr4/io/github/melin/superior/parser/antlr4/arithmetic/Arithmetic.g4 ================================================ grammar Arithmetic; @members { public boolean bracket_enbled = true; } arithmetic: expression EOF; expression : booleanExpression ; booleanExpression : NOT booleanExpression #logicalNot | valueExpression predicate? #predicated | left=booleanExpression operator=AND right=booleanExpression #logicalBinary | left=booleanExpression operator=OR right=booleanExpression #logicalBinary ; predicate : NOT? kind=BETWEEN lower=valueExpression AND upper=valueExpression | NOT? kind=IN '(' expression (',' expression)* ')' | NOT? kind=RLIKE pattern=valueExpression | NOT? kind=LIKE pattern=valueExpression (ESCAPE escapeChar=STRING)? | IS NOT? kind=NULL | IS NOT? kind=(TRUE | FALSE | UNKNOWN) ; valueExpression : primaryExpression #valueExpressionDefault | operator=(MINUS | PLUS | TILDE) valueExpression #arithmeticUnary | left=valueExpression operator=(ASTERISK | SLASH | PERCENT | DIV) right=valueExpression #arithmeticBinary | left=valueExpression operator=(PLUS | MINUS | CONCAT_PIPE) right=valueExpression #arithmeticBinary | left=valueExpression operator=AMPERSAND right=valueExpression #arithmeticBinary | left=valueExpression operator=HAT right=valueExpression #arithmeticBinary | left=valueExpression operator=PIPE right=valueExpression #arithmeticBinary | left=valueExpression comparisonOperator right=valueExpression #comparison ; primaryExpression : CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | CASE value=expression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | constant #constantDefault | functionName '(' (setQuantifier? argument+=expression (',' argument+=expression)*)? ')' #functionCall | identifier '->' expression #lambda | '(' identifier (',' identifier)+ ')' '->' expression #lambda | value=primaryExpression '[' index=valueExpression ']' #subscript | identifier #columnReference | '(' expression ')' #parenthesizedExpression ; comparisonOperator : EQ | NEQ | NEQJ | LT | LTE | GT | GTE | NSEQ ; whenClause : WHEN condition=expression THEN result=expression ; functionName : IDENTIFIER ; identifier : {!bracket_enbled}? IDENTIFIER | {bracket_enbled}? LBRACKET IDENTIFIER RBRACKET ; constant : NULL #nullLiteral | number #numericLiteral | booleanValue #booleanLiteral | STRING+ #stringLiteral ; setQuantifier : DISTINCT | ALL ; number : MINUS? INTEGER_VALUE #integerLiteral | MINUS? BIGINT_LITERAL #bigIntLiteral | MINUS? SMALLINT_LITERAL #smallIntLiteral | MINUS? TINYINT_LITERAL #tinyIntLiteral | MINUS? DOUBLE_LITERAL #doubleLiteral | MINUS? BIGDECIMAL_LITERAL #bigDecimalLiteral ; booleanValue : TRUE | FALSE ; STRING : '\'' ( ~('\''|'\\') | ('\\' .) )* '\'' | '"' ( ~('"'|'\\') | ('\\' .) )* '"' ; TRUE: 'TRUE'; FALSE: 'FALSE'; NULL: 'NULL'; CASE: 'CASE'; WHEN: 'WHEN'; THEN: 'THEN'; ELSE: 'ELSE'; END: 'END'; DISTINCT: 'DISTINCT'; ALL: 'ALL'; NOT: 'NOT'; AND: 'AND'; OR: 'OR'; BETWEEN: 'BETWEEN'; IN: 'IN'; RLIKE: 'RLIKE'; LIKE: 'LIKE'; IS: 'IS'; ESCAPE: 'ESCAPE'; UNKNOWN: 'UNKNOWN'; EQ : '=' | '=='; NSEQ: '<=>'; NEQ : '<>'; NEQJ: '!='; LT : '<'; LTE : '<='; GT : '>'; GTE : '>='; LBRACKET : '[' ; RBRACKET : ']' ; PLUS: '+'; MINUS: '-'; ASTERISK: '*'; SLASH: '/'; PERCENT: '%'; DIV: 'DIV'; TILDE: '~'; AMPERSAND: '&'; PIPE: '|'; CONCAT_PIPE: '||'; HAT: '^'; BIGINT_LITERAL : DIGIT+ 'L' ; SMALLINT_LITERAL : DIGIT+ 'S' ; TINYINT_LITERAL : DIGIT+ 'Y' ; INTEGER_VALUE : DIGIT+ ; IDENTIFIER : (LETTER | DIGIT | '_')+ ; fragment EXPONENT : 'E' [+-]? DIGIT+ ; fragment DECIMAL_DIGITS : DIGIT+ '.' DIGIT* | '.' DIGIT+ ; DOUBLE_LITERAL : DIGIT+ EXPONENT? 'D' | DECIMAL_DIGITS EXPONENT? 'D' ; BIGDECIMAL_LITERAL : DIGIT+ EXPONENT? 'BD' | DECIMAL_DIGITS EXPONENT? 'BD' ; fragment DIGIT : [0-9] ; fragment LETTER : [a-zA-Z] | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF ; SIMPLE_COMMENT : '--' ('\\\n' | ~[\r\n])* '\r'? '\n'? -> channel(HIDDEN) ; BRACKETED_EMPTY_COMMENT : '/**/' -> channel(HIDDEN) ; BRACKETED_COMMENT : '/*' ~[+] .*? '*/' -> channel(HIDDEN) ; WS : [ \r\n\t] + -> skip ; ================================================ FILE: superior-arithmetic-parser/src/main/kotlin/io/github/melin/superior/parser/arithmetic/AbstractArithParser.kt ================================================ package io.github.melin.superior.parser.arithmetic import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.antlr4.arithmetic.ArithmeticParser import java.util.concurrent.atomic.AtomicReference object AbstractArithParser { private val parserCaches = AtomicReference(AntlrCaches(ArithmeticParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: ArithmeticParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(ArithmeticParser._ATN)) } } ================================================ FILE: superior-arithmetic-parser/src/main/kotlin/io/github/melin/superior/parser/arithmetic/ArithmeticAntlr4Visitor.kt ================================================ package com.github.melin.superior.sql.parser.arithmetic import io.github.melin.superior.common.SQLParserException import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.antlr4.arithmetic.ArithmeticBaseVisitor import io.github.melin.superior.parser.antlr4.arithmetic.ArithmeticParser import io.github.melin.superior.parser.arithmetic.ArithmeticData import org.antlr.v4.runtime.tree.ParseTree import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/7/28 9:49 上午 */ class ArithmeticAntlr4Visitor(val bracketEnbled: Boolean) : ArithmeticBaseVisitor() { private var statement: Statement? = null private val arithmetic = ArithmeticData() override fun visit(tree: ParseTree): Statement? { super.visit(tree) if (statement == null) { throw SQLParserException("不支持的表达式") } return statement } override fun visitExpression(ctx: ArithmeticParser.ExpressionContext): Statement? { statement = arithmetic return super.visitExpression(ctx) } override fun visitIdentifier(ctx: ArithmeticParser.IdentifierContext): Statement? { val name = ctx.text if (!arithmetic.functions.contains(name)) { if (bracketEnbled) { arithmetic.variables.add(StringUtils.substringBetween(name, "[", "]")) } else { arithmetic.variables.add(name) } } return super.visitIdentifier(ctx) } override fun visitFunctionName(ctx: ArithmeticParser.FunctionNameContext): Statement? { val name = ctx.text arithmetic.functions.add(name) return super.visitFunctionName(ctx) } } ================================================ FILE: superior-arithmetic-parser/src/main/kotlin/io/github/melin/superior/parser/arithmetic/ArithmeticHelper.kt ================================================ package com.github.melin.superior.sql.parser.arithmetic import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.antlr4.arithmetic.ArithmeticLexer import io.github.melin.superior.parser.antlr4.arithmetic.ArithmeticParser import io.github.melin.superior.parser.arithmetic.AbstractArithParser import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object ArithmeticHelper { @JvmStatic fun parseStatement(command: String): Statement? { return ArithmeticHelper.parseStatement(command, true) } @JvmStatic fun parseStatement(command: String, bracketEnbled: Boolean): Statement? { val trimCmd = StringUtils.trim(command) val charStream = CharStreams.fromString(trimCmd) val lexer = ArithmeticLexer(charStream) val tokenStream = CommonTokenStream(lexer) val parser = ArithmeticParser(tokenStream) AbstractArithParser.installCaches(parser) parser.bracket_enbled = bracketEnbled parser.interpreter.predictionMode = PredictionMode.SLL val sqlVisitor = ArithmeticAntlr4Visitor(bracketEnbled) try { try { // first, try parsing with potentially faster SLL mode return sqlVisitor.visit(parser.expression()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL return sqlVisitor.visit(parser.expression()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(trimCmd) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractArithParser.refreshParserCaches() } } } } ================================================ FILE: superior-arithmetic-parser/src/main/kotlin/io/github/melin/superior/parser/arithmetic/Data.kt ================================================ package io.github.melin.superior.parser.arithmetic import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class ArithmeticData( val variables: java.util.HashSet = HashSet(), val functions: java.util.HashSet = HashSet() ) : Statement() { override val statementType = StatementType.ARITHMETIC override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-arithmetic-parser/src/test/kotlin/io/github/melin/superior/parser/arithmetic/ArithmetricParserTest.kt ================================================ package io.github.melin.superior.parser.arithmetic import com.github.melin.superior.sql.parser.arithmetic.ArithmeticHelper import io.github.melin.superior.common.StatementType import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class ArithmetricParserTest { @Test fun test0() { val sql = """ 特征1 / (特征_dd_2 - (log2(feature_12) + 特征3)) """ val statement = ArithmeticHelper.parseStatement(sql, false) Assert.assertEquals(StatementType.ARITHMETIC, statement?.statementType) if (statement is ArithmeticData) { Assert.assertEquals(4, statement.variables.toArray().size) Assert.assertEquals(1, statement.functions.size) Assert.assertEquals("log2", statement.functions.toArray().get(0)) } else { Assert.fail() } } @Test fun test1() { val sql = """ case when rand <= 12 then 1 when rand <= 23 then 2 else 3 end """ val statement = ArithmeticHelper.parseStatement(sql, false) Assert.assertEquals(StatementType.ARITHMETIC, statement?.statementType) if (statement is ArithmeticData) { Assert.assertEquals(1, statement.variables.toArray().size) Assert.assertEquals(0, statement.functions.size) } else { Assert.fail() } } @Test fun test2() { val sql = """ [特征1] / ([特征_dd_2] - (log2([feature_12]) + [特征3])) """ val statement = ArithmeticHelper.parseStatement(sql) Assert.assertEquals(StatementType.ARITHMETIC, statement?.statementType) if (statement is ArithmeticData) { Assert.assertEquals(4, statement.variables.toArray().size) Assert.assertEquals(1, statement.functions.size) Assert.assertEquals("log2", statement.functions.toArray().get(0)) } else { Assert.fail() } } } ================================================ FILE: superior-arithmetic-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-common-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-common-parser superior-common-parser ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/AntlrCaches.java ================================================ package io.github.melin.superior.common.antlr4; import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.atn.ATN; import org.antlr.v4.runtime.atn.ParserATNSimulator; import org.antlr.v4.runtime.atn.PredictionContextCache; import org.antlr.v4.runtime.dfa.DFA; public class AntlrCaches { public static final String RELEASE_ANTLR_CACHE_AFTER_PARSING = "releaseAntlrCacheAfterParsing"; private final ATN atn; private final PredictionContextCache predictionContextCache = new PredictionContextCache(); private final DFA[] decisionToDFA; public AntlrCaches(ATN atn) { this.atn = atn; this.decisionToDFA = makeDecisionToDFA(this.atn); } public void installCaches(Parser parser) { parser.setInterpreter(new ParserATNSimulator(parser, atn, decisionToDFA, predictionContextCache)); } private DFA[] makeDecisionToDFA(ATN atn) { DFA[] decisionToDFA = new DFA[atn.getNumberOfDecisions()]; for (int i = 0, len = atn.getNumberOfDecisions(); i < len; i++) { decisionToDFA[i] = new DFA(atn.getDecisionState(i), i); } return decisionToDFA; } } ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/Origin.java ================================================ package io.github.melin.superior.common.antlr4; public class Origin { private int line; private int startPosition; public Origin(int line, int startPosition) { this.line = line; this.startPosition = startPosition; } public int getLine() { return line; } public void setLine(int line) { this.line = line; } public int getStartPosition() { return startPosition; } public void setStartPosition(int startPosition) { this.startPosition = startPosition; } } ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/ParseErrorListener.java ================================================ package io.github.melin.superior.common.antlr4; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.Recognizer; public class ParseErrorListener extends BaseErrorListener { @Override public void syntaxError( Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, java.lang.String msg, RecognitionException e) { Origin position = new Origin(line, charPositionInLine); throw new ParseException(msg, position, position); } } ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/ParseException.java ================================================ package io.github.melin.superior.common.antlr4; import org.apache.commons.lang3.StringUtils; public class ParseException extends RuntimeException { private String command; private String message; private Origin start; private Origin stop; public ParseException(String message, Origin start, Origin stop) { this.message = message; this.start = start; this.stop = stop; } public ParseException(String command, String message, Origin start, Origin stop) { this.command = command; this.message = message; this.start = start; this.stop = stop; } @Override public String getMessage() { StringBuilder builder = new StringBuilder(); builder.append("\n").append(message); if (start != null) { builder.append("(line " + start.getLine() + ", pos " + start.getStartPosition() + ")\n"); if (StringUtils.isNotBlank(command)) { String[] lines = command.split("\n"); builder.append("\n== SQL ==\n"); for (int i = 0; i < start.getLine(); i++) { builder.append(lines[i]).append("\n"); } for (int i = 0; i < start.getStartPosition(); i++) { builder.append("-"); } builder.append("^^^\n"); for (int i = start.getLine(); i < lines.length; i++) { builder.append(lines[i]).append("\n"); } } } else { builder.append("\n== SQL ==\n").append(command); } return StringUtils.trim(builder.toString()); } public ParseException withCommand(String cmd) { return new ParseException(cmd, message, start, stop); } public String getCommand() { return command; } public Origin getStart() { return start; } public Origin getStop() { return stop; } } ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/ParserUtils.java ================================================ package io.github.melin.superior.common.antlr4; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.Interval; import org.antlr.v4.runtime.tree.TerminalNode; public class ParserUtils { /** Get the code that creates the given node. */ public static String source(ParserRuleContext ctx) { CharStream stream = ctx.getStart().getInputStream(); return stream.getText( Interval.of(ctx.getStart().getStartIndex(), ctx.getStop().getStopIndex())); } public static String getString(Token token) { return unescapeSQLString(token.getText()); } public static String getString(TerminalNode token) { return unescapeSQLString(token.getText()); } public static int getInt(Token token) { return Integer.parseInt(token.getText()); } public static String command(ParserRuleContext ctx) { CharStream stream = ctx.getStart().getInputStream(); return stream.getText(Interval.of(0, stream.size())); } public static Origin position(Token token) { return new Origin(token.getLine(), token.getCharPositionInLine()); } private static void appendEscapedChar(StringBuilder sb, char n) { switch (n) { case '0': sb.append("\u0000"); case '\'': sb.append("\'"); case '"': sb.append("\""); case 'b': sb.append("\b"); case 'n': sb.append("\n"); case 'r': sb.append("\r"); case 't': sb.append("\t"); case 'Z': sb.append("\u001A"); case '\\': sb.append("\\"); // The following 2 lines are exactly what MySQL does TODO: why do we do this? case '%': sb.append("\\%"); case '_': sb.append("\\_"); default: sb.append(n); } } private static String unescapeSQLString(String b) { Character enclosure = null; StringBuilder sb = new StringBuilder(b.length()); int i = 0; int strLength = b.length(); while (i < strLength) { char currentChar = b.charAt(i); if (enclosure == null) { if (currentChar == '\'' || currentChar == '\"') { enclosure = currentChar; } } else if (enclosure == currentChar) { enclosure = null; } else if (currentChar == '\\') { if ((i + 6 < strLength) && b.charAt(i + 1) == 'u') { // \u0000 style character literals. int code = 0; int base = i + 2; for (int h = 0; h < 4; h++) { int digit = Character.digit(b.charAt(h + base), 16); code = (code << 4) + digit; } sb.append((char) code); i += 5; } else if (i + 4 < strLength) { // \000 style character literals. char i1 = b.charAt(i + 1); char i2 = b.charAt(i + 2); char i3 = b.charAt(i + 3); if ((i1 >= '0' && i1 <= '1') && (i2 >= '0' && i2 <= '7') && (i3 >= '0' && i3 <= '7')) { char tmp = (char) ((i3 - '0') + ((i2 - '0') << 3) + ((i1 - '0') << 6)); sb.append(tmp); i += 3; } else { appendEscapedChar(sb, i1); i += 1; } } else if (i + 2 < strLength) { // escaped character literals. char n = b.charAt(i + 1); appendEscapedChar(sb, n); i += 1; } } else { // non-escaped character literals. sb.append(currentChar); } i += 1; } return sb.toString(); } } ================================================ FILE: superior-common-parser/src/main/java/io/github/melin/superior/common/antlr4/UpperCaseCharStream.java ================================================ package io.github.melin.superior.common.antlr4; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CodePointCharStream; import org.antlr.v4.runtime.IntStream; import org.antlr.v4.runtime.misc.Interval; public class UpperCaseCharStream implements CharStream { private CodePointCharStream wrapped; public UpperCaseCharStream(CodePointCharStream wrapped) { this.wrapped = wrapped; } @Override public void consume() { wrapped.consume(); } @Override public int LA(int i) { int la = wrapped.LA(i); if (la == 0 || la == IntStream.EOF) { return la; } else { return Character.toUpperCase(la); } } @Override public String getText(Interval interval) { if (size() > 0 && (interval.b - interval.a >= 0)) { return wrapped.getText(interval); } else { return ""; } } @Override public int mark() { return wrapped.mark(); } @Override public void release(int i) { wrapped.release(i); } @Override public int index() { return wrapped.index(); } @Override public void seek(int i) { wrapped.seek(i); } @Override public int size() { return wrapped.size(); } @Override public String getSourceName() { return wrapped.getSourceName(); } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/AlterActionType.kt ================================================ package io.github.melin.superior.common import java.io.Serializable enum class AlterActionType : Serializable { SET_PROPS, SET_SERDE, TOUCH_TABLE, ALTER_COLUMN, ALTER_VIEW_QUERY, ADD_UNIQUE_KEY, ADD_PRIMARY_KEY, ADD_INDEX, ADD_PARTITION, DROP_INDEX, ADD_COLUMN, SET_COLUMN_DEFAULT, DROP_COLUMN, DROP_COLUMN_DRFAULT, DROP_PARTITION, DROP_PRIMARY_KEY, RENAME, RENAME_PARTITION, DETACH_PARTITION, ATTACH_PARTITION, TRUNCATE_PARTITION, REFRESH_MV, // Iceberg SQL Extensions CREATE_TAG, CREATE_BRANCH, DROP_TAG, DROP_BRANCH, ADD_PARTITION_FIELD, DROP_PARTITION_FIELD, REPLACE_PARTITION_FIELD, SET_WRITE_DISTRIBUTION_AND_ORDERING, SET_IDENTIFIER_FIELDS, DROP_IDENTIFIER_FIELDS, // delta ADD_CONSTRAINT, DROP_CONSTRAINT, DROP_FEATURE, CLUSTER_BY, SYNC_IDENTITY, UNKOWN } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/PrivilegeType.kt ================================================ package io.github.melin.superior.common enum class PrivilegeType { READ, WRITE, ALTER, DROP, ADMIN, CREATE, PROCEDURE, OTHER, } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/SQLParserException.kt ================================================ package io.github.melin.superior.common class SQLParserException : RuntimeException { constructor(message: String, ex: Exception?) : super(message, ex) {} constructor(message: String) : super(message) {} constructor(ex: Exception) : super(ex) {} } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/SqlType.kt ================================================ package io.github.melin.superior.common enum class SqlType(val desc: String) { DML("Data Manipulation Language"), DDL("Data Definition Language"), DQL("Data Query Language"), DCL("Data Control Language"), TCL("Transaction Control Language") } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/StatementType.kt ================================================ package io.github.melin.superior.common import java.io.Serializable /** Created by libinsong on 2017/3/6. */ enum class StatementType : Serializable { CREATE_CATALOG, CREATE_DATABASE, CREATE_SCHEMA, CREATE_TABLE, CREATE_TABLE_AS_SELECT, CREATE_TABLE_AS_LIKE, CREATE_MATERIALIZED_VIEW, CREATE_VIEW, CREATE_FILE_VIEW, // spark CREATE_TEMP_VIEW_USING, // spark CREATE_FUNCTION, CREATE_PROCEDURE, DROP_CATALOG, DROP_DATABASE, DROP_SCHEMA, DROP_TABLE, DROP_VIEW, DROP_MATERIALIZED_VIEW, DROP_FUNCTION, DROP_SEQUENCE, DROP_PROCEDURE, TRUNCATE_TABLE, REFRESH_TABLE, EXPORT_TABLE, CANCEL_EXPORT, ANALYZE_TABLE, ALTER_DATABASE, ALTER_VIEW, ALTER_MATERIALIZED_VIEW, ALTER_TABLE, REPAIR_TABLE, COMMENT, // DML SELECT, DELETE, UPDATE, MERGE, INSERT, LOAD_DATA, // spark SHOW, DESC, // spark CACHE, UNCACHE, CLEAR_CACHE, // spark delta VACUUM_TABLE, OPTIMIZE_TABLE, DESC_DELTA_DETAIL, DESC_DELTA_HISTORY, // spark DESC_FUNCTION, DESC_CATALOG, DESC_DATABASE, DESC_SCHEMA, DESC_TABLE, DESC_QUERY, // REFRESH_MV, CANCEL_REFRESH_MV, EXPLAIN, SET, RESET, USE, SPARK_DIST_CP, DATATUNNEL, // spark MERGE_FILE, // spark APP_JAR, // spark CALL, // hudi HELP, // hudi ARITHMETIC, // StarRocks SR_SUBMIT_TASK, SR_DROP_TASK, SR_CREATE_ROUTINE_LOAD, SR_PAUSE_ROUTINE_LOAD, SR_RESUME_ROUTINE_LOAD, SR_STOP_ROUTINE_LOAD, SR_ALTER_ROUTINE_LOAD, LOAD_TABLE, CANCEL_LOAD_TABLE, ALTER_LOAD_TABLE, ADD_RESOURCE, LIST_RESOURCE, REMOVE_RESOURCE, SYNC_META, SYNC_TABLE, SYNC_DATABASE, UNKOWN } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/TableType.kt ================================================ package io.github.melin.superior.common enum class TableType { HIVE, MYSQL, ORACLE, STARROCKS, POSTGRES, SQLSERVER, FLINK, SPARK_STREAM, DAMENG, } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/AnalyzeTable.kt ================================================ package io.github.melin.superior.common.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType data class AnalyzeTable(val tableIds: List) : Statement() { override val statementType = StatementType.ANALYZE_TABLE override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/DefaultStatement.kt ================================================ package io.github.melin.superior.common.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType class DefaultStatement(override val statementType: StatementType) : Statement() { override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/FunctionId.kt ================================================ package io.github.melin.superior.common.relational import com.google.common.collect.Lists import org.apache.commons.lang3.StringUtils data class FunctionId( val catalogName: String?, val schemaName: String?, val functionName: String, ) { companion object { @JvmStatic fun of(functionName: String) = TableId(functionName) @JvmStatic fun of(schemaName: String, functionName: String) = TableId(schemaName, functionName) @JvmStatic fun of(catalogName: String, schemaName: String, functionName: String) = TableId(catalogName, schemaName, functionName) } var funcType: String = "CF" // callfunction & TVF var functionArguments: List = Lists.newArrayList() constructor(schemaName: String?, tableName: String) : this(null, schemaName, tableName) constructor(tableName: String) : this(null, null, tableName) fun getFullFunctionName(): String { if (catalogName != null) { return "$catalogName.$schemaName.$functionName" } if (schemaName != null) { return "$schemaName.$functionName" } return functionName } fun getLowerCatalogName(): String { return StringUtils.lowerCase(catalogName) } fun getLowerSchemaName(): String { return StringUtils.lowerCase(schemaName) } fun getLowerTableName(): String { return StringUtils.lowerCase(functionName) } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/ProcedureId.kt ================================================ package io.github.melin.superior.common.relational import org.apache.commons.lang3.StringUtils data class ProcedureId(val catalogName: String?, val schemaName: String?, val procedureName: String) { constructor(schemaName: String?, procedureName: String) : this(null, schemaName, procedureName) constructor(procedureName: String) : this(null, null, procedureName) fun getFullFunctionName(): String { if (catalogName != null) { return "${catalogName}.${schemaName}.${procedureName}" } if (schemaName != null) { return "${schemaName}.${procedureName}" } return procedureName } fun getLowerCatalogName(): String { return StringUtils.lowerCase(catalogName) } fun getLowerSchemaName(): String { return StringUtils.lowerCase(schemaName) } fun getLowerTableName(): String { return StringUtils.lowerCase(procedureName) } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/SchemaId.kt ================================================ package io.github.melin.superior.common.relational import org.apache.commons.lang3.StringUtils data class SchemaId(val catalogName: String?, val schemaName: String) { companion object { @JvmStatic fun of(schemaName: String) = SchemaId(schemaName) @JvmStatic fun of(catalogName: String, schemaName: String) = SchemaId(catalogName, schemaName) } constructor(schemaName: String) : this(null, schemaName) fun getFullSchemaName(): String { if (catalogName != null) { return "${catalogName}.${schemaName}" } return schemaName } fun getLowerCatalogName(): String { return StringUtils.lowerCase(catalogName) } fun getLowerSchemaName(): String { return StringUtils.lowerCase(schemaName) } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/Statement.kt ================================================ package io.github.melin.superior.common.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import org.apache.commons.lang3.StringUtils import java.io.Serializable abstract class Statement : Serializable { abstract val statementType: StatementType abstract val privilegeType: PrivilegeType abstract val sqlType: SqlType private var sql: String = "" fun setSql(sql: String) { if (StringUtils.endsWith(sql, ";")) { this.sql = StringUtils.substringBeforeLast(sql, ";") } else { this.sql = sql } } fun getSql(): String { return this.sql } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/TableId.kt ================================================ package io.github.melin.superior.common.relational import org.apache.commons.lang3.StringUtils data class TableId(val catalogName: String?, val schemaName: String?, val tableName: String, val metaType: String?) { companion object { @JvmStatic fun of(tableName: String) = TableId(tableName) @JvmStatic fun of(schemaName: String, tableName: String) = TableId(schemaName, tableName) @JvmStatic fun of(catalogName: String, schemaName: String, tableName: String) = TableId(catalogName, schemaName, tableName) } constructor( catalogName: String?, schemaName: String?, tableName: String ) : this(catalogName, schemaName, tableName, null) constructor(schemaName: String?, tableName: String) : this(null, schemaName, tableName, null) constructor(tableName: String) : this(null, null, tableName, null) fun getFullTableName(): String { if (catalogName != null) { return "${catalogName}.${schemaName}.${tableName}" } if (schemaName != null) { return "${schemaName}.${tableName}" } return tableName } fun getLowerCatalogName(): String { return StringUtils.lowerCase(catalogName) } fun getLowerSchemaName(): String { return StringUtils.lowerCase(schemaName) } fun getLowerTableName(): String { return StringUtils.lowerCase(tableName) } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/abs/AbsDatabaseStatement.kt ================================================ package io.github.melin.superior.common.relational.abs import io.github.melin.superior.common.relational.Statement abstract class AbsDatabaseStatement : Statement() { abstract val databaseName: String } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/abs/AbsTableStatement.kt ================================================ package io.github.melin.superior.common.relational.abs import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId abstract class AbsTableStatement : Statement() { abstract val tableId: TableId } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterAction.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.AlterActionType import io.github.melin.superior.common.PrivilegeType abstract class AlterAction(val privilegeType: PrivilegeType = PrivilegeType.ALTER) { abstract val alterType: AlterActionType } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterActions.kt ================================================ package io.github.melin.superior.common.relational.alter import com.google.common.collect.Maps import io.github.melin.superior.common.AlterActionType import io.github.melin.superior.common.relational.SortType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.table.ColumnRel import java.util.HashMap data class AlterTableAction(override var alterType: AlterActionType) : AlterAction() data class AlterPropsAction(var location: String? = null, var properties: HashMap = Maps.newHashMap()) : AlterAction() { override var alterType: AlterActionType = AlterActionType.SET_PROPS constructor(properties: HashMap) : this(null, properties) } data class AlterSerDeAction(var properties: HashMap = Maps.newHashMap()) : AlterAction() { override var alterType: AlterActionType = AlterActionType.SET_SERDE } data class RenameAction(var newTableId: TableId, var ifExists: Boolean = false) : AlterAction() { override var alterType: AlterActionType = AlterActionType.RENAME } data class AlterTouchPartitionAction( val newTableId: TableId, // 修改表,新列名称 val partitionVals: LinkedHashMap? ) : AlterAction() { override var alterType: AlterActionType = AlterActionType.TOUCH_TABLE } data class AlterViewAction( val queryStmt: QueryStmt // 修改表,新列名称 ) : AlterAction() { override var alterType: AlterActionType = AlterActionType.ALTER_VIEW_QUERY } data class RefreshMvAction(var async: Boolean = false) : AlterAction() { override var alterType: AlterActionType = AlterActionType.REFRESH_MV } data class AlterColumnAction( override var alterType: AlterActionType, var columName: String? = null, // 修改列名 var dataType: String? = null, var comment: String? = null, var position: String? = null, var afterCol: String? = null, var setOrDrop: String? = null, var nullable: Boolean = true, var defaultExpression: String? = null, var dropDefault: Boolean = false, var ifNotExists: Boolean = false ) : AlterAction() { var newColumName: String? = null // 修改列名,新列名称 fun getColumn(): ColumnRel? { return if (columName != null) { ColumnRel(columName!!, dataType, comment, nullable, defaultExpression) } else { null } } } data class DropColumnAction(var columNames: ArrayList = arrayListOf()) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_COLUMN fun firstColumn(): String { return columNames.first() } constructor(columName: String) : this(arrayListOf(columName)) } data class AddPartitionAction(var ifNotExists: Boolean = false, var partitions: List>) : AlterAction() { override var alterType: AlterActionType = AlterActionType.ADD_PARTITION } data class DropPartitionAction( var ifExists: Boolean = false, var partitions: List> = listOf() ) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_PARTITION } data class RenamePartitionAction( var fromPartitionVals: LinkedHashMap, var toPartitionVals: LinkedHashMap ) : AlterAction() { override var alterType: AlterActionType = AlterActionType.RENAME_PARTITION } data class CreateIndex(val indexName: String, val indexColumnNames: ArrayList = arrayListOf()) : AlterAction() { override var alterType: AlterActionType = AlterActionType.ADD_INDEX var intimeAction: String = "ONLINE" // mysql ONLINE & OFFLINE var indexCategory: String? = null var indexType: String? = null var comment: String? = null } data class IndexColumnName( val columnName: String, val sortType: SortType = SortType.UNKOWN, ) data class DropIndex(val indexName: String, var ifExists: Boolean = false) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_INDEX } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterDatabase.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.abs.AbsDatabaseStatement import kotlin.collections.ArrayList data class AlterDatabase( val alterActionType: AlterActionType, override val databaseName: String, private val action: AlterAction? ) : AbsDatabaseStatement() { override val statementType = StatementType.ALTER_DATABASE override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DDL val actions: ArrayList = ArrayList() var ifExists: Boolean = false init { if (action != null) { actions.add(action) } } constructor(alterActionType: AlterActionType, databaseName: String) : this(alterActionType, databaseName, null) fun addActions(list: List) { actions.addAll(list) } fun firstAction(): AlterAction { return actions.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterDatabaseActions.kt ================================================ package io.github.melin.superior.common.relational.alter import com.google.common.collect.Maps import io.github.melin.superior.common.AlterActionType import java.util.HashMap data class AlterDbPropsAction( var location: String? = null, var properties: HashMap = Maps.newHashMap() ) : AlterAction() { override var alterType: AlterActionType = AlterActionType.SET_PROPS } data class RenameDbAction(var newDatabaseName: String) : AlterAction() { override var alterType: AlterActionType = AlterActionType.RENAME } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterMaterializedView.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import kotlin.collections.ArrayList data class AlterMaterializedView(override val tableId: TableId, private val action: AlterAction?) : AbsTableStatement() { override val statementType = StatementType.ALTER_MATERIALIZED_VIEW override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DDL val actions: ArrayList = ArrayList() var ifExists: Boolean = false init { if (action != null) { actions.add(action) } } constructor(tableId: TableId) : this(tableId, null) fun addActions(list: List) { actions.addAll(list) } fun firstAction(): AlterAction { return actions.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterTable.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import kotlin.collections.ArrayList data class AlterTable( override val tableId: TableId, private val action: AlterAction?, ) : AbsTableStatement() { override val statementType = StatementType.ALTER_TABLE override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DDL val actions: ArrayList = ArrayList() var ifExists: Boolean = false init { if (action != null) { actions.add(action) } } constructor(tableId: TableId) : this(tableId, null) fun addAction(action: AlterAction) { actions.add(action) } fun addActions(list: List) { actions.addAll(list) } fun firstAction(): AlterAction { return if (action != null) action else actions.first() } fun getFirstAlterType(): AlterActionType { val action = firstAction() return action.alterType } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/AlterView.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import kotlin.collections.ArrayList data class AlterView(override val tableId: TableId, private val action: AlterAction?) : AbsTableStatement() { override val statementType = StatementType.ALTER_VIEW override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DDL val actions: ArrayList = ArrayList() var ifExists: Boolean = false init { if (action != null) { actions.add(action) } } constructor(tableId: TableId) : this(tableId, null) fun addActions(list: List) { actions.addAll(list) } fun firstAction(): AlterAction { return actions.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/DeltaAlterActions.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.AlterActionType class AlterAddConstraintAction() : AlterAction() { override var alterType: AlterActionType = AlterActionType.ADD_CONSTRAINT } class AlterDropConstraintAction() : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_CONSTRAINT } class AlterDropFeatureAction() : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_FEATURE } class AlterClusterByAction() : AlterAction() { override var alterType: AlterActionType = AlterActionType.CLUSTER_BY } class AlterSyncIdentityAction() : AlterAction() { override var alterType: AlterActionType = AlterActionType.SYNC_IDENTITY } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/alter/IcebergAlterActions.kt ================================================ package io.github.melin.superior.common.relational.alter import io.github.melin.superior.common.AlterActionType data class AlterCreateTagAction(val tagName: String) : AlterAction() { override var alterType: AlterActionType = AlterActionType.CREATE_TAG } data class AlterDropTagAction(val tagName: String) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_TAG } data class AlterCreateBranchAction(val branchName: String) : AlterAction() { override var alterType: AlterActionType = AlterActionType.CREATE_BRANCH } data class AlterDropBranchAction(val branchName: String) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_BRANCH } data class AlterSetIdentifierFieldsAction(val fields: List) : AlterAction() { override var alterType: AlterActionType = AlterActionType.SET_IDENTIFIER_FIELDS } data class AlterDropIdentifierFieldsAction(val fields: List) : AlterAction() { override var alterType: AlterActionType = AlterActionType.DROP_IDENTIFIER_FIELDS } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/AddResourceStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class AddResourceStatement(val fileNames: List, val resourceType: String) : Statement() { override val statementType = StatementType.ADD_RESOURCE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(fileName: String, resourceType: String) : this(listOf(fileName), resourceType) fun first(): String { return fileNames.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/CallProcedure.kt ================================================ package io.github.melin.superior.common.relational.common import com.google.common.collect.Sets import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.Statement data class CallProcedure(var procedureIds: HashSet, var properties: Map = mapOf()) : Statement() { override val statementType = StatementType.CALL override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML constructor(procedureId: ProcedureId) : this(Sets.newHashSet(procedureId)) constructor( procedureId: ProcedureId, properties: Map ) : this(Sets.newHashSet(procedureId), properties) fun first(): ProcedureId { return procedureIds.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/CancelExport.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class CancelExport(val database: String?, var queryId: String) : Statement() { override val statementType = StatementType.CANCEL_EXPORT override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DML constructor(queryId: String) : this(null, queryId) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/CommentStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class CommentStatement( val comment: String? = null, val isNull: Boolean = false, val objType: String? = null, val objValue: String? = null ) : Statement() { override val statementType = StatementType.COMMENT override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.TCL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/DescModel.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.SchemaId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.dml.QueryStmt import org.apache.commons.lang3.StringUtils class DescStatement(vararg val keywords: String) : Statement() { override val statementType = StatementType.DESC override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML fun checkSql(sql: String): Boolean { val words = StringUtils.split(sql, " ") if (this.keywords.size != words.size) { return false } val size = this.keywords.size for (i in 0 until size) { if (!StringUtils.equalsIgnoreCase(this.keywords.get(i), words[i])) { return false } } return true } } // spark data class DescFunction(val functionId: FunctionId) : Statement() { override val statementType = StatementType.DESC_FUNCTION override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } data class DescCatalog(val catalog: String) : Statement() { override val statementType = StatementType.DESC_CATALOG override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } // 适用pg 类型数据库 data class DescDatabase(val database: String) : Statement() { override val statementType = StatementType.DESC_DATABASE override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } data class DescSchema(val schemaId: SchemaId) : Statement() { override val statementType = StatementType.DESC_SCHEMA override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } data class DescTable(val tableId: TableId) : Statement() { override val statementType = StatementType.DESC_TABLE override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } data class DescQuery(val queryStmt: QueryStmt) : Statement() { override val statementType = StatementType.DESC_QUERY override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } // spark delta data class DescDeltaDetail(override val tableId: TableId) : AbsTableStatement() { override val statementType = StatementType.DESC_DELTA_DETAIL override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } // spark delta data class DescDeltaHistory(override val tableId: TableId, val limit: Int? = null) : AbsTableStatement() { override val statementType = StatementType.DESC_DELTA_HISTORY override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/ListResourceStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class ListResourceStatement(val fileNames: List, val resourceType: String) : Statement() { override val statementType = StatementType.ADD_RESOURCE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(fileName: String, resourceType: String) : this(listOf(fileName), resourceType) fun first(): String { return fileNames.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/ReSetStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class ReSetStatement(val key: String) : Statement() { override val statementType = StatementType.RESET override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.TCL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/RefreshMaterializedView.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class RefreshMaterializedView( val tableId: TableId, val force: Boolean = false, val mode: String = "Async", val partitionStart: String? = null, val partitionEnd: String? = null, ) : Statement() { override val statementType = StatementType.REFRESH_MV override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/RemoveResourceStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class RemoveResourceStatement(val fileNames: List, val resourceType: String) : Statement() { override val statementType = StatementType.REMOVE_RESOURCE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(fileName: String, resourceType: String) : this(listOf(fileName), resourceType) fun first(): String { return fileNames.first() } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/SetStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class SetStatement(val key: String, val value: String? = null) : Statement() { override val statementType = StatementType.SET override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.TCL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/ShowStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import org.apache.commons.lang3.StringUtils class ShowStatement(vararg val keywords: String) : Statement() { override val statementType = StatementType.SHOW override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML fun checkSql(sql: String): Boolean { val words = StringUtils.split(sql, " ") if (this.keywords.size != words.size) { return false } val size = this.keywords.size for (i in 0 until size) { if (!StringUtils.equalsIgnoreCase(this.keywords.get(i), words[i])) { return false } } return true } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/SyncStatement.kt ================================================ package io.github.melin.superior.common.relational.common import com.google.common.collect.Maps import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.table.ColumnRel data class SyncTable( var sinkTableId: TableId, var sourceTableId: TableId, ) : Statement() { override val statementType = StatementType.SYNC_TABLE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML val sinkOptions: HashMap = Maps.newHashMap() val sourceOptions: HashMap = Maps.newHashMap() var computeCols: List? = null } data class SyncDatabase( var sinkCatalogName: String?, var sinkDatabaseName: String, var sourceCatalogName: String?, var sourceDatabaseName: String, var includingTables: String = ".*" ) : Statement() { override val statementType = StatementType.SYNC_DATABASE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML val sinkOptions: HashMap = Maps.newHashMap() val sourceOptions: HashMap = Maps.newHashMap() var excludingTables: String? = null } data class SyncDatabaseMetadata(val catalogName: String?, val databaseName: String, val owner: String?) : Statement() { override val statementType = StatementType.SYNC_META override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DDL } data class SyncTableMetadata(val tableId: TableId, val owner: String?) : Statement() { override val statementType = StatementType.SYNC_META override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/common/UseStatement.kt ================================================ package io.github.melin.superior.common.relational.common import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class UseCatalog(val catalogName: String) : Statement() { override val statementType = StatementType.USE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } data class UseDatabase(val catalogName: String?, val databaseName: String) : Statement() { override val statementType = StatementType.USE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(databaseName: String) : this(null, databaseName) } data class UseSchema(val databaseName: String?, val schemaName: String) : Statement() { override val statementType = StatementType.USE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(databaseName: String) : this(null, databaseName) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateCatalog.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class CreateCatalog( val catalogName: String, var properties: Map? = null, ) : Statement() { override val statementType = StatementType.CREATE_CATALOG override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DDL constructor(catalogName: String) : this(catalogName, null) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateDatabase.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class CreateDatabase( val catalogName: String?, val databaseName: String, val location: String? = null, var properties: Map? = null, var ifNotExists: Boolean = false, ) : Statement() { override val statementType = StatementType.CREATE_DATABASE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL constructor(databaseName: String) : this(null, databaseName, null, null) constructor( catalogName: String?, databaseName: String, properties: Map? = null, ifNotExists: Boolean = false ) : this(catalogName, databaseName, null, properties, ifNotExists) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateFunction.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement data class CreateFunction( val functionId: FunctionId, val childStatements: ArrayList, var replace: Boolean = false, var temporary: Boolean = false, val className: String? = null, val file: String? = null ) : Statement() { override val statementType = StatementType.CREATE_FUNCTION override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML var global: Boolean = false // starrocks var properties: Map? = null // starrocks var argumentTypes: List? = null // starrocks var returnType: String? = null // starrocks constructor( functionId: FunctionId, childStatements: ArrayList, replace: Boolean ) : this(functionId, childStatements, replace, false) constructor( functionId: FunctionId, childStatements: ArrayList ) : this(functionId, childStatements, false, false) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateMaterializedView.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.table.ColumnRel data class CreateMaterializedView( override val tableId: TableId, var queryStmt: QueryStmt, val comment: String? = null, var ifNotExists: Boolean = false, // 是否存在 if not exists 关键字 var columnRels: List? = null ) : AbsTableStatement() { override val statementType = StatementType.CREATE_MATERIALIZED_VIEW override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL var modelType: String = "Sync" // 表模型类型 var properties: Map = mapOf() } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateProcedure.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.Statement data class CreateProcedure( val procedureId: ProcedureId?, val childStatements: ArrayList, var replace: Boolean = false, var temporary: Boolean = false, val className: String? = null, val file: String? = null ) : Statement() { override val statementType = StatementType.CREATE_PROCEDURE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML constructor( procedureId: ProcedureId, childStatements: ArrayList, replace: Boolean ) : this(procedureId, childStatements, replace, false) constructor(childStatements: ArrayList) : this(null, childStatements) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateSchema.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class CreateSchema(val databaseName: String?, val schemaName: String) : Statement() { override val statementType = StatementType.CREATE_SCHEMA override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL constructor(schemaName: String) : this(null, schemaName) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateTable.kt ================================================ package io.github.melin.superior.common.relational.create import com.google.common.collect.Lists import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.TableType import io.github.melin.superior.common.relational.PartitionType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.table.ColumnRel data class CreateTable( override val tableId: TableId, val tableType: TableType, val comment: String? = null, var lifeCycle: Int? = null, var partitionColumnRels: List? = null, var columnRels: List? = null, var properties: Map? = null, var fileFormat: String? = null, var ifNotExists: Boolean = false, // 是否存在 if not exists 关键字 var external: Boolean = false, var temporary: Boolean = false, var location: String? = null, var querySql: String? = null, val partitionColumnNames: ArrayList = arrayListOf() ) : AbsTableStatement() { // 是否存在 if exists 关键字 override val statementType = StatementType.CREATE_TABLE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL // 建表方式:hive & spark. https://spark.apache.org/docs/3.2.0/sql-ref-syntax-ddl-create-table.html var replace = false var modelType: String = "hive" // 表模型类型 var partitionType: PartitionType? = null // 分区类型 var options: Map? = null var clusteredColumns: List = Lists.newArrayList() // 分桶表分桶列 var sortedColumns: List = Lists.newArrayList() // 分桶表排序列 var storageHandler: String? = null constructor( tableId: TableId, tableType: TableType, comment: String?, columnRels: List? ) : this(tableId, tableType, comment, null, null, columnRels, null, null, false) constructor( tableId: TableId, tableType: TableType, comment: String?, lifeCycle: Int?, columnRels: List? ) : this(tableId, tableType, comment, lifeCycle, null, columnRels, null, null, false) constructor( tableId: TableId, tableType: TableType, comment: String? = null, columnRels: List? = null, ifNotExists: Boolean, properties: Map? = null ) : this(tableId, tableType, comment, null, null, columnRels, properties, null, ifNotExists) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateTableAsSelect.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.PartitionType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.table.ColumnRel data class CreateTableAsSelect( override val tableId: TableId, var queryStmt: QueryStmt, val comment: String? = null, var lifeCycle: Int? = null, var partitionColumnRels: List? = null, var columnRels: List? = null, var properties: Map? = null, var fileFormat: String? = null, var ifNotExists: Boolean = false, // 是否存在 if not exists 关键字 var locationPath: String? = null, val partitionColumnNames: ArrayList = arrayListOf() ) : AbsTableStatement() { // 是否存在 if exists 关键字 override val statementType = StatementType.CREATE_TABLE_AS_SELECT override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL var replace = false // 建表方式:hive & spark. https://spark.apache.org/docs/3.2.0/sql-ref-syntax-ddl-create-table.html var modelType: String = "hive" var partitionType: PartitionType? = null // 分区类型 var options: Map? = null var storageHandler: String? = null constructor( tableId: TableId, queryStmt: QueryStmt ) : this(tableId, queryStmt, null, null, null, null, null, null, false) constructor( tableId: TableId, queryStmt: QueryStmt, comment: String? = null, ifNotExists: Boolean, properties: Map? = null ) : this(tableId, queryStmt, comment, null, null, null, properties, null, ifNotExists) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateTableLike.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class CreateTableLike( val oldTableId: TableId, override val tableId: TableId, var ifNotExists: Boolean = false, var external: Boolean = false, var temporary: Boolean = false ) : AbsTableStatement() { override val statementType = StatementType.CREATE_TABLE_AS_LIKE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/create/CreateView.kt ================================================ package io.github.melin.superior.common.relational.create import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.table.ColumnRel data class CreateView( override val tableId: TableId, var queryStmt: QueryStmt, val comment: String? = null, var ifNotExists: Boolean = false, // 是否存在 if not exists 关键字 var columnRels: List? = null ) : AbsTableStatement() { override val statementType = StatementType.CREATE_VIEW override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL var replace: Boolean = false var temporary: Boolean = false var global: Boolean = false var fileFormat: String? = null var properties: Map = mapOf() } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/delta/OptimizeTable.kt ================================================ package io.github.melin.superior.common.relational.delta import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class OptimizeTable(override val tableId: TableId) : AbsTableStatement() { override val statementType = StatementType.OPTIMIZE_TABLE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/delta/VacuumTable.kt ================================================ package io.github.melin.superior.common.relational.delta import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class VacuumTable(override val tableId: TableId) : AbsTableStatement() { override val statementType = StatementType.VACUUM_TABLE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/DeleteTable.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class DeleteTable( override val tableId: TableId, val inputTables: List, ) : AbsTableStatement() { override val statementType = StatementType.DELETE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML val outputTables: ArrayList = arrayListOf() init { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/InsertFiles.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class InsertFiles( val mode: InsertMode, val queryStmt: QueryStmt, var properties: Map, ) : Statement() { override val statementType = StatementType.INSERT override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/InsertMode.kt ================================================ package io.github.melin.superior.common.relational.dml import java.io.Serializable enum class InsertMode : Serializable { INTO, INTO_REPLACE, OVERWRITE, OVERWRITE_HIVE_DIR, OVERWRITE_DIR, } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/InsertMultiTable.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class InsertMultiTable( val insertTables: List, ) : Statement() { override val statementType = StatementType.UNKOWN override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/InsertTable.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.table.ColumnRel import java.util.* import kotlin.collections.ArrayList import kotlin.collections.LinkedHashMap data class InsertTable( val mode: InsertMode, val queryStmt: QueryStmt, override val tableId: TableId, var columnRels: List? = null, ) : AbsTableStatement() { override val statementType = StatementType.INSERT override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML var properties: Map? = null var fileFormat: String? = null var partitionVals: LinkedHashMap? = null var rows: ArrayList>? = null val outputTables: ArrayList = arrayListOf() var hints: LinkedHashMap>? = null var mysqlReplace: Boolean = false init { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/MergeTable.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class MergeTable( var targetTable: TableId, var inputTables: List = listOf(), ) : Statement() { override val statementType = StatementType.MERGE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/QueryStmt.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class QueryStmt( var inputTables: List, var limit: Int? = null, var offset: Int? = null, ) : Statement() { override val statementType = StatementType.SELECT override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DQL val functionNames: HashSet = hashSetOf() constructor() : this(listOf()) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/dml/UpdateTable.kt ================================================ package io.github.melin.superior.common.relational.dml import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class UpdateTable( override val tableId: TableId, var inputTables: List, ) : AbsTableStatement() { override val statementType = StatementType.UPDATE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropCatalog.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class DropCatalog(val catalogName: String) : Statement() { override val statementType = StatementType.DROP_CATALOG override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropDatabase.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class DropDatabase(val catalogName: String?, val databaseName: String, var ifExists: Boolean = false) : Statement() { override val statementType = StatementType.DROP_DATABASE override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL val databaseNames: ArrayList = arrayListOf() constructor(databaseName: String) : this(null, databaseName) constructor(databaseName: String, ifExists: Boolean) : this(null, databaseName, ifExists) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropFunction.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement data class DropFunction(val functionId: FunctionId) : Statement() { override val statementType = StatementType.DROP_FUNCTION override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL var argumentTypes: List? = null // starrocks } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropMaterializedView.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class DropMaterializedView(override val tableId: TableId, var ifExists: Boolean = false) : AbsTableStatement() { override val statementType = StatementType.DROP_MATERIALIZED_VIEW override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL val tableIds: ArrayList = arrayListOf() } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropProcedure.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.Statement data class DropProcedure(val procedureId: ProcedureId) : Statement() { override val statementType = StatementType.DROP_PROCEDURE override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropSchema.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement class DropSchema( val databaseName: String?, val schemaName: String, ) : Statement() { override val statementType = StatementType.DROP_SCHEMA override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL constructor(schemaName: String) : this(null, schemaName) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropSequence.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class DropSequence( override val tableId: TableId, var ifExists: Boolean = false, var isMaterialized: Boolean = false, ) : AbsTableStatement() { override val statementType = StatementType.DROP_SEQUENCE override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL val tableIds: ArrayList = arrayListOf() } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropTable.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class DropTable(override val tableId: TableId, var ifExists: Boolean = false) : AbsTableStatement() { override val statementType = StatementType.DROP_TABLE override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL val tableIds: ArrayList = arrayListOf() var force: Boolean = false var purge: Boolean = false } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/drop/DropView.kt ================================================ package io.github.melin.superior.common.relational.drop import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class DropView(override val tableId: TableId, var ifExists: Boolean = false) : AbsTableStatement() { override val statementType = StatementType.DROP_VIEW override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DDL val tableIds: ArrayList = arrayListOf() } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/enums.kt ================================================ package io.github.melin.superior.common.relational enum class SortType { ASC, DESC, UNKOWN } enum class PartitionType { RANGE, LIST, HASH, KEY, VALUES, NORMAL, EXPRESSION } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/io/AlterLoadTable.kt ================================================ package io.github.melin.superior.common.relational.io import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class AlterLoadTable( val schemaName: String?, val labelName: String, ) : Statement() { override val statementType = StatementType.ALTER_LOAD_TABLE override val privilegeType = PrivilegeType.ALTER override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/io/CancelLoadTable.kt ================================================ package io.github.melin.superior.common.relational.io import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class CancelLoadTable( val schemaName: String?, val labelName: String, ) : Statement() { override val statementType = StatementType.CANCEL_LOAD_TABLE override val privilegeType = PrivilegeType.DROP override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/io/ExportTable.kt ================================================ package io.github.melin.superior.common.relational.io import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class ExportTable( override val tableId: TableId, val path: String, var properties: Map, var partitionVals: LinkedHashMap, var fileFormat: String? = null, var compression: String? = null, var maxFileSize: String? = null, var overwrite: Boolean = false, var single: Boolean = false, var inputTables: ArrayList, ) : AbsTableStatement() { override val statementType = StatementType.EXPORT_TABLE override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DML val functionNames: HashSet = hashSetOf() constructor( tableId: TableId, path: String, properties: Map, ) : this(tableId, path, properties, linkedMapOf(), null, null, null, false, false, arrayListOf()) constructor( tableId: TableId, path: String, properties: Map, partitionVals: LinkedHashMap, fileFormat: String? = null, compression: String? = null, maxFileSize: String? = null, overwrite: Boolean = false, single: Boolean = false, ) : this( tableId, path, properties, partitionVals, fileFormat, compression, maxFileSize, overwrite, single, arrayListOf() ) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/io/LoadTable.kt ================================================ package io.github.melin.superior.common.relational.io import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class LoadTable( val schemaName: String?, val labelName: String, val tableNames: List, ) : Statement() { override val statementType = StatementType.LOAD_TABLE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/table/ColumnRel.kt ================================================ package io.github.melin.superior.common.relational.table data class ColumnRel( val columnName: String, val typeName: String? = null, val comment: String? = null, var nullable: Boolean = true, var defaultExpr: String? = null, var primaryKey: Boolean = false, val columnDefType: ColumnDefType = ColumnDefType.COMPUTED ) { var columnLength = 0 var precision = 0 var scale = 0 var expression: String? = null // 计算表达式 var position: String? = null var afterCol: String? = null var jsonPath: String? = null // spark streaming sql json path var computedExpr: String? = null // 计算列 var metadataKey: String? = null // 元数据列 constructor( columnName: String, typeName: String?, comment: String? ) : this(columnName, typeName, comment, true, null) constructor( columnName: String, typeName: String?, comment: String?, primaryKey: Boolean = false, columnDefType: ColumnDefType ) : this(columnName, typeName, comment, true, null, primaryKey, columnDefType) constructor( columnName: String, typeName: String?, comment: String?, columnDefType: ColumnDefType ) : this(columnName, typeName, comment, true, null, false, columnDefType) } enum class ColumnDefType { PHYSICAL, METADATA, COMPUTED } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/table/RepairTable.kt ================================================ package io.github.melin.superior.common.relational.table import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement class RepairTable(override val tableId: TableId) : AbsTableStatement() { override val statementType = StatementType.REPAIR_TABLE override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DDL } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/relational/table/TruncateTable.kt ================================================ package io.github.melin.superior.common.relational.table import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement class TruncateTable(override val tableId: TableId, tableIds: ArrayList = ArrayList()) : AbsTableStatement() { override val statementType = StatementType.TRUNCATE_TABLE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DDL init { tableIds.add(tableId) } constructor(tableIds: ArrayList) : this(tableIds.first(), tableIds) } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/type/AbsDataTimeType.kt ================================================ package io.github.melin.superior.common.type abstract class AbsDataTimeType : AbsType() {} ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/type/AbsNumericType.kt ================================================ package io.github.melin.superior.common.type abstract class AbsNumericType : AbsType() { var character: String? = null var collate: String? = null } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/type/AbsStringType.kt ================================================ package io.github.melin.superior.common.type abstract class AbsStringType : AbsType() { var character: String? = null var collate: String? = null } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/type/AbsType.kt ================================================ package io.github.melin.superior.common.type abstract class AbsType : Type { override val alias: String? = null override val alias2: String? = null } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/type/Type.kt ================================================ package io.github.melin.superior.common.type interface Type { val name: String val alias: String? val alias2: String? // 有些有多个别名,例如mysql integer有int 和 int4 两种 } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/util/CommonUtils.kt ================================================ package com.github.melin.superior.sql.parser.util import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.Token import org.antlr.v4.runtime.tree.ParseTree import org.antlr.v4.runtime.tree.TerminalNodeImpl import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2017/4/10. */ object CommonUtils { val KEYWORD_REGEX = "'([A-Z_]+)'".toRegex() fun findShowStatementKeyWord(keyWords: ArrayList, node: ParseTree) { if (node is TerminalNodeImpl) { val count = node.parent.childCount for (i in 0 until count) { val child = node.parent.getChild(i) if (child is TerminalNodeImpl) { keyWords.add(child.text.uppercase()) } } } else { findShowStatementKeyWord(keyWords, node.getChild(0)) } } fun subsql(sql: String?, context: ParserRuleContext): String { val currSql = StringUtils.substring(sql, context.start.startIndex, context.stop.stopIndex + 1) return cleanLastSemi(currSql) } fun subsql(sql: String?, start: Token, stop: Token): String { val currSql = StringUtils.substring(sql, start.stopIndex + 1, stop.stopIndex + 1) return cleanLastSemi(currSql) } private fun cleanLastSemi(text: String): String { if (StringUtils.endsWith(text, ";")) { return StringUtils.substring(text, 0, text.length - 1) } return text } fun cleanQuote(value: String): String { if (StringUtils.isBlank(value)) { return value } var result = value if (StringUtils.startsWith(result, "'") && StringUtils.endsWith(result, "'")) { result = StringUtils.substring(result, 1, -1) } if (StringUtils.startsWith(result, "\"") && StringUtils.endsWith(result, "\"")) { result = StringUtils.substring(result, 1, -1) } if (StringUtils.startsWith(value, "`") && StringUtils.endsWith(value, "`")) { return StringUtils.substring(value, 1, -1) } return StringUtils.trim(result) } } ================================================ FILE: superior-common-parser/src/main/kotlin/io/github/melin/superior/common/util/DateUtils.kt ================================================ package com.github.melin.superior.sql.parser.util import java.time.DateTimeException import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter import java.util.* object DateUtils { fun getCurrentDateTime(): String { try { val ldt = LocalDateTime.ofInstant(Date().toInstant(), ZoneId.systemDefault()) val format = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS") return ldt.format(format) } catch (ex: DateTimeException) { throw RuntimeException(ex.message, ex) } } } ================================================ FILE: superior-dameng-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-dameng-parser superior-dameng-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-dameng-parser/src/main/antlr4/io/github/melin/superior/parser/dameng/antlr4/DmSqlLexer.g4 ================================================ lexer grammar DmSqlLexer; // Keywords ABORT: 'ABORT'; ABSOLUTE: 'ABSOLUTE'; ABSTRACT: 'ABSTRACT'; ACCESSED: 'ACCESSED'; ACCOUNT: 'ACCOUNT'; ACROSS: 'ACROSS'; ACTION: 'ACTION'; ADD: 'ADD'; ADMIN: 'ADMIN'; ADVANCED: 'ADVANCED'; AFTER: 'AFTER'; AGGREGATE: 'AGGREGATE'; ALL: 'ALL'; ALLOW_DATETIME: 'ALLOW_DATETIME'; ALLOW_IP: 'ALLOW_IP'; ALTER: 'ALTER'; ALWAYS: 'ALWAYS'; ANALYZE: 'ANALYZE'; AND: 'AND'; ANY: 'ANY'; APPLY: 'APPLY'; APR: 'APR'; ARCHIVE: 'ARCHIVE'; ARCHIVEDIR: 'ARCHIVEDIR'; ARCHIVELOG: 'ARCHIVELOG'; ARCHIVESTYLE: 'ARCHIVESTYLE'; ARRAY: 'ARRAY'; ARRAYLEN: 'ARRAYLEN'; AS: 'AS'; ASC: 'ASC'; ASCII: 'ASCII'; ASENSITIVE: 'ASENSITIVE'; ASSIGN: 'ASSIGN'; ASYNCHRONOUS: 'ASYNCHRONOUS'; ATTACH: 'ATTACH'; AT_KEYWORD: 'AT'; AUDIT: 'AUDIT'; AUG: 'AUG'; AUTHID: 'AUTHID'; AUTHORIZATION: 'AUTHORIZATION'; AUTO: 'AUTO'; AUTOEXTEND: 'AUTOEXTEND'; AUTONOMOUS_TRANSACTION: 'AUTONOMOUS_TRANSACTION'; AUTO_INCREMENT: 'AUTO_INCREMENT'; AUTO_UPDATE: 'AUTO_UPDATE'; AVG: 'AVG'; BACKED: 'BACKED'; BACKUP: 'BACKUP'; BACKUPDIR: 'BACKUPDIR'; BACKUPINFO: 'BACKUPINFO'; BACKUPSET: 'BACKUPSET'; BADFILE: 'BADFILE'; BAKFILE: 'BAKFILE'; BASE: 'BASE'; BATCH: 'BATCH'; BEFORE: 'BEFORE'; BEGIN: 'BEGIN'; BETWEEN: 'BETWEEN'; BIGDATEDIFF: 'BIGDATEDIFF'; BIGINT: 'BIGINT'; BINARY_KEYWORD: 'BINARY'; BIT: 'BIT'; BITMAP: 'BITMAP'; BLOB: 'BLOB'; BLOCK: 'BLOCK'; BODY: 'BODY'; BOOL: 'BOOL'; BOOLEAN: 'BOOLEAN'; BOTH: 'BOTH'; BRANCH: 'BRANCH'; BREADTH: 'BREADTH'; BREAK: 'BREAK'; BSTRING: 'BSTRING'; BTREE: 'BTREE'; BUFFER: 'BUFFER'; BUILD: 'BUILD'; BULK: 'BULK'; BULK_EXCEPTION: 'BULK_EXCEPTION'; BULK_ROWCOUNT: 'BULK_ROWCOUNT'; BY: 'BY'; BYDAY: 'BYDAY'; BYHOUR: 'BYHOUR'; BYMINUTE: 'BYMINUTE'; BYMONTH: 'BYMONTH'; BYMONTHDAY: 'BYMONTHDAY'; BYSECOND: 'BYSECOND'; BYTE: 'BYTE'; BYWEEKNO: 'BYWEEKNO'; BYYEARDAY: 'BYYEARDAY'; CACHE: 'CACHE'; CALCULATE: 'CALCULATE'; CALL: 'CALL'; CASCADE: 'CASCADE'; CASCADED: 'CASCADED'; CASE: 'CASE'; CASE_SENSITIVE: 'CASE_SENSITIVE'; CAST: 'CAST'; CATALOG: 'CATALOG'; CATCH: 'CATCH'; CHAIN: 'CHAIN'; CHANGE: 'CHANGE'; CHAR: 'CHAR'; CHARACTER: 'CHARACTER'; CHARACTERISTICS: 'CHARACTERISTICS'; CHECK: 'CHECK'; CHECKPOINT: 'CHECKPOINT'; CIPHER: 'CIPHER'; CLASS: 'CLASS'; CLOB: 'CLOB'; CLOSE: 'CLOSE'; CLUSTER: 'CLUSTER'; CLUSTERBTR: 'CLUSTERBTR'; COLLATE: 'COLLATE'; COLLATION: 'COLLATION'; COLLECT: 'COLLECT'; COLUMN: 'COLUMN'; COLUMNS: 'COLUMNS'; COMMENT: 'COMMENT'; COMMIT: 'COMMIT'; COMMITTED: 'COMMITTED'; COMMITWORK: 'COMMITWORK'; COMPILE: 'COMPILE'; COMPLETE: 'COMPLETE'; COMPRESS: 'COMPRESS'; COMPRESSED: 'COMPRESSED'; CONDITIONAL: 'CONDITIONAL'; CONNECT: 'CONNECT'; CONNECT_BY_IS_CYCLE: 'CONNECT_BY_IS_CYCLE'; CONNECT_BY_IS_LEAF: 'CONNECT_BY_IS_LEAF'; CONNECT_BY_ROOT: 'CONNECT_BY_ROOT'; CONNECT_IDLE_TIME: 'CONNECT_IDLE_TIME'; CONNECT_TIME: 'CONNECT_TIME'; CONST: 'CONST'; CONSTANT: 'CONSTANT'; CONSTRAINT: 'CONSTRAINT'; CONSTRAINTS: 'CONSTRAINTS'; CONSTRUCTOR: 'CONSTRUCTOR'; CONSTR_OP: 'CONSTR_OP'; CONTAINS: 'CONTAINS'; CONTEXT: 'CONTEXT'; CONTINUE: 'CONTINUE'; CONVERT: 'CONVERT'; COPY: 'COPY'; CORRESPONDING: 'CORRESPONDING'; CORRUPT: 'CORRUPT'; COUNT: 'COUNT'; COUNTER: 'COUNTER'; CPU_PER_CALL: 'CPU_PER_CALL'; CPU_PER_SESSION: 'CPU_PER_SESSION'; CREATE: 'CREATE'; CROSS: 'CROSS'; CRYPTO: 'CRYPTO'; CTLFILE: 'CTLFILE'; CUBE: 'CUBE'; CUMULATIVE: 'CUMULATIVE'; CURRENT: 'CURRENT'; CURRENT_SCHEMA: 'CURRENT_SCHEMA'; CURRENT_USER: 'CURRENT_USER'; CURSOR: 'CURSOR'; CYCLE: 'CYCLE'; DAILY: 'DAILY'; DANGLING: 'DANGLING'; DATA: 'DATA'; DATABASE: 'DATABASE'; DATAFILE: 'DATAFILE'; DATE: 'DATE'; DATEADD: 'DATEADD'; DATEDIFF: 'DATEDIFF'; DATEPART: 'DATEPART'; DATETIME: 'DATETIME'; DAY: 'DAY'; DBFILE: 'DBFILE'; DDL: 'DDL'; DDL_CLONE: 'DDL_CLONE'; DEBUG: 'DEBUG'; DEC: 'DEC'; DECIMAL: 'DECIMAL'; DECLARE: 'DECLARE'; DECODE: 'DECODE'; DEFAULT: 'DEFAULT'; DEFERRABLE: 'DEFERRABLE'; DEFERRED: 'DEFERRED'; DEFINER: 'DEFINER'; DELETE: 'DELETE'; DELETING: 'DELETING'; DELIMITED: 'DELIMITED'; DELTA: 'DELTA'; DEMAND: 'DEMAND'; DENSE_RANK: 'DENSE_RANK'; DEPTH: 'DEPTH'; DEREF: 'DEREF'; DESC: 'DESC'; DETACH: 'DETACH'; DETERMINISTIC: 'DETERMINISTIC'; DEVICE: 'DEVICE'; DIAGNOSTICS: 'DIAGNOSTICS'; DICTIONARY: 'DICTIONARY'; DIRECTORY: 'DIRECTORY'; DISABLE: 'DISABLE'; DISCONNECT: 'DISCONNECT'; DISKGROUP: 'DISKGROUP'; DISKSPACE: 'DISKSPACE'; DISTINCT: 'DISTINCT'; DISTRIBUTED: 'DISTRIBUTED'; DML: 'DML'; DO: 'DO'; DOMAIN: 'DOMAIN'; DOUBLE: 'DOUBLE'; DOWN: 'DOWN'; DROP: 'DROP'; DUMP: 'DUMP'; EACH: 'EACH'; EDITIONABLE: 'EDITIONABLE'; ELSE: 'ELSE'; ELSEIF: ('ELSEIF' | 'ELSIF'); EMPTY: 'EMPTY'; ENABLE: 'ENABLE'; ENCRYPT: 'ENCRYPT'; ENCRYPTION: 'ENCRYPTION'; END: 'END'; EQU: 'EQU'; ERROR: 'ERROR'; ERRORS: 'ERRORS'; ESCAPE: 'ESCAPE'; EVALNAME: 'EVALNAME'; EVENTINFO: 'EVENTINFO'; EVENTS: 'EVENTS'; EVERY: 'EVERY'; EXCEPT: 'EXCEPT'; EXCEPTION: 'EXCEPTION'; EXCEPTIONS: 'EXCEPTIONS'; EXCEPTION_INIT: 'EXCEPTION_INIT'; EXCHANGE: 'EXCHANGE'; EXCLUDE: 'EXCLUDE'; EXCLUDING: 'EXCLUDING'; EXCLUSIVE: 'EXCLUSIVE'; EXECUTE: 'EXECUTE'; EXISTS: 'EXISTS'; EXIT: 'EXIT'; EXPIRE: 'EXPIRE'; EXPLAIN: 'EXPLAIN'; EXTENDS: 'EXTENDS'; EXTERN: 'EXTERN'; EXTERNAL: 'EXTERNAL'; EXTERNALLY: 'EXTERNALLY'; EXTRACT: 'EXTRACT'; FAILED_LOGIN_ATTEMPS: 'FAILED_LOGIN_ATTEMPS'; FAILED_LOGIN_ATTEMPTS: 'FAILED_LOGIN_ATTEMPTS'; FALSE: 'FALSE'; FAST: 'FAST'; FEB: 'FEB'; FETCH: 'FETCH'; FIELDS: 'FIELDS'; FILE: 'FILE'; FILEGROUP: 'FILEGROUP'; FILESIZE: 'FILESIZE'; FILLFACTOR: 'FILLFACTOR'; FINAL: 'FINAL'; FINALLY: 'FINALLY'; FIRST: 'FIRST'; FLASHBACK: 'FLASHBACK'; FLOAT: 'FLOAT'; FOLLOWING: 'FOLLOWING'; FOR: 'FOR'; FORALL: 'FORALL'; FORCE: 'FORCE'; FOREIGN: 'FOREIGN'; FORMAT: 'FORMAT'; FOUND: 'FOUND'; FREQ: 'FREQ'; FREQUENCE: 'FREQUENCE'; FRI: 'FRI'; FROM: 'FROM'; FULL: 'FULL'; FULLY: 'FULLY'; FUNCTION: 'FUNCTION'; GENERATE: 'GENERATE'; GENERATED: 'GENERATED'; GET: 'GET'; GLOBAL: 'GLOBAL'; GLOBALLY: 'GLOBALLY'; GOTO: 'GOTO'; GRANT: 'GRANT'; GREAT: 'GREAT'; GROUP: 'GROUP'; GROUPING: 'GROUPING'; HASH: 'HASH'; HASHPARTMAP: 'HASHPARTMAP'; HAVING: 'HAVING'; HEXTORAW: 'HEXTORAW'; HIDDEN_KEYWORD: 'HIDDEN'; HIGH: 'HIGH'; HOLD: 'HOLD'; HOUR: 'HOUR'; HOURLY: 'HOURLY'; HUGE: 'HUGE'; IDENTIFIED: 'IDENTIFIED'; IDENTIFIER_KEYWORD: 'IDENTIFIER'; IDENTITY: 'IDENTITY'; IDENTITY_INSERT: 'IDENTITY_INSERT'; IF: 'IF'; IFNULL: 'IFNULL'; IGNORE: 'IGNORE'; IGNORE_ROW_ON_DUPKEY_INDEX: 'IGNORE_ROW_ON_DUPKEY_INDEX'; IMAGE: 'IMAGE'; IMMEDIATE: 'IMMEDIATE'; IN: 'IN'; INCLUDE: 'INCLUDE'; INCLUDING: 'INCLUDING'; INCREASE: 'INCREASE'; INCREMENT: 'INCREMENT'; INDEX: 'INDEX'; INDEXES: 'INDEXES'; INDICES: 'INDICES'; INITIAL: 'INITIAL'; INITIALIZED: 'INITIALIZED'; INITIALLY: 'INITIALLY'; INLINE: 'INLINE'; INNER: 'INNER'; INNERID: 'INNERID'; INPUT: 'INPUT'; INSENSITIVE: 'INSENSITIVE'; INSERT: 'INSERT'; INSERTING: 'INSERTING'; INSTANCE: 'INSTANCE'; INSTANTIABLE: 'INSTANTIABLE'; INSTEAD: 'INSTEAD'; INT: 'INT'; INTEGER: 'INTEGER'; INTENT: 'INTENT'; INTERSECT: 'INTERSECT'; INTERVAL: 'INTERVAL'; INTO: 'INTO'; INVISIBLE: 'INVISIBLE'; IS: 'IS'; ISOLATION: 'ISOLATION'; JAN: 'JAN'; JAVA: 'JAVA'; JOB: 'JOB'; JOIN: 'JOIN'; JSON: 'JSON'; JSON_TABLE: 'JSON_TABLE'; JUL: 'JUL'; JUN: 'JUN'; KEEP: 'KEEP'; KEY: 'KEY'; KEYS: 'KEYS'; LABEL: 'LABEL'; LARGE: 'LARGE'; LAST: 'LAST'; LAST2: 'LAST2'; LAX: 'LAX'; LEAD: 'LEADING'; LEFT: 'LEFT'; LEFTARG: 'LEFTARG'; LESS: 'LESS'; LEVEL: 'LEVEL'; LEVELS: 'LEVELS'; LEXER: 'LEXER'; LIKE: 'LIKE'; LIMIT: 'LIMIT'; LINK: 'LINK'; LIST: 'LIST'; LNNVL: 'LNNVL'; LOB: 'LOB'; LOCAL: 'LOCAL'; LOCALLY: 'LOCALLY'; LOCAL_OBJECT: 'LOCAL_OBJECT'; LOCATION: 'LOCATION'; LOCK: 'LOCK'; LOCKED: 'LOCKED'; LOG: 'LOG'; LOGFILE: 'LOGFILE'; LOGGING: 'LOGGING'; LOGIC: 'LOGIC'; LOGIN: 'LOGIN'; LOGOFF: 'LOGOFF'; LOGON: 'LOGON'; LOGOUT: 'LOGOUT'; LONG: 'LONG'; LONGVARBINARY: 'LONGVARBINARY'; LONGVARCHAR: 'LONGVARCHAR'; LOOP: 'LOOP'; LSN: 'LSN'; MANUAL: 'MANUAL'; MAP: 'MAP'; MAPPED: 'MAPPED'; MAR: 'MAR'; MATCH: 'MATCH'; MATCHED: 'MATCHED'; MATERIALIZED: 'MATERIALIZED'; MAX: 'MAX'; MAXPIECESIZE: 'MAXPIECESIZE'; MAXSIZE: 'MAXSIZE'; MAXVALUE: 'MAXVALUE'; MAX_RUN_DURATION: 'MAX_RUN_DURATION'; MAY: 'MAY'; MEMBER: 'MEMBER'; MEMORY: 'MEMORY'; MEM_SPACE: 'MEM_SPACE'; MERGE: 'MERGE'; MICRO: 'MICRO'; MIN: 'MIN'; MINEXTENTS: 'MINEXTENTS'; MINUS: 'MINUS'; MINUTE: 'MINUTE'; MINUTELY: 'MINUTELY'; MINVALUE: 'MINVALUE'; MIRROR: 'MIRROR'; MOD: 'MOD'; MODE: 'MODE'; MODIFY: 'MODIFY'; MON: 'MON'; MONEY: 'MONEY'; MONITORING: 'MONITORING'; MONTH: 'MONTH'; MONTHLY: 'MONTHLY'; MOUNT: 'MOUNT'; MOVE: 'MOVE'; MOVEMENT: 'MOVEMENT'; MULTISET: 'MULTISET'; NATIONAL: 'NATIONAL'; NATURAL: 'NATURAL'; NCHAR: 'NCHAR'; NCHARACTER: 'NCHARACTER'; NESTED_PATH: 'NESTED_PATH'; NEVER: 'NEVER'; NEW: 'NEW'; NEXT: 'NEXT'; NO: 'NO'; NOARCHIVELOG: 'NOARCHIVELOG'; NOAUDIT: 'NOAUDIT'; NOBRANCH: 'NOBRANCH'; NOCACHE: 'NOCACHE'; NOCOPY: 'NOCOPY'; NOCYCLE: 'NOCYCLE'; NODE: 'NODE'; NOLOCK: 'NOLOCK'; NOLOGGING: 'NOLOGGING'; NOMAXVALUE: 'NOMAXVALUE'; NOMINVALUE: 'NOMINVALUE'; NOMONITORING: 'NOMONITORING'; NONE: 'NONE'; NONEDITIONABLE: 'NONEDITIONABLE'; NOORDER: 'NOORDER'; NOPARALLEL: 'NOPARALLEL'; NORMAL: 'NORMAL'; NOROWDEPENDENCIES: 'NOROWDEPENDENCIES'; NOSORT: 'NOSORT'; NOT: 'NOT'; NOTFOUND: 'NOT_FOUND'; NOT_ALLOW_DATETIME: 'NOT_ALLOW_DATETIME'; NOT_ALLOW_IP: 'NOT_ALLOW_IP'; NOV: 'NOV'; NOVALIDATE: 'NOVALIDATE'; NOWAIT: 'NOWAIT'; NULL: 'NULL'; NULLS: 'NULLS'; NUMBER: 'NUMBER'; NUMERIC: 'NUMERIC'; OBJECT: 'OBJECT'; OCT: 'OCT'; OF: 'OF'; OFF: 'OFF'; OFFLINE: 'OFFLINE'; OFFSET: 'OFFSET'; OIDINDEX: 'OIDINDEX'; OLD: 'OLD'; ON: 'ON'; ONCE: 'ONCE'; ONLINE: 'ONLINE'; ONLY: 'ONLY'; OPEN: 'OPEN'; OPERATOR: 'OPERATOR'; OPTIMIZE: 'OPTIMIZE'; OPTION: 'OPTION'; OR: 'OR'; ORDER: 'ORDER'; ORDINALITY: 'ORDINALITY'; OUT: 'OUT'; OUTER: 'OUTER'; OVER: 'OVER'; OVERLAPS: 'OVERLAPS'; OVERLAY: 'OVERLAY'; OVERRIDE: 'OVERRIDE'; OVERRIDING: 'OVERRIDING'; PACKAGE: 'PACKAGE'; PAD: 'PAD'; PAGE: 'PAGE'; PARALLEL: 'PARALLEL'; PARALLEL_ENABLE: 'PARALLEL_ENABLE'; PARMS: 'PARMS'; PARTIAL: 'PARTIAL'; PARTITION: 'PARTITION'; PARTITIONS: 'PARTITIONS'; PASSING: 'PASSING'; PASSWORD: 'PASSWORD'; PASSWORD_GRACE_TIME: 'PASSWORD_GRACE_TIME'; PASSWORD_LIFE_TIME: 'PASSWORD_LIFE_TIME'; PASSWORD_LOCK_TIME: 'PASSWORD_LOCK_TIME'; PASSWORD_POLICY: 'PASSWORD_POLICY'; PASSWORD_REUSE_MAX: 'PASSWORD_REUSE_MAX'; PASSWORD_REUSE_TIME: 'PASSWORD_REUSE_TIME'; PATH: 'PATH'; PENDANT: 'PENDANT'; PERCENT: 'PERCENT'; PIPE: 'PIPE'; PIPELINED: 'PIPELINED'; PIVOT: 'PIVOT'; PLACING: 'PLACING'; PRAGMA: 'PRAGMA'; PREBUILT: 'PREBUILT'; PRECEDING: 'PRECEDING'; PRECISION: 'PRECISION'; PRESERVE: 'PRESERVE'; PRETTY: 'PRETTY'; PRIMARY: 'PRIMARY'; PRINT: 'PRINT'; PRIOR: 'PRIOR'; PRIVATE: 'PRIVATE'; PRIVILEGE: 'PRIVILEGE'; PRIVILEGES: 'PRIVILEGES'; PROCEDURE: 'PROCEDURE'; PROFILE: 'PROFILE'; PROTECTED: 'PROTECTED'; PT_BULK_ROWCOUNT: 'PT_BULK_ROWCOUNT'; PT_ROWCOUNT: 'PT_ROWCOUNT'; PT_ROWCOUNT2: 'PT_ROWCOUNT2'; PUBLIC: 'PUBLIC'; PURGE: 'PURGE'; QUERY: 'QUERY'; QUERY_REWRITE_INTEGRITY: 'QUERY_REWRITE_INTEGRITY'; QUOTA: 'QUOTA'; RAISE: 'RAISE'; RANDOMLY: 'RANDOMLY'; RANGE: 'RANGE'; RAWTOHEX: 'RAWTOHEX'; READ: 'READ'; READONLY: 'READONLY'; READ_PER_CALL: 'READ_PER_CALL'; READ_PER_SESSION: 'READ_PER_SESSION'; REAL: 'REAL'; REBUILD: 'REBUILD'; RECORD: 'RECORD'; RECORDS: 'RECORDS'; RECURSIVE: 'RECURSIVE'; REDUCED: 'REDUCED'; REF: 'REF'; REFERENCE: 'REFERENCE'; REFERENCES: 'REFERENCES'; REFERENCING: 'REFERENCING'; REFRESH: 'REFRESH'; REJECT: 'REJECT'; RELATED: 'RELATED'; RELATIVE: 'RELATIVE'; RENAME: 'RENAME'; REPEAT: 'REPEAT'; REPEATABLE: 'REPEATABLE'; REPLACE: 'REPLACE'; REPLAY: 'REPLAY'; REPLICATE: 'REPLICATE'; RESPECT: 'RESPECT'; RESIZE: 'RESIZE'; RESTORE: 'RESTORE'; RESTRICT: 'RESTRICT'; RESTRICT_REFERENCES: 'RESTRICT_REFERENCES'; RESULT: 'RESULT'; RESULT_CACHE: 'RESULT_CACHE'; RETURN: 'RETURN'; RETURNING: 'RETURNING'; REUSE: 'REUSE'; REVERSE: 'REVERSE'; REVOKE: 'REVOKE'; REWRITE: 'REWRITE'; RIGHT: 'RIGHT'; RIGHTARG: 'RIGHTARG'; ROLE: 'ROLE'; ROLLBACK: 'ROLLBACK'; ROLLFILE: 'ROLLFILE'; ROLLUP: 'ROLLUP'; ROOT: 'ROOT'; ROW: 'ROW'; ROWCOUNT: 'ROWCOUNT'; ROWCOUNT2: 'ROWCOUNT2'; ROWDEPENDENCIES: 'ROWDEPENDENCIES'; ROWID: 'ROWID'; ROWNUM: 'ROWNUM'; ROWS: 'ROWS'; ROWTYPE: 'ROWTYPE'; RULE: 'RULE'; SALT: 'SALT'; SAMPLE: 'SAMPLE'; SAT: 'SAT'; SAVE: 'SAVE'; SAVEPOINT: 'SAVEPOINT'; SBYTE: 'SBYTE'; SCHEMA: 'SCHEMA'; SCHEMABINDING: 'SCHEMABINDING'; SCN: 'SCN'; SCOPE: 'SCOPE'; SCROLL: 'SCROLL'; SEALED: 'SEALED'; SEARCH: 'SEARCH'; SECOND: 'SECOND'; SECONDLY: 'SECONDLY'; SECTION: 'SECTION'; SEED: 'SEED'; SELECT: 'SELECT'; SELF: 'SELF'; SENSITIVE: 'SENSITIVE'; SEP: 'SEP'; SEQUENCE: 'SEQUENCE'; SERERR: 'SERERR'; SERIALIZABLE: 'SERIALIZABLE'; SERVER: 'SERVER'; SESSION: 'SESSION'; SESSION_PER_USER: 'SESSION_PER_USER'; SET: 'SET'; SETS: 'SETS'; SHADOW: 'SHADOW'; SHARE: 'SHARE'; SHORT: 'SHORT'; SHUTDOWN: 'SHUTDOWN'; SIBLINGS: 'SIBLINGS'; SIMPLE: 'SIMPLE'; SINCE: 'SINCE'; SIZE: 'SIZE'; SIZEOF: 'SIZEOF'; SKIP_KEYWORD: 'SKIP'; SMALLINT: 'SMALLINT'; SNAPSHOT: 'SNAPSHOT'; SOME: 'SOME'; SOUND: 'SOUND'; SPACE_KEYWORD: 'SPACE'; SPAN: 'SPAN'; SPATIAL: 'SPATIAL'; SPEED: 'SPEED'; SPFILE: 'SPFILE'; SPLIT: 'SPLIT'; SQL: 'SQL'; STANDBY: 'STANDBY'; START: 'START'; STARTUP: 'STARTUP'; STAT: 'STAT'; STATEMENT: 'STATEMENT'; STATIC: 'STATIC'; STDDEV: 'STDDEV'; STOP: 'STOP'; STORAGE: 'STORAGE'; STORE: 'STORE'; STRICT: 'STRICT'; STRING: 'STRING'; STRIPING: 'STRIPING'; STRUCT: 'STRUCT'; STYLE: 'STYLE'; SUBPARTITION: 'SUBPARTITION'; SUBPARTITIONS: 'SUBPARTITIONS'; SUBSCRIBE: 'SUBSCRIBE'; SUBSTITUTABLE: 'SUBSTITUTABLE'; SUBSTRING: 'SUBSTRING'; SUBTYPE: 'SUBTYPE'; SUCCESSFUL: 'SUCCESSFUL'; SUM: 'SUM'; SUN: 'SUN'; SUSPEND: 'SUSPEND'; SWITCH: 'SWITCH'; SYNC: 'SYNC'; SYNCHRONOUS: 'SYNCHRONOUS'; SYNONYM: 'SYNONYM'; SYSTEM: 'SYSTEM'; SYS_CONNECT_BY_PATH: 'SYS_CONNECT_BY_PATH'; TABLE: 'TABLE'; TABLESPACE: 'TABLESPACE'; TABLESPACESET: 'TABLESPACESET'; TASK: 'TASK'; TEMPLATE: 'TEMPLATE'; TEMPORARY: 'TEMPORARY'; TEXT: 'TEXT'; THAN: 'THAN'; THEN: 'THEN'; THREAD: 'THREAD'; THROUGH: 'THROUGH'; THROW: 'THROW'; THU: 'THU'; TIES: 'TIES'; TIME: 'TIME'; TIMER: 'TIMER'; TIMES: 'TIMES'; TIMESTAMP: 'TIMESTAMP'; TIMESTAMPADD: 'TIMESTAMPADD'; TIMESTAMPDIFF: 'TIMESTAMPDIFF'; TIME_ZONE: 'TIME_ZONE'; TINYINT: 'TINYINT'; TO: 'TO'; TOP: 'TOP'; TRACE: 'TRACE'; TRACKING: 'TRACKING'; TRAIL: 'TRAILING'; TRANSACTION: 'TRANSACTION'; TRANSACTIONAL: 'TRANSACTIONAL'; TRIGGER: 'TRIGGER'; TRIGGERS: 'TRIGGERS'; TRIM: 'TRIM'; TRUE: 'TRUE'; TRUNCATE: 'TRUNCATE'; TRUNCSIZE: 'TRUNCSIZE'; TRXID: 'TRXID'; TRY: 'TRY'; TUE: 'TUE'; TYPE: 'TYPE'; TYPEDEF: 'TYPEDEF'; TYPEOF: 'TYPEOF'; UINT: 'UINT'; ULONG: 'ULONG'; UNBOUNDED: 'UNBOUNDED'; UNCOMMITTED: 'UNCOMMITTED'; UNCONDITIONAL: 'UNCONDITIONAL'; UNDER: 'UNDER'; UNION: 'UNION'; UNIQUE: 'UNIQUE'; UNLIMITED: 'UNLIMITED'; UNLOCK: 'UNLOCK'; UNPIVOT: 'UNPIVOT'; UNTIL: 'UNTIL'; UNUSABLE: 'UNUSABLE'; UP: 'UP'; UPDATE: 'UPDATE'; UPDATING: 'UPDATING'; USAGE: 'USAGE'; USER: 'USER'; USE_HASH: 'USE_HASH'; USE_MERGE: 'USE_MERGE'; USE_NL: 'USE_NL'; USE_NL_WITH_INDEX: 'USE_NL_WITH_INDEX'; USHORT: 'USHORT'; USING: 'USING'; VALUE: 'VALUE'; VALUES: 'VALUES'; VARBINARY_KEYWORD: 'VARBINARY'; VARCHAR: 'VARCHAR'; VARCHAR2: 'VARCHAR2'; VARIANCE: 'VARIANCE'; VARRAY: 'VARRAY'; VARYING: 'VARYING'; VERIFY: 'VERIFY'; VERSIONS: 'VERSIONS'; VERSIONS_ENDTIME: 'VERSIONS_ENDTIME'; VERSIONS_ENDTRXID: 'VERSIONS_ENDTRXID'; VERSIONS_OPERATION: 'VERSIONS_OPERATION'; VERSIONS_STARTTIME: 'VERSIONS_STARTTIME'; VERSIONS_STARTTRXID: 'VERSIONS_STARTTRXID'; VERTICAL: 'VERTICAL'; VIEW: 'VIEW'; VIRTUAL: 'VIRTUAL'; VISIBLE: 'VISIBLE'; VOID: 'VOID'; VSIZE: 'VSIZE'; WAIT: 'WAIT'; WED: 'WED'; WEEK: 'WEEK'; WEEKLY: 'WEEKLY'; WHEN: 'WHEN'; WHENEVER: 'WHENEVER'; WHERE: 'WHERE'; WHILE: 'WHILE'; WITH: 'WITH'; WITHIN: 'WITHIN'; WITHOUT: 'WITHOUT'; WORK: 'WORK'; WRAPPED: 'WRAPPED'; WRAPPER: 'WRAPPER'; WRITE: 'WRITE'; XML: 'XML'; XMLAGG: 'XMLAGG'; XMLATTRIBUTES: 'XMLATTRIBUTES'; XMLELEMENT: 'XMLELEMENT'; XMLPARSE: 'XMLPARSE'; XMLTABLE: 'XMLTABLE'; YEAR: 'YEAR'; YEARLY: 'YEARLY'; ZONE: 'ZONE'; // Skip WHILE_SPACE: [ \t\r\n]+ -> skip; WHILE_COMMENT: '/*' (COMMENT | .)*? '*/' -> channel(HIDDEN); LINE_COMMENT: '--' ~[\r\n]* -> channel(HIDDEN); // Operators OP_ASSIGN: ':='; OP_ADD_ASSIGN: '+='; OP_SUB_ASSIGN: '-='; OP_MULT_ASSIGN: '*='; OP_DIV_ASSIGN: '/='; OP_MOD_ASSIGN: '%='; OP_AND_ASSIGN: '&='; OP_XOR_ASSIGN: '^='; OP_OR_ASSIGN: '|='; OP_CONSTR: '||'; OP_CAST: '::'; OP_SHIFT_LEFT: '<<'; OP_SHIFT_RIGHT: '>>'; OPR_NE: ('!='| '<>'); OPR_LE: '<='; OPR_GE: '>='; OPR_EQ: '=='; OPR_AEQ: '=>'; OPR_INC: '++'; OPR_DEC: '--'; //OPR_EQ_RIGHT_JOIN: '=*'; OP_SHIFT_RIGHT_ASSIGN: '>>='; OP_SHIFT_LEFT_ASSIGN: '<<='; OP_EQUAL: '='; OP_NOT: '!'; OP_PLUS: '+'; OP_MINUS: '-'; OP_STAR: '*'; OP_DIVIDE: '/'; OP_MOD: '%'; OP_GREATER: '>'; OP_LESS: '<'; OP_BIT_NOT: '~'; OP_BIT_OR: '|'; OP_BIT_AND: '&'; OP_BIT_XOR: '^'; // Symbols BOUNDARY: '..'; DOT: '.'; UNDERLINE: '_'; AT: '@'; SHARP: '#'; DOLLAR: '$'; LR_BRACKET: '('; RR_BRACKET: ')'; LR_SQUARE_BRACKET: '['; RR_SQUARE_BRACKET: ']'; LR_BRACES: '{'; RR_BRACES: '}'; COMMA: (',' | '\uff0c'); SEMI: (';' | '\uff1b'); COLON: ':'; PLACEHOLDER: '?'; OP_U_OPRT: OP_CHARS+?; // Var LT_GLOBAL_VAR: '@''@' IDENTIFIER; LT_IDENTIFIER: ( IDENTIFIERX | IDENTIFIER | LT_DQUOTE_STRING ); // Const LT_STRING: 'N'? '\'' (~'\'' | '\'\'')* '\''; LT_BITSTRING: [B] '\'' [^']* '\''; LT_INTEGER: DIGIT+; LT_BINTEGER: '0' [X] (DIGIT|[A-F])+; //LT_BIGINTEGER: DIGIT {20,}; //LT_DECIMAL: ( (DIGIT* '.' DIGIT+)|(DIGIT+ '.' DIGIT*) ); LT_DECIMAL: (DIGIT* '.' DIGIT+) ; //LT_REAL: ((((DIGIT* '.' DIGIT+)|(DIGIT+ '.' DIGIT*)|(DIGIT+))([E][-+]? DIGIT+))|((DIGIT* '.' DIGIT+)|(DIGIT+ '.' DIGIT*)|(DIGIT+))) ([DF])?|{BINARY_FLOAT_INFINITY}|{BINARY_FLOAT_NAN}|{binary_double_infinity}|{binary_double_nan}; LT_REAL: (DIGIT+ | LT_DECIMAL)('E'([+-]? DIGIT+)?); // frament fragment DIGIT: [0-9]; //fragment DIGIT_PARAM: '@' DIGIT+; fragment CLETTER_H: [\u0080-\u00FF]; fragment CLETTER_T: [\u0000-\u00FF]; fragment CLETTER: [\u4e00-\u9fa5]; fragment LETTER1: (CLETTER | [_A-Z$#]); fragment LETTER_OR_DIGIT1: (CLETTER | [_A-Z0-9$#]); fragment LETTER2: (CLETTER_H | [_A-Z$#]); fragment LETTER_OR_DIGIT2: (CLETTER_H | [_A-Z0-9$#]); fragment IDENTIFIERX: LETTER1 LETTER_OR_DIGIT1*; fragment IDENTIFIER: LETTER2 LETTER_OR_DIGIT2*; fragment LT_DQUOTE_STRING: '"' ~'"'+ '"'; //fragment LT_BQUOTE_STRING: '`' ~'`'+ '`'; //fragment LT_BRACKET_STRING: '[' (~']' | ']' ']')* ']'; fragment NOLETERDIGIT: [^_A-Z#$0-9]; fragment OP_CHARS: [<>=+\-&|*%/^?@!~`]; fragment BINARY_FLOAT_INFINITY: 'BINARY_FLOAT_INFINITY'; fragment BINARY_FLOAT_NAN: 'BINARY_FLOAT_NAN'; fragment BINARY_DOUBLE_INFINITY: 'BINARY_DOUBLE_INFINITY'; fragment BINARY_DOUBLE_NAN: 'BINARY_DOUBLE_NAN'; ================================================ FILE: superior-dameng-parser/src/main/antlr4/io/github/melin/superior/parser/dameng/antlr4/DmSqlParser.g4 ================================================ parser grammar DmSqlParser; options { tokenVocab=DmSqlLexer; } dmprogram : sql_clauses (SEMI sql_clauses)* SEMI? EOF ; sql_clauses : ddlsql | dmlsql | privsql | othersql | utilsql | explainsql | declare_block ; ddlsql : alter_proc_stmt | alter_func_stmt | alter_package_stmt | alter_table_stmt | alter_index_stmt | comment_stmt | alter_trigger_stmt | alter_view_stmt | alter_materialized_view_stmt | refresh_materialized_view_stmt | create_tablespace_stmt | create_func_stmt | create_proc_stmt | create_trigger_stmt | create_view_stmt | create_materialized_view_stmt | create_materialized_view_log_stmt | alter_database_stmt | alter_tablespace_stmt | create_user_stmt | alter_user_stmt | create_profile_stmt | alter_profile_stmt | create_role_stmt | create_sequence_stmt | create_contextindex_stmt | drop_contextindex_stmt | alter_contextindex_stmt | create_audit_rule_stmt | create_dblink_stmt | create_package_stmt | create_package_body_stmt | create_type_stmt | create_type_body_stmt | create_synonym_stmt | create_crypto_stmt | alter_crypto_stmt | alter_session_stmt | create_domain_stmt | create_character_set_stmt | create_collation_stmt | alter_system_set_stmt | create_context_stmt | create_directory_stmt | create_tablespace_set_stmt | alter_tablespace_set_stmt | create_operator_stmt | drop_operator_stmt | flashback_tab_stmt ; dmlsql : call_proc_stmt | delete_stmt | insert_stmt | select_stmt ur_option? | update_stmt | merge_into_stmt | trunc_table_stmt | create_table_stmt | drop_stmt | begin_trans_stmt | commit_trans_stmt | rollback_stmt | savepoint_stmt | create_index_stmt | set_trans_stmt | lock_table_stmt | set_identins_stmt | set_session_stmt | stat_on_org_stmt | create_partition_group_stmt | fetch_stmt | open_stmt | close_cursor_stmt ; privsql : grant_stmt | revoke_stmt ; othersql : connect_stmt | disconnect_stmt | set_schema_stmt | backup_stmt | restore_stmt ; utilsql : alter_diskgroup_stmt | shutdown_stmt | repeat_interval_stmt | create_schema_stmt | assign_stmt ; explainsql : EXPLAIN (dmlsql | assign_stmt) (COMMA (dmlsql | assign_stmt))* | EXPLAIN (AS raw_id)? FOR (dmlsql | ddlsql | privsql |othersql) ; shutdown_stmt : SHUTDOWN ABORT | SHUTDOWN IMMEDIATE | SHUTDOWN NORMAL | SHUTDOWN TRANSACTIONAL local? | STOP INSTANCE ; alter_diskgroup_stmt : alter_tag DISKGROUP LT_STRING pathname CORRUPT ; local : LOCAL ; dmsubprogram : label_list_options? decl_var_cur_list_options? BEGIN plbody except_option? blk_end_option ; declare_block : label_list_options? decl_var_cur_list_1? BEGIN plbody except_option? blk_end_option ; decl_var_cur_list_options : DECLARE | DECLARE decl_var_cur_list | decl_var_cur_list ; decl_var_cur_list_1 : DECLARE | DECLARE decl_var_cur_list ; decl_var_cur_list : ( decl_variable | decl_except | pragma_def | (decl_cursor SEMI) | decl_plsql_type | package_body_def | subpg_decl_stmt )+ ; decl_plsql_type : TYPE variable_name IS plsql_type_def SEMI | SUBTYPE variable_name IS sub_plsql_datatype not_null? SEMI ; plsql_type_def : RECORD '(' rec_item_def_list ')' | REF CURSOR | REF CURSOR RETURN plsql_datatype | ARRAY plsql_datatype rank_specifiers | REF CURSOR '(' param_def_list ')' | REF CURSOR '(' param_def_list ')' RETURN plsql_datatype | ARRAY plsql_datatype '[' lt_int_lst ']' | plsql_datatype | TABLE OF plsql_datatype not_null? | TABLE OF plsql_datatype not_null? INDEX BY plsql_datatype | VARRAY '(' LT_INTEGER ')' OF plsql_datatype not_null? ; lt_int_lst : LT_INTEGER | lt_int_lst COMMA LT_INTEGER ; rec_item_def_list : rec_item_def (COMMA rec_item_def)* ; rec_item_def : id plsql_datatype opt_rank_specifier2 not_null? default_clause_option? ; decl_variable : variable_name_list plsql_datatype not_null? default_clause_option? SEMI | variable_name_list AS plsql_datatype not_null? default_clause_option? SEMI | variable_name_list CONSTANT plsql_datatype not_null? default_clause_option? SEMI ; not_null : NOT NULL ; plsql_datatype : datatype | qualified_name dblink_clause? '%' TYPE | qualified_name dblink_clause? '%' ROWTYPE | REF qualified_name | CURSOR ; default_clause_option : DEFAULT default_exp | assign_op default_exp ; variable_name_list : variable_name (COMMA variable_name)* ; decl_except : variable_name_list EXCEPTION FOR '-' LT_INTEGER SEMI | variable_name_list EXCEPTION FOR '-' LT_INTEGER COMMA LT_STRING SEMI ; pragma_def : PRAGMA pragma SEMI ; pragma : EXCEPTION_INIT '(' except_name COMMA '-' LT_INTEGER ')' | AUTONOMOUS_TRANSACTION ; plbody : (plsql SEMI)+ ; ss_plbody : plblock ; label : label_demiliter_l label_name label_demiliter_r ; label_list : label+ ; label_list_options : label_list ; label_demiliter_l : OP_SHIFT_LEFT ; label_demiliter_r : OP_SHIFT_RIGHT ; plsql : dmlsql | if_stmt | assign_stmt | goto_stmt | while_stmt | loop_stmt | repeat_stmt | for_stmt | return_stmt | plblock | raise_stmt | exit_stmt | print_stmt | execute_stmt | continue_stmt | case_stmt | null_stmt | label plsql | forall_stmt | pipe_row_stmt ; ur_option : WITH id ; flashback_trig_enable : ENABLE TRIGGERS | DISABLE TRIGGERS ; scn_or_lsn : SCN | LSN ; full_table_name_list : full_table_name (COMMA full_table_name)* ; flashback_tab_stmt : FLASHBACK TABLE full_table_name_list TO BEFORE DROP rename? | FLASHBACK TABLE full_table_name_list TO BEFORE TRUNCATE | FLASHBACK TABLE full_table_name_list TO TIMESTAMP exp flashback_trig_enable? | FLASHBACK TABLE full_table_name_list TO scn_or_lsn trxid flashback_trig_enable? ; rename : RENAME TO id ; alter_system_set_stmt : alter_tag SYSTEM SET LT_STRING '=' raw_exp defer? scope? ; defer : DEFERRED ; scope : MEMORY | BOTH | SPFILE ; alter_session_stmt : alter_tag SESSION sess_id? SET QUERY_REWRITE_INTEGRITY assign_op exp | alter_tag SESSION sess_id? SET EVENTS LT_STRING | alter_tag SESSION sess_id? SET TIME_ZONE assign_op set_time_zone_string | alter_tag SESSION sess_id? SET LT_STRING '=' raw_exp purge? | alter_tag SESSION sess_id? SET CASE_SENSITIVE assign_op exp | alter_tag SESSION sess_id? SET CASE_SENSITIVE assign_op DEFAULT | alter_tag SESSION sess_id? SET CURRENT_SCHEMA '=' qualified_name | alter_tag SESSION sess_id? SET sess_attr '=' sess_attr_val | alter_tag SESSION sess_id? ENABLE PARALLEL parallel_mode | alter_tag SESSION sess_id? DISABLE PARALLEL parallel_mode | alter_tag SESSION sess_id? FORCE PARALLEL parallel_mode parallel_degree? ; parallel_mode : DML | QUERY | DDL ; parallel_degree : PARALLEL LT_INTEGER ; purge : PURGE ; sess_id : LT_INTEGER | LT_DECIMAL ; set_time_zone_string : LOCAL | LT_STRING ; sess_attr : raw_id ; sess_attr_val : raw_id | LT_STRING ; set_schema_stmt : SET SCHEMA qualified_name ; plblock : decl_var_cur_list_1? BEGIN plbody except_option? blk_end_option ; except_option : EXCEPTION except_handler_list finally_option? | FINALLY finally_tail ; finally_option : FINALLY finally_tail ; finally_tail : plbody ; except_handler_list : except_handler+ ; except_handler : WHEN except_list THEN plbody ; except_name : variable_name ; except_list : qualified_name (OR qualified_name)* ; if_stmt : if_stmt_clause elseif_lst_option? else_option? END IF | ss_if_stmt_clause ss_elseif_lst_option? ss_else_option? ; if_stmt_clause : if_condition_clause if_then_clause ; if_condition_clause : IF bool_exp ; if_then_clause : THEN plbody ; elseif_lst_option : elseif_clause elseif_lst_option? ; elseif_clause : ELSEIF bool_exp THEN plbody ; else_option : ELSE plbody ; ss_if_stmt_clause : if_condition_clause ss_plbody ; ss_elseif_lst_option : ss_elseif_clause ss_elseif_lst_option? ; ss_elseif_clause : ELSEIF bool_exp ss_plbody ; ss_else_option : ELSE ss_plbody ; case_stmt : CASE plsearched_when_list else_option? END case_option? label_name_options? | CASE bool_exp plsearched_when_list else_option? END case_option? label_name_options? ; plsearched_when_clause : WHEN bool_exp THEN plbody ; plsearched_when_list : plsearched_when_clause+ ; case_option : CASE ; assign_stmt : assign_obj2 assign_op bool_exp | SET assign_obj assign_op bool_exp ; assign_obj : assignment_obj ; assign_obj2 : pexp_pfx2 | stm_param_name ; assign_op : ASSIGN | OP_ASSIGN | '=' ; goto_stmt : GOTO id ; while_stmt : WHILE bool_exp LOOP plbody end_loop_label_null ; loop_stmt : LOOP plbody end_loop_label_null ; repeat_stmt : REPEAT plbody UNTIL bool_exp ; for_stmt : FOR id in_option for_condition LOOP plbody end_loop_label_null ; forall_stmt : forall_start for_condition forall_save_exception_option? forall_dml_stmt | forall_start forall_index_values OF pexp forall_between_option? forall_save_exception_option? forall_dml_stmt ; forall_between_option : BETWEEN exp AND exp ; forall_save_exception_option : SAVE EXCEPTIONS ; forall_index_values : INDICES | VALUES ; forall_start : FORALL id IN ; forall_dml_stmt : delete_stmt | insert_stmt | update_stmt | merge_into_stmt | query_exp | execute_stmt ; in_option : IN REVERSE? ; for_condition : exp '..' exp | exp ; pipe_row_stmt : PIPE ROW '(' exp ')' ; exit_stmt : EXIT | EXIT WHEN bool_exp | EXIT id | EXIT id WHEN bool_exp ; continue_stmt : CONTINUE | CONTINUE WHEN bool_exp | CONTINUE id | CONTINUE id WHEN bool_exp ; null_stmt : NULL ; print_stmt : PRINT exp ; execute_stmt : EXECUTE IMMEDIATE exp bulk_or_single_into? using_clause? dyn_return? ; dyn_return : return_option bulk_or_single_into? ; using_clause : USING using_exp_list ; using_exp_list : using_exp (COMMA using_exp)* ; using_exp : param_in_out_option? exp ; alter_proc_stmt : alter_tag PROCEDURE full_proc_name COMPILE cascade_opt? debug_tag? ; alter_func_stmt : alter_tag FUNCTION full_fun_name COMPILE cascade_opt? debug_tag? ; alter_package_stmt : alter_tag pkg_type full_proc_name COMPILE declare_opt? cascade_opt? debug_tag? ; pkg_type : PACKAGE | TYPE | CLASS ; declare_opt : DECLARE ; alter_table_stmt : alter_tag TABLE full_table_name alter_table_action ; alter_tag : ALTER ; alter_index_stmt : alter_tag INDEX full_index_name alter_index_action ; full_index_name : qualified_name ; alter_index_action : RENAME TO index_name | visible_clause | rebuild_clause | UNUSABLE | MONITORING USAGE | NOMONITORING USAGE ; rebuild_clause : REBUILD storage_tag? index_no_sort? online_options? exclusive_options? asynchronous_options? ; exclusive_options : SHARE | EXCLUSIVE ; asynchronous_options : ASYNCHRONOUS | ASYNCHRONOUS LT_INTEGER ; visible_clause : VISIBLE | INVISIBLE ; column_def_list : column_def (COMMA column_def_list)* ; lock : NO LOCK ; alter_table_partition_action : ADD range_partition lock? | ADD list_partition | ADD hash_partition | DROP PARTITION exist? full_partition_name | DROP PARTITION exist? FOR '(' exp_list ')' | EXCHANGE PARTITION full_partition_name WITH TABLE full_table_name including_indexes? | EXCHANGE SUBPARTITION full_partition_name WITH TABLE full_table_name including_indexes? | SPLIT PARTITION full_partition_name AT_KEYWORD '(' range_partition_exp_list ')' INTO '(' split_partition_list ')' | SPLIT PARTITION full_partition_name VALUES '(' list_partition_exp_list ')' INTO '(' split_partition_list ')' | SPLIT PARTITION full_partition_name INTO '(' list_partition_list COMMA hash_partition ')' | SPLIT PARTITION full_partition_name INTO '(' range_partition_list COMMA hash_partition ')' | MERGE PARTITIONS partition_no? COMMA partition_no? INTO PARTITION full_partition_name | MERGE PARTITIONS full_partition_name COMMA full_partition_name INTO PARTITION full_partition_name | SET SUBPARTITION TEMPLATE template_info | DROP SUBPARTITION exist? full_partition_name | DROP SUBPARTITION exist? FOR '(' exp_list ')' | MODIFY PARTITION full_partition_name ADD add_subpartition_desc | MODIFY SUBPARTITION full_partition_name ADD add_subpartition_desc | MODIFY PARTITION full_partition_name ADD VALUES '(' list_partition_value_list ')' | MODIFY PARTITION full_partition_name DROP VALUES '(' list_partition_value_list ')' | RENAME PARTITION full_partition_name TO full_partition_name | RENAME SUBPARTITION full_partition_name TO full_partition_name | MODIFY SUBPARTITION full_partition_name ADD VALUES '(' list_partition_value_list ')' | MODIFY SUBPARTITION full_partition_name DROP VALUES '(' list_partition_value_list ')' | MOVE PARTITION full_partition_name TABLESPACE tablespace_name | MOVE SUBPARTITION full_partition_name TABLESPACE tablespace_name | MOVE TABLESPACE tablespace_name | LOCK PARTITIONS | LOCK ROOT ; template_info : '(' template_item_1? ')' | template_item_2 ; template_item_2 : SUBPARTITIONS LT_INTEGER storage_hash_tag? | LT_INTEGER storage_hash_tag? ; template_item_1 : range_subpartition_list | hash_subpartition_list | list_subpartition_list ; including_indexes : INCLUDING INDEXES | EXCLUDING INDEXES ; truncate_partition_name : full_partition_name | '(' full_partition_name ')' ; cons_enable : ENABLE | DISABLE ; reuse_storage_option : REUSE STORAGE | DROP STORAGE ; alter_table_action : ADD column_tag? not_exist? '(' column_def_list ')' | ALTER column_tag? column_name SET DEFAULT default_exp | ALTER column_tag? column_name SET DEFAULT ON NULL default_exp | ALTER column_tag? column_name DROP DEFAULT | ADD CONSTRAINT constraint_name_options? table_constraint_clause check_option_def_true? cons_enable? | ADD table_constraint_clause check_option_def_true? cons_enable? | DROP constraint_name_def restrict_cascade? | ALTER column_tag? column_name RENAME TO column_name | RENAME COLUMN column_name TO column_name | RENAME TO table_name | MODIFY mdf_column_def | MODIFY CONSTRAINT constraint_name ENABLE | MODIFY CONSTRAINT constraint_name DISABLE restrict_cascade? | REBUILD MODIFY mdf_column_def | MODIFY '(' mdf_column_def_list ')' | ADD column_tag? not_exist? column_def | DROP column_tag? exist? '(' drop_column_list ')' | DROP column_tag? exist? column_name restrict_cascade? | ENABLE ALL TRIGGERS | DISABLE ALL TRIGGERS | MODIFY constraint_name_def TO table_constraint_clause check_option_def_true? restrict_cascade? | MODIFY space_limit_1 | alter_table_partition_action | DROP IDENTITY | DROP AUTO_INCREMENT | ADD column_tag? not_exist? column_name identity_clause | ENABLE ata_lock_option | DISABLE ata_lock_option | ENABLE CONSTRAINT constraint_name check_option_def_true? | DISABLE CONSTRAINT constraint_name restrict_cascade? | ALTER column_tag? column_name SET not_null_spec | MODIFY ERROR TO ctab_error_option | MODIFY LOG TO ctab_log_option | ALTER column_tag? '(' column_list ')' SET STAT | ALTER column_tag? '(' column_list ')' SET STAT NONE | ALTER column_tag? column_name SET STAT NONE | WITH COUNTER | WITHOUT COUNTER | LOGGING | NOLOGGING | REBUILD COLUMNS | TRUNCATE PARTITION truncate_partition_name reuse_storage_option? | TRUNCATE PARTITION FOR '(' exp_list ')' reuse_storage_option? | TRUNCATE SUBPARTITION truncate_partition_name reuse_storage_option? | TRUNCATE SUBPARTITION FOR '(' exp_list ')' reuse_storage_option? | ALTER column_tag? column_name SET not_tag? VISIBLE | ENABLE ROW MOVEMENT | DISABLE ROW MOVEMENT | MODIFY PATH pathname | LOCATION '(' pathname ')' | DEFAULT DIRECTORY id | DEFAULT DIRECTORY id LOCATION '(' pathname ')' | ENABLE USING LONG ROW | WITH DELTA | WITHOUT DELTA | FORCE COLUMN STORAGE | REBUILD hfs_rebuild_level | REFRESH STAT | SET STAT storage_stat_flag? storage_stat_cols? | WITH ADVANCED LOG | WITHOUT ADVANCED LOG | TRUNCATE ADVANCED LOG | ADD LOGIC LOG | DROP LOGIC LOG | DROP PRIMARY KEY restrict_cascade? | DROP PARTITION GROUP full_table_name | read_only_flag_not_null | MOVE PARTITION full_partition_name TO raft_name fast_flag? | MOVE TO full_grp_name fast_flag? | increment_set | ALTER column_tag? column_name ADD user_clause | ALTER column_tag? column_name DROP user_clause | RENAME constraint_name_def TO constraint_name | PARALLEL LT_INTEGER ; fast_flag : FAST ; storage_stat_flag : NONE | ASYNCHRONOUS | SYNCHRONOUS ; storage_stat_cols : ON '(' column_list ')' | EXCEPT '(' column_list ')' ; hfs_rebuild_level : SECTION | TABLE ; ata_lock_option : PAGE LOCK | ROW LOCK | PAGE ROW LOCK | ROW PAGE LOCK ; mdf_column_def_list : mdf_column_def (COMMA mdf_column_def)* ; mdf_column_def : column_def_low | virtual_column_def | column_name column_def_4_option? ; column_def : column_def_low | virtual_column_def ; column_def_ex : column_def comment_clause? ; column_def_low : column_name datatype charset_option? collate_clause_option? column_def_4_option? storage_tag? encrypt_clause_options? compress_clause_opt? ; virtual_column_datatype : datatype ; virtual_column_generated : GENERATED ALWAYS ; virtual_column_virtual : VIRTUAL ; virtual_column_visible : VISIBLE ; virtual_column_def : column_name virtual_column_datatype? virtual_column_generated? AS '(' exp ')' virtual_column_virtual? charset_option? collate_clause_option? column_def_4_option? storage_tag? encrypt_clause_options? virtual_column_visible? ; charset_option : CHARACTER SET qualified_name ; column_def_4_option : identity_clause | column_constraint_def | auto_update_clause | default_clause_with_on_null_opt (identity_clause | column_constraint_def | auto_update_clause)? | identity_clause default_clause_with_on_null_opt | identity_clause column_constraint_def | identity_clause auto_update_clause | column_constraint_def default_clause_with_on_null_opt | column_constraint_def auto_update_clause | column_constraint_def identity_clause | auto_update_clause default_clause_with_on_null_opt | auto_update_clause column_constraint_def | auto_update_clause identity_clause | default_clause_with_on_null_opt auto_update_clause column_constraint_def | default_clause_with_on_null_opt column_constraint_def auto_update_clause | default_clause_with_on_null_opt identity_clause column_constraint_def | default_clause_with_on_null_opt column_constraint_def identity_clause | default_clause_with_on_null_opt identity_clause auto_update_clause | default_clause_with_on_null_opt auto_update_clause identity_clause | identity_clause auto_update_clause column_constraint_def | identity_clause column_constraint_def auto_update_clause | identity_clause auto_update_clause default_clause_with_on_null_opt | identity_clause default_clause_with_on_null_opt auto_update_clause | identity_clause default_clause_with_on_null_opt column_constraint_def | identity_clause column_constraint_def default_clause_with_on_null_opt | column_constraint_def default_clause_with_on_null_opt auto_update_clause | column_constraint_def auto_update_clause default_clause_with_on_null_opt | column_constraint_def default_clause_with_on_null_opt identity_clause | column_constraint_def identity_clause default_clause_with_on_null_opt | column_constraint_def identity_clause auto_update_clause | column_constraint_def auto_update_clause identity_clause | auto_update_clause column_constraint_def default_clause_with_on_null_opt | auto_update_clause default_clause_with_on_null_opt column_constraint_def | auto_update_clause identity_clause column_constraint_def | auto_update_clause column_constraint_def identity_clause | auto_update_clause identity_clause default_clause_with_on_null_opt | auto_update_clause default_clause_with_on_null_opt identity_clause | default_clause_with_on_null_opt identity_clause auto_update_clause column_constraint_def | default_clause_with_on_null_opt identity_clause column_constraint_def auto_update_clause | default_clause_with_on_null_opt auto_update_clause identity_clause column_constraint_def | default_clause_with_on_null_opt auto_update_clause column_constraint_def identity_clause | default_clause_with_on_null_opt column_constraint_def identity_clause auto_update_clause | default_clause_with_on_null_opt column_constraint_def auto_update_clause identity_clause | identity_clause default_clause_with_on_null_opt auto_update_clause column_constraint_def | identity_clause default_clause_with_on_null_opt column_constraint_def auto_update_clause | identity_clause auto_update_clause default_clause_with_on_null_opt column_constraint_def | identity_clause auto_update_clause column_constraint_def default_clause_with_on_null_opt | identity_clause column_constraint_def default_clause_with_on_null_opt auto_update_clause | identity_clause column_constraint_def auto_update_clause default_clause_with_on_null_opt | auto_update_clause default_clause_with_on_null_opt identity_clause column_constraint_def | auto_update_clause default_clause_with_on_null_opt column_constraint_def identity_clause | auto_update_clause identity_clause default_clause_with_on_null_opt column_constraint_def | auto_update_clause identity_clause column_constraint_def default_clause_with_on_null_opt | auto_update_clause column_constraint_def identity_clause default_clause_with_on_null_opt | auto_update_clause column_constraint_def default_clause_with_on_null_opt identity_clause | column_constraint_def default_clause_with_on_null_opt identity_clause auto_update_clause | column_constraint_def default_clause_with_on_null_opt auto_update_clause identity_clause | column_constraint_def identity_clause default_clause_with_on_null_opt auto_update_clause | column_constraint_def identity_clause auto_update_clause default_clause_with_on_null_opt | column_constraint_def auto_update_clause identity_clause default_clause_with_on_null_opt | column_constraint_def auto_update_clause default_clause_with_on_null_opt identity_clause ; auto_update_clause : ON UPDATE update_exp ; update_exp : exp ; identity_clause : IDENTITY '(' exp COMMA exp ')' | IDENTITY | AUTO_INCREMENT ; default_clause_with_on_null_opt : default_clause | DEFAULT ON NULL default_exp ; default_clause : DEFAULT default_exp ; default_exp : exp ; column_constraint_def : column_constraints constraint_attributes_options? ; constraint_name_def_options : constraint_name_def ; constraint_name_def : CONSTRAINT constraint_name ; column_constraints : column_constraint+ ; column_constraint : constraint_name_def_options? column_constraint_action cons_enable? ; column_constraint_action : not_null_spec | NOT VISIBLE | unique_spec using_index_clause? | refs_spec | check_constraint_def ; not_null_spec : not_tag? NULL ; unique_spec : UNIQUE | PRIMARY KEY | CLUSTER PRIMARY KEY | NOT CLUSTER PRIMARY KEY | CLUSTER KEY | CLUSTER UNIQUE KEY ; refs_spec : refs_spec_action (WITH INDEX)? ; refs_spec_action : foreign_key? REFERENCES pendant_tag? refd_table_and_columns match_option? ref_triggered_action? ; foreign_key : FOREIGN KEY ; refd_table_and_columns : full_table_name | full_table_name '(' ref_column_list ')' ; ref_column_list : column_list ; column_list : column_name compress_level? compress_type? (COMMA column_name compress_level? compress_type?)* ; column_list2 : exp compress_level? compress_type? (COMMA exp compress_level? compress_type?)* ; full_column_list : full_column_name (COMMA full_column_name)* ; column_list_list : '(' column_list ')' as_alias? storage_tag? | '(' column_list ')' as_alias? storage_tag? COMMA column_list_list ; drop_column_list : column_name restrict_cascade? (COMMA column_name restrict_cascade?)* ; match_option : MATCH match_type ; match_type : FULL | PARTIAL | SIMPLE ; ref_triggered_action : update_rule | delete_rule | update_rule delete_rule | delete_rule update_rule ; update_rule : ON UPDATE ref_action ; delete_rule : ON DELETE ref_action ; ref_action : CASCADE | SET NULL | SET DEFAULT | NO ACTION | RESTRICT ; check_constraint_def : CHECK '(' check_condition ')' ; check_condition : bool_exp ; restrict_cascade : RESTRICT | CASCADE CONSTRAINTS? ; cascade_opt : CASCADE ; constraint_name_options : constraint_name ; check_option_def_true : NOT? CHECK ; constraint_attributes_options : constraint_attributes ; constraint_attributes : constraint_check_time | deferrable_option | constraint_check_time deferrable_option | deferrable_option constraint_check_time ; deferrable_option : DEFERRABLE ; constraint_check_time : INITIALLY DEFERRED | INITIALLY IMMEDIATE ; table_constraint_clause : table_constraint constraint_attributes_options? ; table_constraint : unique_spec '(' column_list ')' using_index_clause? | foreign_key_clause | check_constraint_def ; using_index_clause : USING INDEX TABLESPACE (id | DEFAULT) ; foreign_key_clause : FOREIGN KEY '(' ref_column_list ')' refs_spec ; alter_trigger_stmt : alter_tag TRIGGER full_trigger_name (alter_trigger_option | RENAME TO trigger_name) ; alter_trigger_option : ENABLE | DISABLE | COMPILE debug_tag? | COMPILE AUTO ; alter_table_partition_action_options : alter_table_partition_action ; refresh_materialized_view_stmt : REFRESH MATERIALIZED VIEW full_view_name force? refresh_complete_del? | REFRESH MATERIALIZED VIEW full_view_name COMPLETE refresh_complete_del? | REFRESH MATERIALIZED VIEW full_view_name FAST ; complete_del_null : USING DEFAULT | USING TRUNCATE | USING DELETE ; refresh_complete_del : complete_del_null ; alter_materialized_view_stmt : alter_tag MATERIALIZED VIEW full_view_name alter_table_partition_action_options? mv_refresh_clause? query_rewrite? ; alter_view_stmt : alter_tag VIEW full_view_name alter_view_action ; alter_view_action : COMPILE | ADD CONSTRAINT constraint_name_options? view_constraint_clause DISABLE cons_novalidate? | ADD view_constraint_clause DISABLE cons_novalidate? | DROP constraint_name_def ; cons_novalidate : NOVALIDATE ; view_constraint_clause : view_constraint ; view_constraint : view_unique_spec '(' column_list ')' | FOREIGN KEY '(' ref_column_list ')' view_refs_spec ; view_unique_spec : UNIQUE | PRIMARY KEY ; view_refs_spec : view_refs_spec_action ; view_refs_spec_action : foreign_key? REFERENCES refd_table_and_columns ; call_proc_stmt : raw_call_proc_stmt | call_proc_stmt_2 ; raw_call_proc_stmt : member_access2 | member2 | invocation_expression2 ; call_proc_stmt_2 : CALL raw_call_proc_stmt | exec_proc_stmt ; exec_proc_stmt : EXECUTE full_proc_name dblink_clause? | EXECUTE full_proc_name dblink_clause? raw_exp_list | EXECUTE full_proc_name dblink_clause? param_list ; dblink_clause : '@' id ; dblink_clause2 : '@' qualified_name ; param_list : param (COMMA param)* ; param : param_name OPR_AEQ bool_exp ; raw_exp_list : raw_exp (COMMA raw_exp)* ; exp_list_2 : exp (COMMA exp)+ ; exp_list : exp | exp_list_2 ; ins_exp_list : (exp | DEFAULT) (COMMA(exp | DEFAULT))* ; lt_exp : op=('-' | '+') lt_exp | LT_INTEGER | LT_DECIMAL | LT_REAL | LT_STRING | member_access LT_STRING | member LT_STRING | LT_BITSTRING | INTERVAL '+' LT_STRING interval_qualifier | INTERVAL '-' LT_STRING interval_qualifier | INTERVAL LT_STRING interval_qualifier ; range_partition_exp : lt_exp | MAXVALUE | null_value | invocation_expression ; range_partition_exp_list : range_partition_exp (COMMA range_partition_exp)* ; list_partition_exp : lt_exp | null_value | invocation_expression ; list_partition_exp_list : list_partition_exp (COMMA list_partition_exp)* ; list_partition_value_list : list_partition_exp_list | DEFAULT ; close_cursor_stmt : CLOSE assign_obj2 ; close_cursor_statement : CLOSE CURSOR assign_obj ; begin_trans_stmt : BEGIN TRANSACTION ; commit_trans_stmt : commit_head commit_tail? ; commit_head : COMMIT work_tag? | COMMITWORK ; commit_tail : AND CHAIN | AND NO CHAIN | WRITE | WRITE commit_wait_immed_option | commit_wait_immed_option ; commit_wait_immed_option : WAIT | NOWAIT | IMMEDIATE | WAIT IMMEDIATE | NOWAIT IMMEDIATE | IMMEDIATE WAIT | BATCH WAIT | IMMEDIATE NOWAIT | BATCH NOWAIT | AUTO ; connect_stmt : CONNECT user_name password ; password : id | LT_BINTEGER | LT_DECIMAL | LT_INTEGER | LT_REAL ; ts_storage : ON id | ON LT_INTEGER | ON LT_INTEGER FOR RESTORE ; ts_storage_clause : STORAGE '(' ts_storage ')' ; create_tablespace_stmt : CREATE TABLESPACE not_exist? tablespace_name DATAFILE file_list cache? copy_num? region_size? striping_clause? redundancy_clause? with_huge_clause? ts_storage_clause? | CREATE TABLESPACE not_exist? tablespace_name DATAFILE file_list cache? ENCRYPT WITH cipher_name copy_num? region_size? striping_clause? redundancy_clause? with_huge_clause? ts_storage_clause? | CREATE TABLESPACE not_exist? tablespace_name DATAFILE file_list cache? ENCRYPT WITH cipher_name BY password copy_num? region_size? striping_clause? redundancy_clause? with_huge_clause? ts_storage_clause? | CREATE HUGE TABLESPACE not_exist? tablespace_name PATH pathname copy_num? region_size? striping_clause? redundancy_clause? ts_storage_clause? ; ctss_with_clause : WITH '(' id_list ')' ; create_tablespace_set_stmt : CREATE TABLESPACE SET id ctss_with_clause? ; alter_tablespace_set_stmt : alter_tag TABLESPACE SET id ADD '(' id_list ')' | alter_tag TABLESPACE SET id DELETE '(' id_list ')' ; cache : CACHE '=' id ; alter_tablespace_stmt : alter_tag TABLESPACE tablespace_name alter_tablespace_action | alter_tag HUGE TABLESPACE tablespace_name ADD PATH pathname ; keep : KEEP ; alter_tablespace_action : RENAME TO tablespace_name | RENAME DATAFILE pathname_list TO pathname_list | ADD DATAFILE file_list | DROP DATAFILE pathname | ONLINE | OFFLINE | CACHE '=' id | RESIZE DATAFILE pathname TO LT_INTEGER on_raft? | DATAFILE pathname_list autoextend? | CORRUPT | OPTIMIZE LT_INTEGER | MOVE TO raft_name read_only_flag? keep? | ADD HUGE PATH pathname region_size? ; file_list : file (COMMA file)* ; pathname_list : pathname (COMMA pathname)* ; integer_list : LT_INTEGER (COMMA LT_INTEGER)* ; file : pathname mirror? SIZE LT_INTEGER autoextend? ; mirror : MIRROR pathname ; autoextend_nextsize : NEXT LT_INTEGER ; autoextend_maxsize : MAXSIZE LT_INTEGER | MAXSIZE UNLIMITED ; autoextend : AUTOEXTEND OFF | AUTOEXTEND ON autoextend_nextsize? autoextend_maxsize? ; on_raft : ON id ; archfile : archflag? archstyle_options? archdir? ; archflag : ARCHIVELOG | NOARCHIVELOG ; archstyle_options : ARCHIVESTYLE archstyle ; archstyle : LT_STRING ; archdir : ARCHIVEDIR pathname ; bakfile : BACKUPDIR pathname ; parameters_option_list : PARMS '(' parameter_option_list ')' ; parameter_option_list : parameter_option (COMMA parameter_option)* ; parameter_option : id DELIMITED BY exp | id exp ; pathname : LT_STRING ; pathname_options : pathname ; backup_stmt : BACKUP back_range_option with_bak_dir_list? backup_to_options? backup_path_null backup_desc_options? backup_maxsize? backup_limit? backup_identified? backup_compressed? backup_without? backup_trace_file_level? backup_tsk_thread_num_null backup_parallel_dir? ; back_range_option : DATABASE backup_options? | TABLESPACE tablespace_name backup_options? | TABLE full_table_name | ARCHIVE LOG back_archive_spec_null | ARCHIVELOG back_archive_spec_null ; back_archive_spec_null : archive_spec? not_backed_up? backup_delete_archive? ; not_backed_up : NOT BACKED UP | NOT BACKED UP LT_INTEGER TIMES | NOT BACKED UP SINCE TIME LT_STRING ; archive_spec : ALL | FROM LSN spec_lsn | UNTIL LSN spec_lsn | LSN BETWEEN spec_lsn AND spec_lsn | FROM TIME LT_STRING | UNTIL TIME LT_STRING | TIME BETWEEN LT_STRING AND LT_STRING ; spec_lsn : LT_INTEGER ; backup_delete_archive : DELETE INPUT ; backup_options : FULL | FULL DDL_CLONE | DDL_CLONE | FULL SHADOW | SHADOW | INCREMENT FROM LSN LT_INTEGER | INCREMENT cumulative? base_on_backup? ; cumulative : CUMULATIVE ; with_bak_dir_list : WITH BACKUPDIR pathname_list ; base_on_backup : BASE ON BACKUPSET pathname ; backup_to_options : TO backup_name ; backup_path_null : device_type? parms_command? | BAKFILE pathname | BACKUPSET pathname_options? device_type? parms_command? ; device_type : DEVICE TYPE media_name ; parms_command : PARMS LT_STRING ; media_name : id ; backup_desc_options : BACKUPINFO backup_desc ; backup_desc : LT_STRING ; backup_maxsize : MAXSIZE LT_INTEGER | MAXPIECESIZE LT_INTEGER ; backup_limit : LIMIT READ SPEED LT_INTEGER | LIMIT WRITE SPEED LT_INTEGER | LIMIT READ SPEED LT_INTEGER WRITE SPEED LT_INTEGER ; backup_identified : IDENTIFIED BY password | IDENTIFIED BY password ENCRYPT WITH cipher_name | IDENTIFIED BY password WITH ENCRYPTION LT_INTEGER | IDENTIFIED BY password WITH ENCRYPTION LT_INTEGER ENCRYPT WITH cipher_name ; backup_compressed : COMPRESSED | COMPRESSED LEVEL LT_INTEGER ; backup_without : WITHOUT LOG | WITHOUT MIRROR | WITHOUT LOG WITHOUT MIRROR ; backup_tsk_thread_num_null : tsk_thread_num? ; backup_parallel_dir : PARALLEL pathname | PARALLEL | PARALLEL LT_INTEGER | PARALLEL READ SIZE LT_INTEGER | PARALLEL LT_INTEGER READ SIZE LT_INTEGER ; backup_trace_file_level : TRACE FILE pathname | TRACE LEVEL LT_INTEGER | TRACE FILE pathname TRACE LEVEL LT_INTEGER | TRACE LEVEL LT_INTEGER TRACE FILE pathname ; restore_stmt : RESTORE DATABASE FROM restore_from restore_identified? with_bak_arch_dir_list? res_until? restore_file_list_options? mirror_file_list_options? archfile bakfile? restore_parallel? | RESTORE TABLE full_table_name_options? res_struct? res_without_index_constraint? FROM restore_from restore_identified? restore_trace_file_level? | RESTORE TABLESPACE tablespace_name restore_datafile_lst FROM restore_from restore_identified? with_bak_arch_dir_list? restore_file_list_options? mirror_file_list_options? restore_mapped_file? restore_trace_file_level? restore_tsk_thread_num_null restore_parallel? | RESTORE TABLESPACE tablespace_name FROM restore_from restore_identified? with_bak_arch_dir_list? restore_file_list_options? mirror_file_list_options? restore_mapped_file? restore_trace_file_level? restore_tsk_thread_num_null restore_parallel? res_until? ; restore_datafile_lst : DATAFILE pathname_list | DATAFILE integer_list ; restore_mapped_file : mapped_file ; mapped_file : MAPPED FILE LT_STRING ; res_struct : STRUCT ; tsk_thread_num : TASK THREAD LT_INTEGER ; restore_tsk_thread_num_null : tsk_thread_num? ; restore_parallel : NOT PARALLEL ; full_table_name_options : full_table_name ; res_without_index_constraint : WITH INDEX | WITH INDEX WITH CONSTRAINT | WITH INDEX WITHOUT CONSTRAINT | WITHOUT INDEX | WITHOUT INDEX WITH CONSTRAINT | WITHOUT INDEX WITHOUT CONSTRAINT | WITH CONSTRAINT | WITHOUT CONSTRAINT ; restore_from : pathname | BACKUP backup_name | BACKUPSET pathname device_type? parms_command? ; res_until : UNTIL TIME LT_STRING | UNTIL LSN LT_INTEGER | UNTIL TIME LT_STRING UNTIL LSN LT_INTEGER | UNTIL LSN LT_INTEGER UNTIL TIME LT_STRING ; restore_file_list_options : restore_file_list ; mirror_file_list_options : mirror_file_list ; restore_trace_file_level : TRACE FILE pathname | TRACE LEVEL LT_INTEGER | TRACE FILE pathname TRACE LEVEL LT_INTEGER | TRACE LEVEL LT_INTEGER TRACE FILE pathname ; restore_file_list : restore_file (COMMA restore_file)* ; restore_file : DBFILE LT_INTEGER TO pathname ; mirror_file_list : mirror_file (COMMA mirror_file)* ; mirror_file : MIRROR LT_INTEGER TO pathname ; with_bak_arch_dir_list : WITH BACKUPDIR pathname_list | WITH ARCHIVEDIR pathname_list | WITH BACKUPDIR pathname_list WITH ARCHIVEDIR pathname_list ; restore_identified : IDENTIFIED BY password | IDENTIFIED BY password ENCRYPT WITH cipher_name ; create_func_stmt : CREATE replace_option? FUNCTION not_exist? full_func_name (func_def_inner | (WRAPPED LT_STRING)) ; func_aggr_clause : AGGREGATE USING plsql_datatype ; pipelined_options : PIPELINED ; replace_option : OR REPLACE ; edit_options : EDITIONABLE | NONEDITIONABLE ; encryption_option : WITH ENCRYPTION ; calc_option : FOR CALCULATE ; func_action : is_as dmsubprogram | EXTERNAL pathname inner_fun_name? USING platform_type | func_aggr_clause | PIPELINED is_as dmsubprogram | PIPELINED USING plsql_datatype ; func_call_options : func_call_option_list ; func_call_option_list : func_call_option+ ; func_call_option : invoker_rights_clause | deterministic_clause | PARALLEL_ENABLE | result_cache_clause ; invoker_rights_clause_options : invoker_rights_clause ; invoker_rights_clause : AUTHID DEFINER | AUTHID CURRENT_USER ; deterministic_clause_options : deterministic_clause ; deterministic_clause : DETERMINISTIC ; func_call_option2_options : func_call_option_list2 ; func_call_option_list2 : func_call_option2+ ; func_call_option2 : deterministic_clause | result_cache_clause | PARALLEL_ENABLE ; result_cache_clause : RESULT_CACHE ; inner_fun_name : qualified_name ; platform_type : id ; param_def_list_option : '(' ')' | '(' param_def_list ')' ; param_def_list : param_def | param_def COMMA param_def_list ; param_def : param_name param_in_out_option? plsql_datatype default_clause_option? ; param_in_out_option : IN | OUT | IN OUT | OUT IN | OUT NOCOPY | IN OUT NOCOPY | OUT IN NOCOPY ; is_as : IS | AS ; stat_on_org_stmt : STAT stat_para stat_size? ON qualified_name '(' column_list ')' global_tag? | STAT stat_para stat_size? ON INDEX qualified_name global_tag? | STAT ON qualified_name global_tag? ; stat_size : SIZE LT_INTEGER ; stat_para : LT_INTEGER | LT_DECIMAL | LT_REAL ; stat_summarize : COLUMN LT_INTEGER LT_REAL LT_INTEGER LT_REAL | COLUMN stm_param stm_param stm_param stm_param ; mstat_ex : BY without_into_select ; indexid : LT_INTEGER ; global_tag : GLOBAL ; bm_join_index_clause : from_clause WHERE search_condition ; parallel_stmt : NOPARALLEL | PARALLEL | PARALLEL LT_INTEGER ; create_index_stmt : CREATE replace_option? partition_tag? unique_tag? INDEX not_exist? index_name with_inner? ON full_table_name '(' index_column_list ')' bm_join_index_clause? global_tag? partition_clause? storage_tag? index_no_sort? online_options? reverse_options? unusable_options? parallel_stmt? ; with_inner : WITH INNER ; index_no_sort : NOSORT ; online_options : ONLINE ; unusable_options : UNUSABLE ; reverse_options : REVERSE ; index_column_list : index_column_name (COMMA index_column_name)* ; index_column_name : exp asc_desc_option? ; storage_hash_tag : STORE IN storage_hash ; storage_hash : '(' id_list ')' ; storage_tag : storage_tag_nn | tablespace_clause | tablespace_clause storage_tag_nn | storage_tag_nn tablespace_clause ; storage_tag_nn : STORAGE '(' storage_list ')' ; tablespace_clause : TABLESPACE id local_option? ; object_table_substitution_clause : object_table_substitution ; object_table_substitution : SUBSTITUTABLE AT_KEYWORD ALL LEVELS | NOT SUBSTITUTABLE AT_KEYWORD ALL LEVELS ; oid_clause : OBJECT IDENTIFIER_KEYWORD IS oid_gen_type ; oid_gen_type : SYSTEM GENERATED | PRIMARY KEY ; oid_index_clause : OIDINDEX id | OIDINDEX id oid_tablespace_clause | OIDINDEX oid_tablespace_clause ; oid_tablespace_clause : '(' oid_tablespace_name? ')' ; oid_tablespace_name : TABLESPACE id ; local_option : LOCAL ; storage_list : storage (COMMA storage)* ; storage_hashpartmap : HASHPARTMAP '(' LT_INTEGER ')' ; storage : INITIAL LT_INTEGER | NEXT LT_INTEGER | MINEXTENTS LT_INTEGER | ON PRIMARY | ON id | FILLFACTOR LT_INTEGER | CACHE '=' id | BRANCH LT_INTEGER | BRANCH '(' LT_INTEGER COMMA LT_INTEGER ')' | NOBRANCH | CLUSTERBTR | SECTION '(' LT_INTEGER ')' | STAT storage_stat_flag? storage_stat_cols? | FILESIZE '(' LT_INTEGER ')' | WITH COUNTER | WITHOUT COUNTER | WITH DELTA | WITHOUT DELTA | USING LONG ROW | storage_hashpartmap ; id_list : PRIMARY | id | id COMMA id_list | PRIMARY COMMA id_list ; create_proc_stmt : CREATE replace_option? PROCEDURE not_exist? full_proc_name2 (WITH ENCRYPTION)? param_def_list_option? invoker_rights_clause_options? func_action | CREATE replace_option? PROCEDURE not_exist? full_proc_name2 WRAPPED LT_STRING ; create_package_stmt : CREATE replace_option? edit_options? pkg_cls_flag not_exist? full_proc_name2 encryption_option? under_option? final_inst_list_options? invoker_rights_clause_options? is_as package_def_list_options? blk_end_option | CREATE replace_option? edit_options? pkg_cls_flag not_exist? full_proc_name2 WRAPPED LT_STRING ; pkg_cls_flag : PACKAGE | CLASS ; blk_end_option : blk_end_option_low ; blk_end_option_low : END | END id ; package_def_list_options : package_def_list ; package_def_list : package_def+ ; package_def : decl_variable | decl_cursor SEMI | decl_except | pragma_def | PRAGMA RESTRICT_REFERENCES '(' restrict_param_lst ')' SEMI | decl_plsql_type | method_inherit_options? method_attr_options? member_static? PROCEDURE id param_def_list_option? SEMI | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype func_call_option2_options? pipelined_options? SEMI | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype func_call_option2_options? PIPELINED USING plsql_datatype SEMI ; restrict_param_lst : id_list | DEFAULT COMMA id_list ; create_package_body_stmt : create_pkg_body_header encryption_option? is_as package_body_def_list package_body_init_option? blk_end_option | create_pkg_body_header encryption_option? is_as package_body_init_option? blk_end_option | create_pkg_body_header WRAPPED LT_STRING ; create_pkg_body_header : CREATE replace_option? edit_options? pkg_cls_body_flag full_proc_name2 ; pkg_cls_body_flag : PACKAGE BODY | CLASS BODY ; package_body_init_option : decl_var_cur_list_1? BEGIN plbody except_option? ; package_body_def_list : package_def | package_body_def | package_def package_body_def_list | package_body_def package_body_def_list ; package_body_def : method_inherit_options? method_attr_options? member_static? PROCEDURE id param_def_list_option? check_exec_options? is_as dmsubprogram SEMI | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype func_call_option2_options? pipelined_options? check_exec_options? is_as dmsubprogram SEMI ; package_body_def2 : PROCEDURE id param_def_list_option? check_exec_options? is_as dmsubprogram SEMI | FUNCTION id param_def_list_option? RETURN plsql_datatype deterministic_clause_options? pipelined_options? check_exec_options? is_as dmsubprogram SEMI ; check_exec_options : EXECUTE CHECK | EXECUTE NOT CHECK ; subpg_decl_stmt : method_inherit_options? method_attr_options? member_static? PROCEDURE id param_def_list_option? SEMI | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype SEMI ; create_type_stmt : CREATE replace_option? TYPE full_proc_name2 encryption_option? invoker_rights_clause_options? force_option? object_option '(' object_def_list_options? ')' final_inst_list_options? | CREATE replace_option? TYPE full_proc_name2 encryption_option? invoker_rights_clause_options? force_option? is_as plsql_type_def | CREATE replace_option? TYPE full_proc_name2 WRAPPED LT_STRING ; force_option : FORCE ; object_option : is_as OBJECT | UNDER full_proc_name ; under_option : UNDER full_proc_name ; object_def_list_options : object_def_list ; object_def_list : object_def (COMMA object_def)* ; object_def : variable_name_list plsql_datatype | method_inherit_options? method_attr_options? member_static? PROCEDURE id param_def_list_option? | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype deterministic_clause_options? pipelined_options? | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype deterministic_clause_options? PIPELINED USING plsql_datatype | method_inherit_options? CONSTRUCTOR FUNCTION id param_def_list_option? RETURN SELF AS RESULT | PRAGMA RESTRICT_REFERENCES '(' restrict_param_lst ')' ; member_static : MEMBER | STATIC ; method_inherit_options : method_inherit_option ; method_inherit_option : overriding_option | final_inst_list | overriding_option final_inst_list ; final_inst_list_options : final_inst_list ; final_inst_list : final_inst | final_inst final_inst_list ; final_inst : FINAL | INSTANTIABLE | NOT FINAL | NOT INSTANTIABLE ; overriding_option : OVERRIDING | NOT OVERRIDING ; method_attr_options : method_attr ; method_attr : MAP | ORDER ; create_type_body_stmt : CREATE replace_option? TYPE BODY full_proc_name2 encryption_option? is_as object_body_def_list END | CREATE replace_option? TYPE BODY full_proc_name2 WRAPPED LT_STRING ; object_body_def_list : object_body_def | object_body_def object_body_def_list ; object_body_def : method_inherit_options? method_attr_options? member_static? PROCEDURE id param_def_list_option? is_as dmsubprogram SEMI | method_inherit_options? method_attr_options? member_static? FUNCTION id param_def_list_option? RETURN plsql_datatype deterministic_clause_options? pipelined_options? is_as dmsubprogram SEMI | method_inherit_options? CONSTRUCTOR FUNCTION id param_def_list_option? RETURN SELF AS RESULT is_as dmsubprogram SEMI ; create_context_stmt : CREATE replace_option? CONTEXT not_exist? namespace USING full_object_name initialized? ; namespace : id ; initialized : ACCESSED LOCALLY | ACCESSED GLOBALLY | INITIALIZED EXTERNALLY | INITIALIZED GLOBALLY ; create_directory_stmt : CREATE replace_option? DIRECTORY not_exist? id AS LT_STRING ; create_crypto_stmt : CREATE CRYPTO crypto_name pathname ; alter_crypto_stmt : alter_tag CRYPTO crypto_name alter_crypto_action ; alter_crypto_action : RENAME TO crypto_name | ADD BLOCK ENCRYPT CIPHER cipher_name INNERID LT_INTEGER BLOCK SIZE LT_INTEGER KEY SIZE LT_INTEGER | ADD ENCRYPT CIPHER cipher_name INNERID LT_INTEGER KEY SIZE LT_INTEGER | ADD HASH CIPHER cipher_name INNERID LT_INTEGER HASH SIZE LT_INTEGER | MODIFY CIPHER cipher_name RENAME TO cipher_name | DROP CIPHER cipher_name | ADD CRYPTO HASH LT_STRING | DROP CRYPTO HASH LT_STRING ; comment_stmt : comment_tag ON TABLE full_table_name IS LT_STRING | comment_tag ON COLUMN full_column_name IS LT_STRING | comment_tag ON VIEW full_view_name IS LT_STRING ; comment_tag : COMMENT ; create_partition_group_stmt : CREATE PARTITION GROUP full_table_name PARTITION BY horizon_partition_act_datatype storage_act_datatype? ; storage_act_datatype : STORAGE '(' pg_storage_lst ')' | STORAGE '(' ON full_column_list ')' ; pg_storage_lst : pg_storage (COMMA pg_storage)* ; pg_storage : ON '(' full_column_list ')' | storage_hashpartmap ; create_table_stmt : CREATE table_temp_option? table_type_option? TABLE not_exist? create_table_action | CREATE HUGE TABLE not_exist? create_table_action | CREATE SNAPSHOT TABLE not_exist? full_table_name FROM full_table_name ; ctab_append_attr_clause : ctab_append_attr_list ; ctab_append_attr_list : ctab_append_attr+ ; cobjtab_append_attr_clause : cobjtab_append_attr_list ; cobjtab_append_attr_list : cobjtab_append_attr | cobjtab_append_attr cobjtab_append_attr_list ; ctab_append_attr : on_commit_option_nn | logging_option_nn | partition_clause_nn | space_limit_nn | storage_tag_nn | tablespace_clause ; cobjtab_append_attr : oid_clause | oid_index_clause ; create_table_action : full_table_name '(' table_element_list ')' ctab_append_attr_clause? compress_tag? rowdependencies_clause? ctab_row_movement_clause? ctab_log_options? advance_log_clause? add_log_clause? ctab_error_options? distribute_by? increment? | full_table_name '(' table_element_list ')' FROM DEFAULT DIRECTORY id LOCATION '(' pathname ')' | full_table_name '(' table_element_list ')' FROM DATAFILE? pathname parameters_option_list? | full_table_name '(' table_element_list ')' FROM DATAFILE DEFAULT DIRECTORY id LOCATION '(' pathname ')' parameters_option_list? | full_table_name on_commit_option? logging_option? (PARTITION BY horizon_partition_act)? space_limit? storage_tag? compress_tag? rowdependencies_clause? ctab_log_options? advance_log_clause? add_log_clause? ctab_error_options? AS without_into_select2 distribute_by? increment? | full_table_name on_commit_option? logging_option? space_limit? storage_tag? compress_tag? rowdependencies_clause? ctab_log_options? advance_log_clause? add_log_clause? ctab_error_options? LIKE normal_tv increment? | full_table_name '(' table_element_list ')' USING PARTITION GROUP full_table_name BY '(' column_list ')' pg_sub_partition? lock_partitions_clause? storage_tag? compress_tag? rowdependencies_clause? ctab_row_movement_clause? ctab_log_options? advance_log_clause? add_log_clause? ctab_error_options? | full_table_name OF qualified_name object_table_substitution_clause? objtab_elem_constraint? cobjtab_append_attr_clause? ctab_append_attr_clause? compress_tag? rowdependencies_clause? ctab_row_movement_clause? ctab_log_options? advance_log_clause? add_log_clause? ctab_error_options? distribute_by? increment? ; ctab_log_options : LOG ctab_log_option ; ctab_log_option : ALL | NONE | LOB NONE | LAST ; ctab_error_options : WHEN ERROR ctab_error_option ; advance_log_clause : WITH ADVANCED LOG ; add_log_clause : ADD LOGIC LOG ; ctab_error_option : TRUNCATE | DISABLE ; ctab_row_movement_clause : ENABLE ROW MOVEMENT | DISABLE ROW MOVEMENT ; range_distribute_act : VALUES LESS THAN '(' range_partition_exp_list ')' ON id | VALUES EQU OR LESS THAN '(' range_partition_exp_list ')' ON id ; range_distribute_act_lst : range_distribute_act | range_distribute_act_lst COMMA range_distribute_act ; list_distribute_act : VALUES '(' list_partition_value_list ')' ON id ; list_distribute_act_list : list_distribute_act (COMMA list_distribute_act)* ; distribute_by_option : DISTRIBUTED | DISTRIBUTED FULLY | DISTRIBUTED RANDOMLY | DISTRIBUTED BY '(' column_list ')' | DISTRIBUTED BY HASH '(' column_list ')' | DISTRIBUTED BY RANGE '(' column_list ')' '(' range_distribute_act_lst ')' | DISTRIBUTED BY LIST '(' column_list ')' '(' list_distribute_act_list ')' ; distribute_by : distribute_by_option ; increment_set : AUTO_INCREMENT '=' LT_INTEGER | AUTO_INCREMENT LT_INTEGER ; increment : increment_set ; rowdependencies_clause : ROWDEPENDENCIES | NOROWDEPENDENCIES ; pg_sub_partition : SUBPARTITION BY '(' column_list ')' ; table_type_option : VERTICAL | EXTERNAL ; table_temp_option : GLOBAL TEMPORARY | LOCAL TEMPORARY | TEMPORARY | SHARE TEMPORARY ; objtab_elem_constraint : '(' objtab_element_cons_list ')' ; objtab_element_cons_list : objtab_element_cons (COMMA objtab_element_cons_list)* ; objtab_element_cons : objcol_constraint | table_constraint_def ; objcol_constraint : column_name charset_option? collate_clause_option? column_def_4_option? storage_tag? encrypt_clause_options? compress_clause_opt? ; table_element_list : table_element (COMMA table_element)* ; table_element : column_def_ex | table_constraint_def ; table_constraint_def : constraint_name_def_options? table_constraint_clause cons_enable? ; on_commit_option : on_commit_option_nn ; on_commit_option_nn : ON COMMIT del_res ROWS ; logging_option : logging_option_nn ; logging_option_nn : LOGGING | NOLOGGING ; partition_clause : partition_clause_nn ; partition_clause_nn : PARTITION BY partition_act ; horizon_partition_clause : PARTITION BY horizon_partition_act ; compress_tag_hdr : COMPRESS compress_level? compress_type? ; compress_clause_opt : compress_tag_hdr ; compress_tag : compress_tag_hdr | compress_tag_hdr '(' column_list ')' | compress_tag_hdr EXCEPT '(' column_list ')' ; compress_level : LEVEL LT_INTEGER ; compress_type : FOR LT_STRING ; range_partition : PARTITION full_partition_name VALUES LESS THAN '(' range_partition_exp_list ')' storage_tag? subpartition_desc_option? | PARTITION full_partition_name VALUES EQU OR LESS THAN '(' range_partition_exp_list ')' storage_tag? subpartition_desc_option? ; range_partition_list : range_partition (COMMA range_partition)* ; hash_partition : PARTITION full_partition_name storage_tag? subpartition_desc_option? ; hash_partition_list : hash_partition (COMMA hash_partition)* ; list_partition : PARTITION full_partition_name VALUES '(' list_partition_value_list ')' storage_tag? subpartition_desc_option? ; list_partition_list : list_partition (COMMA list_partition)* ; split_partition_list : hash_partition (COMMA hash_partition)* ; partition_act : horizon_partition_act | vertical_partition_act ; vertical_partition_act : COLUMN '(' column_list ')' as_alias? | COLUMN '(' column_list_list ')' ; interval_item : INTERVAL '(' exp ')' ; horizon_partition_act_datatype : RANGE '(' datatype_list ')' subpartion_template_list_datatype_options? '(' range_partition_list ')' | HASH '(' datatype_list ')' subpartion_template_list_datatype_options? PARTITIONS (LT_INTEGER | DEFAULT) storage_hash_tag? | HASH '(' datatype_list ')' subpartion_template_list_datatype_options? '(' hash_partition_list ')' | LIST '(' datatype_list ')' subpartion_template_list_datatype_options? '(' list_partition_list ')' ; horizon_partition_act : RANGE '(' column_list ')' interval_item? subpartion_template_list_options? '(' range_partition_list ')' lock_partitions_clause? | HASH '(' column_list ')' subpartion_template_list_options? PARTITIONS (LT_INTEGER | DEFAULT) storage_hash_tag? lock_partitions_clause? | HASH '(' column_list ')' subpartion_template_list_options? '(' hash_partition_list ')' lock_partitions_clause? | LIST '(' column_list ')' subpartion_template_list_options? '(' list_partition_list ')' lock_partitions_clause? | REFERENCE '(' constraint_name ')' ; lock_partitions_clause : LOCK ROOT | LOCK PARTITIONS ; subpartion_template_list_datatype_options : subpartion_template_list_datatype ; subpartion_template_list_datatype : subpartion_template_datatype (COMMA subpartion_template_datatype)* ; subpartion_template_list_options : subpartion_template_list ; subpartion_template_list : subpartion_template (COMMA subpartion_template)* ; subpartion_template_datatype : range_subpartion_template_datatype | hash_subpartion_template_datatype | list_subpartion_template_datatype ; range_subpartion_template_datatype : SUBPARTITION BY RANGE '(' datatype_list ')' | SUBPARTITION BY RANGE '(' datatype_list ')' SUBPARTITION TEMPLATE '(' range_subpartition_list ')' ; hash_subpartion_template_datatype : SUBPARTITION BY HASH '(' datatype_list ')' ((SUBPARTITION TEMPLATE)? hash_subpartions_template_datatype_option)? | SUBPARTITION BY HASH '(' datatype_list ')' SUBPARTITION TEMPLATE '(' hash_subpartition_list ')' ; hash_subpartions_template_datatype_option : SUBPARTITIONS (LT_INTEGER | DEFAULT) storage_hash_tag? ; list_subpartion_template_datatype : SUBPARTITION BY LIST '(' datatype_list ')' | SUBPARTITION BY LIST '(' datatype_list ')' SUBPARTITION TEMPLATE '(' list_subpartition_list ')' ; subpartion_template : range_subpartion_template | hash_subpartion_template | list_subpartion_template ; range_subpartion_template : SUBPARTITION BY RANGE '(' column_list ')' | SUBPARTITION BY RANGE '(' column_list ')' SUBPARTITION TEMPLATE '(' range_subpartition_list ')' ; hash_subpartion_template : SUBPARTITION BY HASH '(' column_list ')' ((SUBPARTITION TEMPLATE)? hash_subpartions_template_option)? | SUBPARTITION BY HASH '(' column_list ')' SUBPARTITION TEMPLATE '(' hash_subpartition_list ')' ; hash_subpartions_template_option : SUBPARTITIONS (LT_INTEGER | DEFAULT) storage_hash_tag? ; list_subpartion_template : SUBPARTITION BY LIST '(' column_list ')' (SUBPARTITION TEMPLATE '(' list_subpartition_list ')')? ; range_subpartition : SUBPARTITION full_partition_name VALUES LESS THAN '(' range_partition_exp_list ')' storage_tag? | SUBPARTITION full_partition_name VALUES EQU OR LESS THAN '(' range_partition_exp_list ')' storage_tag? ; hash_subpartition : SUBPARTITION full_partition_name storage_tag? ; list_subpartition : SUBPARTITION full_partition_name VALUES '(' list_partition_value_list ')' storage_tag? ; range_subpartition_list : range_subpartition (COMMA range_subpartition)* ; hash_subpartition_list : hash_subpartition (COMMA hash_subpartition)* ; list_subpartition_list : list_subpartition (COMMA list_subpartition)* ; subpartition_hash_desc : hash_subpartition subpartition_desc_option? ; subpartition_range_desc : range_subpartition subpartition_desc_option? ; subpartition_list_desc : list_subpartition subpartition_desc_option? ; subpartition_hash_desc_list : subpartition_hash_desc (COMMA subpartition_hash_desc)* ; subpartition_range_desc_list : subpartition_range_desc (COMMA subpartition_range_desc)* ; subpartition_list_desc_list : subpartition_list_desc (COMMA subpartition_list_desc)* ; subpartition_desc : '(' subpartition_range_desc_list ')' | '(' subpartition_hash_desc_list ')' | '(' subpartition_list_desc_list ')' | SUBPARTITIONS LT_INTEGER storage_hash_tag? ; subpartition_desc_option : subpartition_desc ; add_subpartition_desc : subpartition_range_desc_list | subpartition_hash_desc_list | subpartition_list_desc_list ; partition_no : RANGE LT_INTEGER | LT_INTEGER ; comment_clause : COMMENT LT_STRING ; encrypt_clause_options : encrypt_clause ; encrypt_clause : NO ENCRYPT | ENCRYPT | ENCRYPT encrypt_cipher | ENCRYPT encrypt_cipher hash_cipher | FULL ENCRYPT WITH full_cipher_name ; encrypt_cipher : WITH full_cipher_name | WITH full_cipher_name encrypt_type | encrypt_type ; crypto_name : id ; cipher_name : id ; full_cipher_name : id ; encrypt_type : MANUAL | MANUAL manual_clause | AUTO | AUTO BY password | AUTO BY WRAPPED LT_STRING ; manual_clause : user_clause | BY password user_clause_options? | BY WRAPPED LT_STRING user_clause_options? ; user_clause_options : user_clause ; user_clause : USER '(' user_list_option? ')' ; user_list_option : user_list ; user_list : user_name (COMMA user_list)* ; hash_cipher : HASH WITH full_cipher_name | HASH WITH full_cipher_name hash_type ; hash_type : SALT | NO SALT ; space_limit : space_limit_nn ; space_limit_nn : DISKSPACE LIMIT LT_INTEGER | DISKSPACE UNLIMITED ; space_limit_1 : DISKSPACE LIMIT LT_INTEGER | DISKSPACE UNLIMITED ; space_limit2 : DISKSPACE LIMIT LT_INTEGER | DISKSPACE UNLIMITED ; del_res : DELETE | PRESERVE ; trig_enable : ENABLE | DISABLE ; at_raft : EXECUTE AT_KEYWORD id | EXECUTE AT_KEYWORD LT_INTEGER ; create_trigger_stmt : CREATE replace_option? TRIGGER full_trigger_name2 (WITH ENCRYPTION)? before_after ((trig_del_ins_upd_list local? ON full_table_name2) | (trig_event_list local? ON event_object at_raft?)) trig_referencing_def_options? trig_for_each_option? trig_when_option? trig_enable? dmsubprogram | CREATE replace_option? TRIGGER full_trigger_name2 WRAPPED LT_STRING ; before_after : BEFORE | AFTER | INSTEAD OF ; trig_del_ins_upd_list : (trig_del_ins_upd (OF column_list)?) (OR (trig_del_ins_upd (OF column_list)?))* ; trig_del_ins_upd : DELETE | INSERT | UPDATE ; update_of_option : UPDATE nowait? | UPDATE OF full_column_list nowait? ; nowait : NOWAIT | WAIT LT_INTEGER | SKIP_KEYWORD LOCKED | LT_INTEGER SKIP_KEYWORD LOCKED ; trig_event_list : trig_event (OR trig_event)* ; trig_event : CREATE | ALTER | DROP | AUDIT | NOAUDIT | GRANT | REVOKE | TRUNCATE | ANALYZE | LOGIN | LOGON | LOGOUT | LOGOFF | SERERR | BACKUP DATABASE | RESTORE DATABASE | TIMER | STARTUP | SHUTDOWN | COMMENT | DDL | CHECKPOINT ; event_object : qualified_name '.' SCHEMA | SCHEMA | DATABASE ; trig_referencing_def_options : trig_referencing_def ; trig_referencing_def : REFERENCING trig_referencing_list ; trig_referencing_list : trig_referencing_old | trig_referencing_new | trig_referencing_old trig_referencing_new ; trig_referencing_old : OLD row_tag? as_tag? trig_old_name ; trig_referencing_new : NEW row_tag? as_tag? trig_new_name ; trig_for_each_option : FOR EACH ROW | FOR EACH STATEMENT | trig_timer_rate ; trig_timer_rate : FOR ONCE AT_KEYWORD DATETIME LT_STRING max_run_duration? exec_ep_seqno? | rate_over_day rate_in_day duaring_date? max_run_duration? exec_ep_seqno? | repeat_interval duaring_date? max_run_duration? exec_ep_seqno? ; exec_ep_seqno : EXECUTE AT_KEYWORD LT_INTEGER ; rate_over_day : month_rate | week_rate | day_rate ; month_rate : FOR EACH LT_INTEGER MONTH day_in_month | FOR EACH LT_INTEGER MONTH day_in_month_week ; day_in_month : DAY LT_INTEGER ; day_in_month_week : DAY LT_INTEGER OF WEEK LT_INTEGER | DAY LT_INTEGER OF WEEK LAST ; week_rate : FOR EACH LT_INTEGER WEEK day_of_week_list ; day_of_week_list : LT_INTEGER (COMMA LT_INTEGER)* ; day_rate : FOR EACH LT_INTEGER DAY ; rate_in_day : once_in_day | times_in_day ; once_in_day : AT_KEYWORD TIME LT_STRING ; times_in_day : duaring_time? FOR EACH LT_INTEGER MINUTE | duaring_time? FOR EACH LT_INTEGER SECOND ; duaring_time : FROM TIME LT_STRING | FROM TIME LT_STRING TO TIME LT_STRING ; duaring_date : FROM DATETIME LT_STRING | FROM DATETIME LT_STRING TO DATETIME LT_STRING ; trig_when_option : WHEN '(' trig_when_condition ')' ; trig_when_condition : bool_exp ; repeat_interval_stmt : repeat_interval ; max_run_duration : MAX_RUN_DURATION LT_INTEGER ; repeat_interval : frequency_clause (SEMI interval_clause_single*)? ; frequency_clause : FREQ '=' frequency_define ; frequency_define : predefined_frequency ; predefined_frequency : YEARLY | MONTHLY | WEEKLY | DAILY | HOURLY | MINUTELY | SECONDLY ; interval_clause_list : interval_clause_single (SEMI interval_clause_single)* ; interval_clause_single : interval_clause | bymonth_clause | byweekno_clause | byyearday_clause | bymonthday_clause | byday_clause | byhour_clause | byminute_clause | bysecond_clause ; interval_clause : INTERVAL '=' intervalnum ; intervalnum : LT_INTEGER ; bymonth_clause : BYMONTH '=' monthlist ; monthlist : month | monthlist COMMA month ; month : numeric_month | char_month ; numeric_month : LT_INTEGER ; char_month : JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC ; byweekno_clause : BYWEEKNO '=' weekno_list ; weekno_list : weekno (COMMA weekno)* ; weekno : lt_integer_negative ; byyearday_clause : BYYEARDAY '=' yearday_list ; yearday_list : yearday (COMMA yearday)* ; yearday : lt_integer_negative ; bymonthday_clause : BYMONTHDAY '=' monthday_list ; monthday_list : monthday (COMMA monthday)* ; monthday : lt_integer_negative ; byday_clause : BYDAY '=' byday_list ; byday_list : byday (COMMA byday)* ; byday : weekdaynum_options? day ; weekdaynum_options : weekdaynum ; weekdaynum : lt_integer_negative ; day : MON | TUE | WED | THU | FRI | SAT | SUN ; byhour_clause : BYHOUR '=' hour_list ; hour_list : hour (COMMA hour)* ; hour : LT_INTEGER ; byminute_clause : BYMINUTE '=' minute_list ; minute_list : minute (COMMA minute)* ; minute : LT_INTEGER ; bysecond_clause : BYSECOND '=' second_list ; second_list : second (COMMA second)* ; second : LT_INTEGER ; query_rewrite : ENABLE QUERY REWRITE | DISABLE QUERY REWRITE ; build_clause : BUILD IMMEDIATE | BUILD DEFERRED ; mv_refresh_option : ON DEMAND | ON COMMIT | WITH PRIMARY KEY | WITH ROWID | START WITH exp | NEXT exp | FAST | COMPLETE | FORCE | complete_del_null ; mv_refresh_option_list : mv_refresh_option+ ; mv_refresh_clause : REFRESH mv_refresh_option_list | NEVER REFRESH ; mv_log_purge_syn_asyn_clause : SYNCHRONOUS | ASYNCHRONOUS ; mv_log_purge_clause : PURGE REPEAT exp | PURGE START WITH exp REPEAT exp | PURGE IMMEDIATE mv_log_purge_syn_asyn_clause? | PURGE START WITH exp NEXT exp | PURGE START WITH exp | PURGE NEXT exp ; mv_log_with_syntax_item : PRIMARY KEY | ROWID | SEQUENCE ; mv_log_with_syntax_item_list : mv_log_with_syntax_item | mv_log_with_syntax_item COMMA mv_log_with_syntax_item | mv_log_with_syntax_item COMMA mv_log_with_syntax_item COMMA mv_log_with_syntax_item ; mv_log_including_new_values : INCLUDING NEW VALUES | EXCLUDING NEW VALUES ; mv_log_with_clause_null : mv_log_including_new_values? | WITH mv_log_with_syntax_item_list? column_list_options? mv_log_including_new_values? ; create_materialized_view_log_stmt : CREATE MATERIALIZED VIEW LOG ON full_table_name horizon_partition_clause? space_limit? storage_tag? compress_tag? ctab_log_options? mv_log_with_clause_null mv_log_purge_clause? ; prebuilt_table_clause_null : ON PREBUILT TABLE | ON PREBUILT TABLE WITHOUT REDUCED PRECISION | ON PREBUILT TABLE WITH REDUCED PRECISION ; create_materialized_view_stmt : CREATE MATERIALIZED VIEW full_view_name2 column_list_options? build_clause? horizon_partition_clause? storage_tag? compress_tag? ctab_log_options? mv_refresh_clause? query_rewrite? AS select_stmt | CREATE MATERIALIZED VERTICAL VIEW full_view_name2 column_list_options? build_clause? horizon_partition_clause? storage_tag? compress_tag? ctab_log_options? mv_refresh_clause? query_rewrite? AS select_stmt | CREATE MATERIALIZED VIEW FOR full_table_name mv_refresh_clause? AS select_stmt | CREATE MATERIALIZED VIEW full_view_name2 FOR full_table_name prebuilt_table_clause_null mv_refresh_clause? query_rewrite? AS select_stmt ; create_view_stmt : CREATE replace_option? force? VIEW not_exist? create_view_stmt_body ; create_view_stmt_body : full_view_name2 column_list3_options? with_schemabinding? AS (without_into_select2 with_check_or_readonly_option? | joined_table | TABLE full_tv_name) ; column_list3_options : '(' column_list3 ')' ; column_list3 : column_name compress_level? compress_type? | column_list3 COMMA column_name compress_level? compress_type? | column_list3 COMMA view_constraint_def | column_name view_column_constraint_def | column_list3 COMMA column_name view_column_constraint_def ; view_column_constraint_def : view_column_constraints constraint_attributes_options? ; view_column_constraints : view_column_constraint ; view_column_constraint : constraint_name_def_options? view_column_constraint_action DISABLE cons_novalidate? ; view_column_constraint_action : view_unique_spec | view_refs_spec ; view_constraint_def : constraint_name_def_options? view_constraint_clause DISABLE cons_novalidate? ; with_schemabinding : WITH SCHEMABINDING ; column_list_options : '(' column_list ')' ; with_check_or_readonly_option : WITH check_level_option? CHECK OPTION | WITH READ ONLY ; check_level_option : LOCAL | CASCADED ; decl_cursor : cursor_declaration_2 ; delete_stmt : with_option? DELETE delete_stmt_body ; delete_stmt_body : from_tag? from_tv where_current_option return_into_obj? limit_option? check_limit_option? log_errors? | from_tag? full_tv_name delete_multi_tv_option where_current_option return_into_obj? limit_option? check_limit_option? log_errors? ; delete_multi_tv_option : FROM from_tv_list | USING from_tv_list ; check_limit_option : CHECK LIMIT LT_INTEGER ; where_current_option : where_clause? | WHERE CURRENT OF qualified_name | WHERE CURRENT OF CURSOR ; where_clause : WHERE search_condition ; start_with_clause_null : START WITH search_condition ; connect_by_item : CONNECT BY nocycle_flag? search_condition ; connect_by_clause : connect_by_item+ ; hierarchical_query_clause : connect_by_clause start_with_clause_null? | start_with_clause_null connect_by_clause ; nocycle_flag : NOCYCLE ; search_condition : bool_exp ; disconnect_stmt : DISCONNECT disconnect_option ; disconnect_option : CURRENT | ALL ; drop_stmt : DROP drop_db_object drop_stmt_body_1 | drop_stmt_2 ; drop_stmt_body_1 : full_object_name restrict_cascade? purge_option? is_detach? | LOG ON full_table_name ; drop_stmt_2 : DROP drop_id_db_object full_object_name restrict_cascade? is_detach? | DROP PUBLIC drop_db_object full_object_name restrict_cascade? is_detach? | DROP PUBLIC drop_id_db_object full_object_name restrict_cascade? is_detach? | DROP TABLESPACE exist? tablespace_name | DROP HUGE TABLESPACE exist? full_object_name | DROP PARTITION GROUP full_object_name force_option? ; drop_id_db_object : id_db_object exist? ; id_db_object : ROLE | TYPE | SEQUENCE | DIRECTORY | PACKAGE | LINK | PROFILE ; drop_db_object : db_object exist? ; exist : IF EXISTS ; not_exist : IF NOT EXISTS ; db_object : FUNCTION | INDEX | PROCEDURE | TABLE | TRIGGER | VIEW | MATERIALIZED VIEW | USER | SCHEMA | LOGIN | AUDIT RULE | CRYPTO | PACKAGE BODY | TYPE BODY | SYNONYM | CLASS | CLASS BODY | DOMAIN | CHARACTER SET | COLLATION | CONTEXT | TABLESPACE SET ; is_detach : DETACH ; purge_option : PURGE ; alter_database_stmt : alter_tag DATABASE alter_database_action | alter_tag DATABASE ADD NODE LOGFILE file_list | alter_tag DATABASE ADD NODE | alter_tag SYSTEM alter_system_action ; alter_system_action : ARCHIVE LOG CURRENT | SWITCH LOGFILE ; alter_database_action : ADD LOGFILE file_list | RENAME LOGFILE pathname_list TO pathname_list | RESIZE LOGFILE pathname TO LT_INTEGER | MOUNT | OPEN force? | SUSPEND | NORMAL force? | PRIMARY force? | STANDBY force? | ADD ARCHIVELOG LT_STRING | DELETE ARCHIVELOG LT_STRING | MODIFY ARCHIVELOG LT_STRING | ARCHIVELOG | NOARCHIVELOG | ARCHIVELOG CURRENT | ENABLE BLOCK CHANGE TRACKING | DISABLE BLOCK CHANGE TRACKING ; force : NO FORCE | FORCE ; tablespace_name : id ; raft_name : id ; fetch_into : INTO assignment_obj_list ; bulk_or_single_into : fetch_into | BULK COLLECT INTO assignment_obj_list ; fetch_stmt : FETCH fetch_tail ; fetch_statement : FETCH CURSOR fetch_tail ; fetch_tail : fetch_option? assign_obj bulk_or_single_into? fetch_limit_option? ; fetch_limit_option : LIMIT exp ; fetch_option : fetch_direct_option from_tag? ; fetch_direct_option : NEXT | PRIOR | FIRST | LAST2 | ABSOLUTE top_exp | RELATIVE top_exp ; log_errors_into : INTO full_tv_name ; log_errors_expression : '(' exp ')' ; log_errors_unlimited : REJECT LIMIT UNLIMITED | REJECT LIMIT LT_INTEGER ; log_errors : LOG ERRORS log_errors_into? log_errors_expression? log_errors_unlimited ; insert_stmt : INSERT insert_stmt_body ; insert_stmt_body : into_tag? full_tv_name alias_option? insert_tail return_into_obj? log_errors? | into_tag? select_with_paran alias_option? insert_tail return_into_obj? log_errors? | multi_insert_stmt_body ; full_column_list_options : '(' full_column_list ')' ; ins_value_options : VALUES ins_value ; insert_into_single : INTO full_tv_name alias_option? full_column_list_options? ins_value_options? ; multi_insert_into_list : insert_into_single+ ; multi_insert_tag : ALL | FIRST ; insert_into_single_condition : WHEN bool_exp THEN multi_insert_into_list ; multi_insert_into_condition_list : insert_into_single_condition+ ; multi_insert_into_else : ELSE multi_insert_into_list ; multi_insert_stmt_body : ALL multi_insert_into_list without_into_select2 log_errors? | multi_insert_tag? multi_insert_into_condition_list multi_insert_into_else? without_into_select2 log_errors? ; insert_tail : insert_action | '(' full_column_list ')' insert_action ; insert_action : VALUES ins_value | without_into_select2 | DEFAULT VALUES | call_proc_stmt_2 | VALUES record_var_values | TABLE full_tv_name ; record_var_values : record_var_value (COMMA record_var_value)* ; record_var_value : member | invocation_expression | element_access | member_access ; ins_value : '(' ')' | '(' ins_value_list ')' | ins_value COMMA '(' ins_value_list ')' ; open_stmt : OPEN open_tail ; open_statement : OPEN CURSOR open_tail ; open_tail : assign_obj2 | assign_obj2 FOR without_into_select | assign_obj2 FOR exp using_clause? ; return_stmt : RETURN | RETURN bool_exp ; raise_stmt : RAISE exp | RAISE ; rollback_stmt : ROLLBACK work_tag? commit_tail? to_savepoint? ; to_savepoint : TO SAVEPOINT savepoint_name | TO savepoint_name ; savepoint_stmt : SAVEPOINT savepoint_name ; select_stmt : without_into_select2 ; all_distinct_option : ALL | DISTINCT | UNIQUE ; all_distinct_option_2 : ALL | DISTINCT | UNIQUE ; corresponding_clause : CORRESPONDING | CORRESPONDING BY '(' column_list ')' ; top_option : TOP top_exp PERCENT? (WITH TIES)? | TOP top_exp COMMA top_exp ; limit_option : limit_clause | row_limiting_clause ; limit_clause : LIMIT top_exp ((OFFSET | COMMA) top_exp)? | OFFSET top_exp LIMIT top_exp ; limit_not_empty : limit_clause | row_limiting_clause ; row_limiting_clause : FETCH first_next_desc row_num_desc ONLY | FETCH first_next_desc top_exp row_num_desc ONLY | FETCH first_next_desc row_num_desc WITH TIES | FETCH first_next_desc top_exp row_num_desc WITH TIES | FETCH first_next_desc top_exp PERCENT row_num_desc ONLY | FETCH first_next_desc top_exp PERCENT row_num_desc WITH TIES | OFFSET top_exp row_num_desc | OFFSET top_exp row_num_desc FETCH first_next_desc row_num_desc ONLY | OFFSET top_exp row_num_desc FETCH first_next_desc top_exp row_num_desc ONLY | OFFSET top_exp row_num_desc FETCH first_next_desc row_num_desc WITH TIES | OFFSET top_exp row_num_desc FETCH first_next_desc top_exp row_num_desc WITH TIES | OFFSET top_exp row_num_desc FETCH first_next_desc top_exp PERCENT row_num_desc ONLY | OFFSET top_exp row_num_desc FETCH first_next_desc top_exp PERCENT row_num_desc WITH TIES ; row_num_desc : ROW | ROWS ; first_next_desc : FIRST | NEXT ; select_item_list : select_item (COMMA select_item)* ; select_item : exp (alias | AS alias_2) | bool_exp | '*' ; as_alias : AS alias_2 ; select_tail : from_clause? where_clause? hierarchical_query_clause? (group_by_clause having_clause? | having_clause group_by_clause?)? ; from_clause : FROM from_tv_list ; from_tv_list : from_tv (COMMA from_tv)* ; from_tv : normal_tv joined_table_element* | '(' normal_tv joined_table_element+ ')' ; joined_table : normal_tv joined_table_element+ | '(' normal_tv joined_table_element+ ')' ; trxid : LT_INTEGER ; flashback_query_low : WHEN TIMESTAMP exp | WHEN TRXID trxid | AS OF TIMESTAMP exp | AS OF scn_or_lsn trxid | VERSIONS BETWEEN TIMESTAMP exp AND exp | VERSIONS BETWEEN TRXID trxid AND trxid | VERSIONS BETWEEN scn_or_lsn trxid_option AND trxid_option | AFTER OF TIMESTAMP exp | AFTER OF scn_or_lsn trxid ; trxid_option : trxid | MINVALUE | MAXVALUE ; range_from_to : TOP LT_INTEGER | FROM LT_INTEGER TO LT_INTEGER ; sample_exp : LT_DECIMAL | LT_INTEGER | LT_REAL ; pivot_sfun : invocation_expression as_alias? | invocation_expression alias ; pivot_sfun_lst : pivot_sfun (COMMA pivot_sfun)* ; pivot_for_clause : FOR '(' exp_list_2 ')' | FOR exp ; pivot_in_clause1_expr : exp as_alias? | exp alias | '(' exp_list_2 ')' as_alias? | '(' exp_list_2 ')' alias | ANY ; pivot_in_clause_low_1 : pivot_in_clause1_expr | pivot_in_clause_low_1 COMMA pivot_in_clause1_expr ; pivot_in_clause_low_2 : without_into_select ; pivot_in_clause_low : pivot_in_clause_low_1 | pivot_in_clause_low_2 ; pivot_xml : XML ; pivot_clause_low : PIVOT pivot_xml? '(' pivot_sfun_lst pivot_for_clause IN '(' pivot_in_clause_low? ')' ')' ; unpivot_val_col_lst : exp | '(' exp_list_2 ')' ; include_clause : INCLUDE NULLS | EXCLUDE NULLS ; unpivot_in_clause_expr : exp AS exp | exp | '(' exp_list_2 ')' AS '(' exp_list_2 ')' | '(' exp_list_2 ')' AS exp | '(' exp_list_2 ')' ; unpivot_in_clause_low : unpivot_in_clause_expr (COMMA unpivot_in_clause_expr)* ; unpivot_clause_low : UNPIVOT include_clause? '(' unpivot_val_col_lst pivot_for_clause IN '(' unpivot_in_clause_low ')' ')' ; sample_clause_low : SAMPLE '(' sample_exp ')' | SAMPLE '(' sample_exp ')' SEED '(' sample_exp ')' | SAMPLE BLOCK '(' sample_exp ')' | SAMPLE BLOCK '(' sample_exp ')' SEED '(' sample_exp ')' ; normal_tv_name : full_tv_name | '(' full_tv_name ')' ; normal_tv_tail : normal_tv_tail_low (WITH '(' NOLOCK ')')? | WITH '(' NOLOCK ')' normal_tv_tail_low? ; normal_tv_tail_low : normal_tv_tail_low2 normal_alias? | normal_alias ; normal_alias : AS alias_2 | alias ; normal_tv_tail_low2 : normal_tv_tail_low3+ ; normal_tv_tail_low3 : normal_alias? (pivot_clause_low | unpivot_clause_low) | flashback_query_low | sample_clause_low ; normal_tv_derived_table_options : normal_tv_derived_table_low ; normal_tv_derived_table_low : normal_tv_tail_low2 (normal_alias column_list_options?)? | normal_alias column_list_options? ; normal_tv_derived_table : select_with_paran | select_with_paran_with_alias ; select_with_paran_with_alias : select_with_paran normal_tv_derived_table_low | '(' select_with_paran_with_alias ')' normal_alias ? ; from_table_exp : TABLE '(' exp ')' | '(' from_table_exp ')' ; from_table_select_with_paran : TABLE select_with_paran | '(' from_table_select_with_paran ')' ; normal_tv : normal_tv_name normal_tv_tail? | ARRAY pexp_pfx range_from_to? (as_alias | alias)? | from_table_exp range_from_to? alias | from_table_select_with_paran range_from_to? (as_alias | alias)? | XMLTABLE '(' exp xml_passing? xmlcoldef_lst_options? ')' alias_option? | JSON_TABLE '(' argument COMMA LT_STRING on_error? jsoncol_lst ')' (as_alias | alias)? | normal_tv_derived_table | full_tv_name '(' column_list2 ')' normal_tv_derived_table_options? ; xml_passing : PASSING exp ; xmlcoldef_lst_options : COLUMNS xmlcoldef_lst ; xmlcoldef_lst : xmlcoldef (COMMA xmlcoldef)* ; xmlcoldef : column_name datatype PATH exp ; on_error : NULL ON ERROR | ERROR ON ERROR | DEFAULT exp ON ERROR ; jsoncol_lst : COLUMNS '(' jsoncoldef_lst ')' ; jsoncoldef_lst : jsoncoldef (COMMA jsoncoldef)* ; jsoncoldef : json_exists_col | json_qurey_col | json_value_col | json_nested_col | ordinality_col ; json_exists_col : column_name datatype EXISTS PATH LT_STRING on_error? ; json_qurey_col : column_name datatype FORMAT JSON PATH LT_STRING on_error? ; json_value_col : column_name datatype PATH LT_STRING on_error? ; json_nested_col : NESTED_PATH LT_STRING jsoncol_lst ; ordinality_col : column_name FOR ORDINALITY ; joined_table_element : cross_join | qualified_join | cross_outer_apply_join ; cross_outer_apply_clause : CROSS APPLY | OUTER APPLY ; cross_outer_apply_join : cross_outer_apply_clause normal_tv | cross_outer_apply_clause '(' joined_table ')' ; cross_join : CROSS JOIN normal_tv | CROSS JOIN '(' joined_table ')' ; partition_out_join : PARTITION BY '(' exp_list ')' ; qualified_join : NATURAL JOIN normal_tv | NATURAL JOIN '(' joined_table ')' | NATURAL join_type JOIN normal_tv | NATURAL join_type JOIN '(' joined_table ')' | JOIN from_tv qualified_joinspec | partition_out_join? join_type join_hint? JOIN from_tv partition_out_join? qualified_joinspec ; qualified_joinspec : ON join_condition | named_columns_join ; named_columns_join : USING '(' column_list ')' ; join_hint : HASH | MERGE ; join_type : INNER | outer_join_type (INNER | OUTER)? ; outer_join_type : LEFT | RIGHT | FULL ; join_condition : bool_exp ; group_by_clause : GROUP BY group_item ; group_item : exp_rollup_cube_item | exp_rollup_cube_item2 ; exp_rollup_cube_item2 : exp_rollup_cube_item COMMA exp_rollup_cube_item | exp_rollup_cube_item2 COMMA exp_rollup_cube_item ; exp_rollup_cube_item : exp | '(' ')' | '(' exp_list_2 ')' | ROLLUP '(' grouping_set_items ')' | CUBE '(' grouping_set_items ')' | GROUPING SETS '(' grouping_set_items ')' ; grouping_set_items : grouping_set_item | grouping_set_items COMMA grouping_set_item ; grouping_set_item : exp | '(' ')' | '(' exp_list_2 ')' ; having_clause : HAVING search_condition ; without_into_select : (simple_select | select_with_paran) (sel_clause_app for_xml_path?)? ; sel_clause_app : order_by ((for_update limit_option?) | (limit_not_empty for_update_options?))? | for_update order_by? limit_option? | limit_not_empty order_by? for_update_options? ; select_clause : query_exp | select_with_paran ; simple_select : select_clause ( (UNION | EXCEPT | MINUS | INTERSECT) all_distinct_option? corresponding_clause? select_clause)* ; select_with_paran : '(' without_into_select ')' | '(' select_with_paran ')' ; query_exp : with_option? SELECT all_distinct_option? top_option? select_item_list bulk_or_single_into? select_tail for_xml_path? ; for_xml_path : FOR XML PATH '(' LT_STRING ')' ; with_tag : WITH | WITH RECURSIVE ; with_option : with_tag with_clause ; with_clause : with_function_list | with_view_list | with_function_list with_view_list ; with_function_list : with_function_list_element+ ; func_def_inner : encryption_option? calc_option? param_def_list_option? RETURN plsql_datatype func_call_options? func_action ; with_function_list_element : FUNCTION id func_def_inner SEMI ; with_view_list : with_view_list_element (COMMA with_view_list_element)* ; depth_type_option : DEPTH FIRST BY | BREADTH FIRST BY ; search_clause : SEARCH depth_type_option order_by_list SET full_column_name ; cycle_clause : CYCLE full_column_list SET full_column_name TO default_exp DEFAULT default_exp ; with_view_list_element : id column_list_options? AS select_with_paran search_clause? cycle_clause? ; assignment_obj_list : assignment_obj (COMMA assignment_obj)* ; assignment_obj : pexp_pfx | stm_param_name ; order_by_options : order_by ; order_by : ORDER BY order_by_list | ORDER SIBLINGS BY order_by_list ; asc_desc_option : ASC | DESC ; nulls_last_option : NULLS FIRST | NULLS LAST ; collate_option : COLLATE id ; order_by_list : order_by_item (COMMA order_by_item)* ; order_by_item : bool_exp collate_option? asc_desc_option? nulls_last_option? ; for_update_options : for_update ; for_update : FOR READ ONLY | FOR update_of_option ; set_session_stmt : SET SESSION CHARACTERISTICS AS trans_mode_lst ; set_trans_stmt : SET TRANSACTION trans_mode_lst | SET TIME ZONE exp | START TRANSACTION trans_mode_lstl? ; trans_mode_lstl : trans_mode_lst ; trans_mode_lst : trans_mode (COMMA trans_mode)* ; trans_mode : trans_rw_option | ISOLATION LEVEL trans_level_option | DIAGNOSTICS SIZE LT_INTEGER ; time_zone_exp_new : AT LOCAL | AT TIME ZONE exp ; trans_rw_option : READ ONLY | READ WRITE ; trans_level_option : READ COMMITTED | SERIALIZABLE | REPEATABLE READ | READ UNCOMMITTED ; lock_table_stmt : LOCK TABLE full_tv_name IN lock_mode_option MODE | LOCK TABLE full_tv_name IN lock_mode_option MODE NOWAIT ; lock_mode_option : SHARE | EXCLUSIVE | INTENT SHARE | INTENT EXCLUSIVE | SHARE INTENT EXCLUSIVE | ROW SHARE | SHARE UPDATE | ROW EXCLUSIVE | SHARE ROW EXCLUSIVE ; set_identins_stmt : SET IDENTITY_INSERT full_table_name set_identins_option ; set_identins_option : OFF | ON | ON WITH REPLACE NULL ; trunc_table_stmt : TRUNCATE TABLE full_table_name reuse_storage_option? cascade_opt? | TRUNCATE TABLE full_table_name PARTITION truncate_partition_name reuse_storage_option? cascade_opt? ; update_stmt : with_option? UPDATE update_stmt_body ; update_stmt_body : update_tv_list SET set_value_list update_from_clause? where_current_option collect_into_rset? return_into_obj? limit_option? check_limit_option? log_errors? ; update_tv_list : from_tv_list ; return_item : exp ; return_item_list : return_item (COMMA return_item)* ; return_option : RETURN | RETURNING ; return_into_obj : return_option return_item_list INTO assignment_obj_list | return_option return_item_list BULK COLLECT INTO assignment_obj_list ; collect_into_rset : INTO assignment_obj ; alias_option : alias | AS alias_2 ; set_value_list : set_value_node (COMMA set_value_node)* ; set_value_node : full_column_name assign_op DEFAULT | full_column_name assign_op exp | '(' set_col_list ')' assign_op select_with_paran | '(' set_col_list ')' assign_op record_var_value | ROW assign_op record_var_value ; set_col_list : full_column_name (COMMA full_column_name)* ; update_from_clause : from_clause ; merge_into_stmt : MERGE merge_into_stmt_body ; merge_into_stmt_body : INTO full_tv_name alias_option? USING from_tv ON bool_exp merge_into_sub_clause log_errors? | INTO select_with_paran alias_option? USING from_tv ON bool_exp merge_into_sub_clause log_errors? ; merge_into_sub_clause : merge_update_clause merge_insert_clause | merge_insert_clause merge_update_clause | merge_update_clause | merge_insert_clause ; merge_update_clause : WHEN MATCHED THEN UPDATE SET set_value_list where_clause? | WHEN MATCHED THEN UPDATE SET set_value_list where_clause? DELETE where_clause? ; merge_insert_clause : WHEN NOT MATCHED THEN INSERT full_column_list_options? VALUES '(' ins_value_list ')' where_clause? ; create_profile_stmt : CREATE PROFILE not_exist? profile_name resource_limit_options? ; alter_profile_stmt : alter_tag PROFILE profile_name resource_limit_options? ; create_user_stmt : CREATE USER not_exist? user_name | CREATE USER not_exist? user_name IDENTIFIED authent_type pwd_policy? account_lock? user_encrypt_options? space_limit? read_only_flag? resource? expire? allow_ip_list? not_allow_ip_list? allow_dt_list? not_allow_dt_list? default_ts_name? quota_ts? ; default_ts_name : default_ts_name_lst ; default_ts_name_lst : default_ts_name_node+ ; default_ts_name_node : default_ts_name_low | temp_ts_name | default_idx_ts_name | default_ts_group_name_low ; default_idx_ts_name : DEFAULT INDEX TABLESPACE tablespace_name ; default_ts_name_low : DEFAULT TABLESPACE tablespace_name | DEFAULT TABLESPACE NULL ; temp_ts_name : TEMPORARY TABLESPACE tablespace_name ; default_ts_group_name_low : DEFAULT TABLESPACE GROUP tablespace_name | DEFAULT TABLESPACE GROUP NULL ; on_schema : ON SCHEMA id ; replace_old_pwd : REPLACE password ; alter_user_stmt : alter_tag USER user_name authent_type_options? replace_old_pwd? pwd_policy? account_lock? user_encrypt_options? space_limit2? read_only_flag? resource? expire? allow_ip_list? not_allow_ip_list? allow_dt_list? not_allow_dt_list? default_ts_name? on_schema? quota_ts? | alter_tag USER user_name GRANT CONNECT THROUGH user_name | alter_tag USER user_name REVOKE CONNECT THROUGH user_name ; user_encrypt_options : user_encrypt_option ; user_encrypt_option : ENCRYPT BY password | ENCRYPT BY WRAPPED LT_STRING ; authent_type_options : IDENTIFIED authent_type ; hash_cipher_option : hash_cipher ; authent_type : BY password hash_cipher_option? force_format? | EXTERNALLY as? | BY WRAPPED LT_STRING hash_cipher_option? ; force_format : FORCE FORMAT ; as : AS LT_STRING ; pwd_policy : PASSWORD_POLICY LT_INTEGER ; account_lock : ACCOUNT LOCK | ACCOUNT UNLOCK ; read_only_flag : READ ONLY | NOT READ ONLY ; read_only_flag_not_null : READ ONLY | READ WRITE ; resource : LIMIT resource_limit_list | PROFILE profile_name | DROP PROFILE ; expire : PASSWORD EXPIRE ; resource_limit_options : LIMIT resource_limit_list ; resource_limit_list : resource_limit_list_with_comma | resource_limit_list_with_empty ; resource_limit_list_with_comma : resource_limit | resource_limit COMMA resource_limit_list_with_comma ; resource_limit_list_with_empty : resource_limit resource_limit | resource_limit resource_limit_list_with_empty ; resource_limit : SESSION_PER_USER resource_limit_value | CONNECT_IDLE_TIME resource_limit_value | FAILED_LOGIN_ATTEMPS resource_limit_value | FAILED_LOGIN_ATTEMPTS resource_limit_value | PASSWORD_LIFE_TIME resource_limit_value | PASSWORD_REUSE_TIME resource_limit_value | PASSWORD_REUSE_MAX resource_limit_value | PASSWORD_LOCK_TIME resource_limit_value | PASSWORD_GRACE_TIME resource_limit_value | CPU_PER_CALL resource_limit_value | CPU_PER_SESSION resource_limit_value | MEM_SPACE resource_limit_value | READ_PER_CALL resource_limit_value | READ_PER_SESSION resource_limit_value | CONNECT_TIME resource_limit_value ; resource_limit_value : UNLIMITED | DEFAULT | LT_INTEGER ; create_audit_rule_stmt : CREATE AUDIT RULE rule_name audit_rule_action by_login_or_all whenever_stmt_options? allow_ip_list? allow_dt_list? op_freq? ; rule_name : id ; audit_rule_action : STARTUP | SHUTDOWN | DATABASE | LOGIN | CONNECT | ROLLBACK | COMMIT | USER | ROLE | SCHEMA | TABLE | VIEW | INDEX | PROCEDURE | TRIGGER | SEQUENCE | CONTEXT | GRANT | REVOKE | AUDIT | NOAUDIT | INSERT TABLE | UPDATE TABLE | DELETE TABLE | SELECT TABLE | LOCK TABLE | EXECUTE PROCEDURE | SELECT ON full_object_name | INSERT ON full_object_name | UPDATE ON full_object_name | DELETE ON full_object_name | EXECUTE ON full_object_name | PACKAGE | PACKAGE BODY | SYNONYM | TYPE | TYPE BODY | PROFILE ; by_login_or_all : BY login_name | BY ALL ; allow_ip_list : ALLOW_IP NULL | ALLOW_IP ip_list ; not_allow_ip_list : NOT_ALLOW_IP NULL | NOT_ALLOW_IP ip_list ; ip_list : id | id COMMA ip_list ; allow_dt_list : ALLOW_DATETIME NULL | ALLOW_DATETIME dt_list ; not_allow_dt_list : NOT_ALLOW_DATETIME NULL | NOT_ALLOW_DATETIME dt_list ; dt_list : dt | dt COMMA dt_list ; dt : id id TO id id ; op_freq : INTERVAL LT_INTEGER TIMES LT_INTEGER ; quota_val : LT_INTEGER | LT_INTEGER LT_IDENTIFIER ; quota_ts_node : QUOTA quota_val ON tablespace_name | QUOTA UNLIMITED ON tablespace_name ; quota_ts_lst : quota_ts_node | quota_ts_lst quota_ts_node ; quota_ts : quota_ts_lst | QUOTA UNLIMITED | QUOTA LT_INTEGER ; create_role_stmt : CREATE ROLE not_exist? role_name ; create_dblink_stmt : CREATE replace_option? LINK not_exist? qualified_name CONNECT db_type_str? WITH login_name IDENTIFIED BY password USING LT_STRING dblink_option_lst_options? | CREATE replace_option? LINK not_exist? qualified_name CONNECT db_type_str? WITH login_name IDENTIFIED BY WRAPPED LT_STRING USING LT_STRING dblink_option_lst_options? | CREATE replace_option? PUBLIC LINK not_exist? qualified_name CONNECT db_type_str? WITH login_name IDENTIFIED BY password USING LT_STRING dblink_option_lst_options? | CREATE replace_option? PUBLIC LINK not_exist? qualified_name CONNECT db_type_str? WITH login_name IDENTIFIED BY WRAPPED LT_STRING USING LT_STRING dblink_option_lst_options? ; db_type_str : LT_STRING ; dblink_option_lst_options : OPTION '(' dblink_option_lst ')' ; dblink_option_lst : dblink_option (COMMA dblink_option)* ; dblink_option : id '=' exp ; create_synonym_stmt : CREATE replace_option? PUBLIC SYNONYM not_exist? full_synonym_name FOR full_obj_name | CREATE replace_option? SYNONYM not_exist? full_synonym_name FOR full_obj_name ; full_synonym_name : qualified_name ; full_obj_name : qualified_name dblink_clause? ; create_domain_stmt : CREATE DOMAIN not_exist? qualified_name as_tag? datatype charset_option? domain_default_option? domain_constraints_option? ; domain_default_option : default_clause ; domain_constraints_option : domain_constraints_def ; domain_constraints_def : domain_constraints constraint_attributes_options? ; domain_constraints : domain_constraint+ ; domain_constraint : domain_constraint_name_def_options? column_constraint_action ; domain_constraint_name_def_options : domain_constraint_name_def ; domain_constraint_name_def : CONSTRAINT domain_constraint_name ; domain_constraint_name : qualified_name ; create_character_set_stmt : CREATE CHARACTER SET not_exist? character_set_name as_tag? character_set_source collate_clause_option? ; character_set_source : GET existing_character_set_name ; existing_character_set_name : character_set_name ; character_set_name : qualified_name ; collate_clause_option : COLLATE collation_name | COLLATION FROM DEFAULT ; collation_name : qualified_name ; create_collation_stmt : CREATE COLLATION not_exist? collation_name FOR existing_character_set_name FROM existing_collation_name pad_option? ; existing_collation_name : collation_name ; pad_option : NO PAD | PAD SPACE_KEYWORD ; create_sequence_stmt : CREATE SEQUENCE not_exist? sequence_name sequence_option_list_options? | alter_tag SEQUENCE sequence_name sequence_option_list_options? ; sequence_option_list_options : sequence_option_list ; sequence_option_list : sequence_option | sequence_option sequence_option_list ; sequence_option : increment_option | start_option | current_option | maxvalue_option | minvalue_option | cycle_option | cache_option | order_option | seq_local_option ; sequence_name : qualified_name ; increment_option : INCREMENT BY exp ; start_option : START WITH exp ; current_option : CURRENT VALUE exp ; maxvalue_option : MAXVALUE exp | NOMAXVALUE ; minvalue_option : MINVALUE exp | NOMINVALUE ; cycle_option : CYCLE | NOCYCLE ; cache_option : CACHE exp | NOCACHE ; order_option : ORDER | NOORDER ; seq_local_option : GLOBAL | LOCAL ; whenever_stmt_options : WHENEVER whenever_stmt ; whenever_stmt : SUCCESSFUL | NOT SUCCESSFUL ; grant_stmt : grant_tag grant_stmt_body ; grant_tag : GRANT ; grant_stmt_body : grant_privs ON full_object_name TO grantees with_grant_option? by_grantor? | grant_privs ON db_object full_object_name TO grantees with_grant_option? by_grantor? | grant_privs ON qualified_name full_object_name TO grantees with_grant_option? by_grantor? | db_priv_list TO grantees with_admin_option? by_grantor? | grant_privs TO grantees with_admin_option? by_grantor? ; revoke_stmt : REVOKE revoke_stmt_body ; revoke_stmt_body : grant_privs ON full_object_name FROM grantees revoke_action? by_grantor? | GRANT OPTION FOR grant_privs ON full_object_name FROM grantees revoke_action? by_grantor? | grant_privs ON db_object full_object_name FROM grantees revoke_action? by_grantor? | GRANT OPTION FOR grant_privs ON db_object full_object_name FROM grantees revoke_action? by_grantor? | grant_privs ON qualified_name qualified_name FROM grantees revoke_action? by_grantor? | GRANT OPTION FOR grant_privs ON qualified_name qualified_name FROM grantees revoke_action? by_grantor? | db_priv_list FROM grantees by_grantor? | ADMIN OPTION FOR db_priv_list FROM grantees by_grantor? | grant_privs FROM grantees by_grantor? | ADMIN OPTION FOR role_name_list FROM grantees by_grantor? ; grant_privs : ALL | ALL PRIVILEGES | grant_priv_list ; grant_priv_list : grant_priv | grant_priv COMMA grant_priv_list ; grant_priv_off : OFF ; grant_priv : SELECT grant_priv_off? | INSERT grant_priv_off? | DELETE grant_priv_off? | UPDATE grant_priv_off? | REFERENCES grant_priv_off? | EXECUTE grant_priv_off? | SELECT FOR DUMP grant_priv_off? | SELECT '(' column_list ')' | UPDATE '(' column_list ')' | INSERT '(' column_list ')' | REFERENCES '(' column_list ')' | ALTER grant_priv_off? | INDEX grant_priv_off? | role_name | FLASHBACK grant_priv_off? ; revoke_action : RESTRICT | CASCADE ; db_priv_list : db_priv | db_priv COMMA db_priv_list ; db_priv : ALTER DATABASE | BACKUP DATABASE | RESTORE DATABASE | CREATE USER | ALTER USER | DROP USER | CREATE ROLE | DROP ROLE | ADMIN ANY ROLE | ADMIN ANY DATABASE PRIVILEGE | GRANT ANY OBJECT PRIVILEGE | CREATE SCHEMA | DROP SCHEMA | CREATE ANY SCHEMA | DROP ANY SCHEMA | CREATE TABLE | DROP TABLE | CREATE ANY TABLE | ALTER ANY TABLE | ALTER TABLE | DROP ANY TABLE | INSERT TABLE | INSERT ANY TABLE | UPDATE TABLE | UPDATE ANY TABLE | DELETE TABLE | DELETE ANY TABLE | SELECT TABLE | SELECT ANY TABLE | REFERENCES TABLE | REFERENCES ANY TABLE | GRANT TABLE | GRANT ANY TABLE | CREATE VIEW | DROP VIEW | CREATE ANY VIEW | ALTER ANY VIEW | ALTER VIEW | DROP ANY VIEW | INSERT VIEW | INSERT ANY VIEW | UPDATE VIEW | UPDATE ANY VIEW | DELETE VIEW | DELETE ANY VIEW | SELECT VIEW | SELECT ANY VIEW | GRANT VIEW | GRANT ANY VIEW | CREATE PROCEDURE | DROP PROCEDURE | CREATE ANY PROCEDURE | DROP ANY PROCEDURE | EXECUTE PROCEDURE | EXECUTE ANY PROCEDURE | GRANT PROCEDURE | GRANT ANY PROCEDURE | CREATE SEQUENCE | DROP SEQUENCE | ALTER ANY SEQUENCE | ALTER SEQUENCE | CREATE ANY SEQUENCE | DROP ANY SEQUENCE | SELECT SEQUENCE | SELECT ANY SEQUENCE | GRANT SEQUENCE | GRANT ANY SEQUENCE | DROP TRIGGER | CREATE TRIGGER | CREATE ANY TRIGGER | DROP ANY TRIGGER | ALTER ANY TRIGGER | ALTER TRIGGER | CREATE INDEX | DROP INDEX | CREATE ANY INDEX | ALTER ANY INDEX | ALTER INDEX | DROP ANY INDEX | CREATE CONTEXT INDEX | DROP CONTEXT INDEX | CREATE ANY CONTEXT INDEX | ALTER ANY CONTEXT INDEX | ALTER CONTEXT INDEX | DROP ANY CONTEXT INDEX | CREATE PACKAGE | DROP PACKAGE | CREATE ANY PACKAGE | DROP ANY PACKAGE | EXECUTE PACKAGE | EXECUTE ANY PACKAGE | GRANT PACKAGE | GRANT ANY PACKAGE | CREATE LINK | DROP LINK | CREATE ANY LINK | DROP ANY LINK | CREATE SYNONYM | DROP SYNONYM | CREATE ANY SYNONYM | DROP ANY SYNONYM | CREATE PUBLIC SYNONYM | DROP PUBLIC SYNONYM | CREATE REPLICATE | ALTER REPLICATE | DROP REPLICATE | AUDIT DATABASE | LABEL DATABASE | VERIFY DATABASE | CREATE TABLESPACE | DROP TABLESPACE | ALTER TABLESPACE | CREATE MATERIALIZED VIEW | DROP MATERIALIZED VIEW | CREATE ANY MATERIALIZED VIEW | DROP ANY MATERIALIZED VIEW | ALTER ANY MATERIALIZED VIEW | ALTER MATERIALIZED VIEW | SELECT MATERIALIZED VIEW | SELECT ANY MATERIALIZED VIEW | CREATE ANY DOMAIN | DROP ANY DOMAIN | CREATE DOMAIN | DROP DOMAIN | GRANT ANY DOMAIN | GRANT DOMAIN | USAGE ANY DOMAIN | USAGE DOMAIN | CREATE ANY CHARACTER SET | DROP ANY CHARACTER SET | CREATE CHARACTER SET | DROP CHARACTER SET | GRANT ANY CHARACTER SET | GRANT CHARACTER SET | USAGE ANY CHARACTER SET | USAGE CHARACTER SET | CREATE ANY COLLATION | DROP ANY COLLATION | CREATE COLLATION | DROP COLLATION | GRANT ANY COLLATION | GRANT COLLATION | USAGE ANY COLLATION | USAGE COLLATION | CREATE ANY CONTEXT | DROP ANY CONTEXT | GRANT ANY CONTEXT | SELECT ANY DICTIONARY | ADMIN REPLAY | ADMIN BUFFER | COMMENT ANY TABLE | DUMP ANY TABLE | DUMP TABLE | ADMIN JOB | CREATE ANY DIRECTORY | DROP ANY DIRECTORY | CREATE SESSION | CREATE PROFILE | ALTER PROFILE | DROP PROFILE | CREATE PARTITION GROUP | DROP PARTITION GROUP | CREATE ANY PARTITION GROUP | DROP ANY PARTITION GROUP | USAGE PARTITION GROUP | USAGE ANY PARTITION GROUP | CREATE OPERATOR | DROP OPERATOR | CREATE ANY OPERATOR | DROP ANY OPERATOR | FLASHBACK TABLE | FLASHBACK ANY TABLE | UNLIMITED TABLESPACE | SUBSCRIBE ; by_grantor : BY user_name ; grantees : user_role_name | user_role_name COMMA grantees ; create_schema_stmt : CREATE SCHEMA full_schema_name? (AUTHORIZATION user_name)? SEMI? (grant_and_ddl SEMI?)* ; oprt_arg : LEFTARG opr_dtype | RIGHTARG opr_dtype ; oprt_arg_lst : oprt_arg (COMMA oprt_arg)* ; create_operator_stmt : CREATE OPERATOR qualified_u_oprt '(' FUNCTION full_func_name COMMA oprt_arg_lst ')' ; drop_operator_stmt : DROP OPERATOR exist? qualified_u_oprt '(' opr_datatype_lst ')' ; grant_and_ddl : grant_stmt | create_func_stmt | create_index_stmt | create_proc_stmt | create_table_stmt | create_trigger_stmt | create_view_stmt | create_materialized_view_stmt | create_materialized_view_log_stmt | alter_table_stmt | create_sequence_stmt | create_contextindex_stmt | create_synonym_stmt | create_package_stmt | create_package_body_stmt | create_dblink_stmt | create_type_stmt | create_type_body_stmt | create_domain_stmt | create_character_set_stmt | create_collation_stmt | create_context_stmt | comment_stmt | create_partition_group_stmt | create_operator_stmt | drop_operator_stmt ; top_exp : LT_INTEGER | stm_param | member | '(' exp ')' | null_value ; u_oprt : OP_U_OPRT ; qualified_u_oprt : u_oprt | qualified_name ('.' u_oprt)? ; exp_u_oprt : u_oprt | OPERATOR '(' qualified_u_oprt ')' ; raw_exp : '-' raw_exp | LT_INTEGER | LT_BINTEGER | LT_DECIMAL | LT_REAL | LT_STRING | member_access LT_STRING | member LT_STRING | LT_BITSTRING | member_access | member | null_value | stm_param | INTERVAL ('+' | '-') LT_STRING interval_qualifier | INTERVAL LT_STRING interval_qualifier | global_var ; exp : op=('~'|'+'|'-') exp | exp_u_oprt exp | BINARY_KEYWORD exp | PRIOR exp | select_with_paran | '(' exp '-' exp ')' interval_qualifier? | exp op=('*' | '/' | '%' | MOD) exp | exp op=('+' | '-' | '|' |'^' | '&') exp | exp exp_u_oprt exp | '(' exp exp_u_oprt ')' | exp op=(OP_CONSTR | OP_SHIFT_LEFT | OP_SHIFT_RIGHT) exp | boolean_case | if_exp | null_value | stm_param | USER | USER '(' ')' | INTERVAL ('+'| '-')? LT_STRING interval_qualifier | DATEPART '(' datepart_op COMMA exp ')' | IFNULL '(' bool_exp COMMA bool_exp ')' | datead_fun '(' datepart_op COMMA exp COMMA exp ')' | REPEAT '(' exp COMMA exp ')' | REPLICATE '(' exp COMMA exp ')' | OVERLAY '(' exp PLACING exp FROM exp (FOR exp)? ')' | decode_case | pexp_pfx '%' (ROWCOUNT | ROWCOUNT2 | IS OPEN | FOUND | NOT FOUND) | global_var | NEXT VALUE FOR pexp_pfx | CONNECT_BY_ROOT (qualified_name | '(' exp ')') | ARRAYLEN '(' exp ')' | CHAR '(' exp ')' | REVERSE '(' exp ')' | ROWNUM | sizeof_expression | pexp | TRUE | FALSE | invocation_expression OVER '(' afun_partition_by? order_by_options? afun_windowing? ')' | exp ignore_nulls_clause OVER '(' afun_partition_by? order_by_options? afun_windowing? ')' | invocation_expression from_first_last_option '(' afun_partition_by? order_by_options? afun_windowing? ')' | pexp_pfx '(' afun_arg_lst ')' OVER '(' afun_partition_by? order_by_options? afun_windowing? ')' | pexp time_zone_exp_new | CURSOR FAST? select_with_paran | exp MULTISET (UNION | INTERSECT | EXCEPT) all_distinct_option? exp | SET '(' exp ')' | contains_exp ; from_first_last_option : FROM FIRST OVER | FROM LAST OVER | FROM FIRST IGNORE NULLS OVER | FROM LAST IGNORE NULLS OVER | FROM FIRST RESPECT NULLS OVER | FROM LAST RESPECT NULLS OVER ; afun_arg_lst : afun_arg_lst_low ; afun_arg_lst_low : exp ignore_nulls_clause (COMMA exp)* ; in_value_exp : op=('~'| '+'| '-') in_value_exp | PRIOR in_value_exp | in_value_exp op=('*'|'/'| '%'| MOD ) in_value_exp | in_value_exp op=('+'|'-'| '|'| '^' ) in_value_exp | in_value_exp op=(OP_CONSTR | OP_SHIFT_LEFT | OP_SHIFT_RIGHT) in_value_exp | boolean_case | if_exp | null_value | stm_param | USER | USER '(' ')' | INTERVAL '+' LT_STRING interval_qualifier | INTERVAL '-' LT_STRING interval_qualifier | INTERVAL LT_STRING interval_qualifier | DATEPART '(' datepart_op COMMA in_value_exp ')' | datead_fun '(' datepart_op COMMA in_value_exp COMMA in_value_exp ')' | REPEAT '(' in_value_exp COMMA in_value_exp ')' | REPLICATE '(' in_value_exp COMMA in_value_exp ')' | OVERLAY '(' in_value_exp PLACING in_value_exp FROM in_value_exp ')' | OVERLAY '(' in_value_exp PLACING in_value_exp FROM in_value_exp FOR in_value_exp ')' | decode_case | pexp_pfx '%' ROWCOUNT | pexp_pfx '%' ROWCOUNT2 | global_var | NEXT VALUE FOR pexp_pfx | ARRAYLEN '(' in_value_exp ')' | CHAR '(' in_value_exp ')' | REVERSE '(' in_value_exp ')' | ROWNUM | sizeof_expression | pexp_a | pexp_b | pexp_c | TRUE | FALSE | pexp_a time_zone_exp_new ; afun_partition_by : PARTITION BY exp_list ; afun_windowing : afun_windowing_type afun_range_clause | afun_windowing_type BETWEEN afun_range_clause AND afun_range_clause ; afun_windowing_type : ROWS | RANGE ; afun_range_clause : exp PRECEDING | exp FOLLOWING | CURRENT ROW ; pexp : pexp_a | pexp_b | pexp_c | pexp_d | pexp_e ; pexp_pfx : pexp_pfx DOT (id dblink_clause? | key | '*') (('[' exp_list ']')+)? | pexp_pfx '(' opt_argument_list ')' ( keep_clause | within_clause )? (('[' exp_list ']')+)? | pexp_pfx '.' ( EXECUTE | EXTRACT )'(' opt_argument_list ')' (('[' exp_list ']')+)? | XMLPARSE '(' raw_id exp raw_id? ')' (('[' exp_list ']')+)? | XMLELEMENT '(' xmlele_name xmlele_sub_lst? ')' (('[' exp_list ']')+)? | XMLAGG '(' exp order_by_options? ')' (('[' exp_list ']')+)? | pexp_c_insert (('[' exp_list ']')+)? | new_arr_expression | pexp_cast | stm_param_normal ; pexp_cast : '(' exp AS datatype ')' | CAST '(' exp AS datatype ')' | CAST '(' COLLECT '(' all_distinct_option? exp order_by_options? ')' AS datatype ')' ; pexp_b : element_access | new_arr_expression ; pexp_a : typeof_expression | LT_INTEGER | LT_BINTEGER | LT_DECIMAL | LT_REAL | LT_STRING | LT_BITSTRING ; pexp_c : member ('%' BULK (EXCEPTION | ROWCOUNT))? | member_access | new_obj_expression | invocation_expression | ':' trig_new_name '.' column_name | NEW '.' column_name ; pexp_c_insert : member | new_obj_expression | ':' trig_new_name '.' column_name | NEW '.' column_name | member '%' BULK EXCEPTION | member '%' BULK ROWCOUNT ; pexp_d : member LT_STRING | CAST '(' exp AS datatype ')' | CAST '(' COLLECT '(' all_distinct_option? exp order_by_options? ')' AS datatype ')' | CONVERT '(' datatype COMMA exp ')' | CONVERT '(' datatype COMMA exp COMMA exp ')' | TRIM '(' exp ')' | TRIM '(' orient_option FROM exp ')' | TRIM '(' exp FROM exp ')' | TRIM '(' orient_option exp FROM exp ')' | TRUNCATE '(' value_list ')' | INSERT '(' value_list ')' | EXTRACT '(' datepart FROM exp ')' | EXTRACT '(' exp COMMA exp ')' | GROUPING '(' exp ')' ; pexp_e : '(' exp ')' ; pexp_pfx2 : pexp_pfx2 DOT (id dblink_clause? | key) (('[' exp_list ']')+)? | pexp_pfx2 '(' opt_argument_list ')' ( keep_clause | within_clause )? (('[' exp_list ']')+)? | pexp_pfx2 '.' ( EXECUTE | EXTRACT )'(' opt_argument_list ')' (('[' exp_list ']')+)? | pexp_c2_insert (('[' exp_list ']')+)? | XMLPARSE '(' raw_id exp raw_id? ')' (('[' exp_list ']')+)? | XMLELEMENT '(' xmlele_name xmlele_sub_lst? ')' (('[' exp_list ']')+)? | XMLAGG '(' exp order_by_options? ')' (('[' exp_list ']')+)? | new_arr_expression | pexp_cast | stm_param_normal ; member2 : variable_name dblink_clause? ; pexp_c2_insert : member2 | new_obj_expression | ':' trig_new_name '.' column_name | NEW '.' column_name | member2 '%' BULK EXCEPTION | member2 '%' BULK ROWCOUNT ; member_access2 : pexp_pfx2 (DOT id dblink_clause?)+ | pexp_pfx2 (DOT key)+ ; invocation_expression2 : pexp_pfx2 invocation_expression_low ; member : id dblink_clause? ; key : FIRST | NEXT | PRIOR | DELETE | GET | SET | EXISTS | TRIM | ROWNUM | ROWS ; member_access : pexp_pfx ((DOT id dblink_clause?)+ | (DOT key)+ | (DOT '*')+) ; invocation_expression : pexp_pfx invocation_expression_low | xmlfun_inv_expression | xmlagg_inv_expression ; invocation_expression_low : ('.' EXECUTE LR_BRACKET opt_argument_list? RR_BRACKET)+ | (LR_BRACKET opt_argument_list? RR_BRACKET (keep_clause | within_clause)? )+ ; xmlagg_inv_expression : XMLAGG '(' exp order_by_options? ')' ; xmlfun_inv_expression : XMLPARSE '(' raw_id exp raw_id ')' | XMLPARSE '(' raw_id exp ')' | XMLELEMENT '(' xmlele_name xmlele_sub_lst? ')' | pexp_pfx (DOT EXTRACT '(' opt_argument_list? ')')+ ; xmlele_name : id | EVALNAME exp ; xmlele_sub_lst : COMMA xmlval_lst | COMMA XMLATTRIBUTES '(' xmlattr_lst ')' | COMMA XMLATTRIBUTES '(' xmlattr_lst ')' COMMA xmlval_lst ; xmlattr_lst : xmlattr (COMMA xmlattr)* ; xmlattr : exp | exp id | exp AS id | exp AS EVALNAME exp ; xmlval_lst : exp (COMMA exp)* ; keep_clause : KEEP '(' DENSE_RANK FIRST order_by_options? ')' | KEEP '(' DENSE_RANK LAST order_by_options? ')' ; within_clause : WITHIN GROUP '(' order_by_options? ')' ; typeof_expression : TYPEOF '(' sizeof_type ')' ; new_obj_expression : NEW qualified_name '(' opt_argument_list? ')' ; new_arr_expression : array_creation_expression ; array_creation_expression : NEW new_array_type '[' exp_list ']' opt_rank_specifier? opt_array_initializer? | NEW STRUCT new_array_type '[' exp_list ']' opt_rank_specifier? opt_array_initializer? ; plsql_datatype_ex : INTERVAL interval_qualifier | qualified_name '%' TYPE | qualified_name '%' ROWTYPE | REF qualified_name | CURSOR ; new_array_type : plsql_datatype_ex | dtype | REF CURSOR ; opt_array_initializer : array_initializer ; array_initializer : '{' '}' | '{' variable_initializer_list opt_comma? '}' ; variable_initializer_list : variable_initializer (COMMA variable_initializer)* ; variable_initializer : exp ; opt_comma : COMMA ; sizeof_expression : SIZEOF '(' type_name ')' ; element_access : pexp_c ('[' exp_list ']')+ ; decode_case : DECODE '(' exp_list ')' ; else_exp : ELSE exp ; boolean_case : CASE bool_exp? bool_when_list else_exp? END case_option? ; if_exp : IF '(' bool_exp COMMA bool_exp COMMA bool_exp ')' ; bool_when_list : (WHEN bool_exp THEN exp)+ ; ops : '=' | '==' | '>' | '<' | '<' '>' | '>' '=' | '<' '=' | OPR_NE | OPR_GE | OPR_LE | OP_MULT_ASSIGN ; value_list : exp_list ; in_value_list : in_value_exp ; value_list_set : '(' value_list ')' (COMMA '(' value_list ')')* ; comma_list : COMMA+ ; ins_value_list : ins_exp_list | comma_list ins_exp_list ; null_value : NULL ; id_and_rsvd_word_others : new_none_reserved_word | alias_resvd_word | variable_resvd_word | schname_resvd_word ; id_and_rsvd_word : raw_id | reserved_word | id_and_rsvd_word_others ; stm_param : stm_param_normal | stm_param_name ; stm_param_normal : '?' | ':' LT_INTEGER | ':' '<' LT_INTEGER param_name_options? '>' | '^' '?' '^' ; stm_param_name : ':' id_and_rsvd_word ; param_name_options : id ; contains_query_exp : exp | contains_query_exp (AND | OR | AND NOT) contains_query_exp ; contains_query_exp_lst : contains_query_exp (COMMA contains_query_exp)* ; contains_exp : CONTAINS '(' exp COMMA contains_query_exp ')' | CONTAINS '(' exp COMMA contains_query_exp COMMA contains_query_exp ')' | CONTAINS '(' exp COMMA contains_query_exp COMMA SYSTEM LABEL COMMA LT_INTEGER COMMA LT_INTEGER ')' | CONTAINS '(' exp COMMA contains_query_exp COMMA contains_query_exp COMMA contains_query_exp_lst ')' ; strict_option : '(' LAX ')' | LAX | '(' STRICT ')' | STRICT ; with_unique_option : WITHOUT UNIQUE KEYS | WITH UNIQUE KEYS ; type_option : TYPE ; type_element : qualified_name ; type_element_list : type_element (COMMA type_element)* ; bool_exp : exp | bool_exp_element ; bool_exp_element : exp IS not_tag? JSON strict_option? with_unique_option? | exp IS not_tag? OF type_option? '(' type_element_list ')' | NOT (bool_exp_element | exp) //| (bool_exp_element | exp) (AND | OR) (bool_exp_element | exp) | bool_exp_element (AND | OR) (bool_exp_element | exp) | exp (AND | OR) (bool_exp_element | exp) | exp not_tag? IN (select_with_paran | in_value_list | ('(' value_list ')')) | '(' exp_list_2 ')' not_tag? IN (select_with_paran | ('(' value_list_set ')')) | '(' exp_list_2 ')' ops query_any_options? (select_with_paran | ('(' value_list_set ')')) | exp ops query_any_options (select_with_paran | ('(' value_list_set ')')) | EXISTS select_with_paran | exp ops exp | exp IS not_tag? NULL | exp NOT? BETWEEN exp AND exp | exp NOT? LIKE exp (ESCAPE exp)? | pexp_pfx '.' ROW NOT? LIKE exp (ESCAPE exp)? | BINARY_KEYWORD pexp_pfx '.' ROW NOT? LIKE exp (ESCAPE exp)? | '(' exp_list_2 ')' OVERLAPS '(' exp_list_2 ')' | LNNVL '(' (bool_exp_element | exp) ')' | exp not_tag? MEMBER OF exp | '(' bool_exp_element ')' ; query_any_options : ALL | SOME | ANY | EVERY ; global_var : LT_GLOBAL_VAR ; reserved_word : IFNULL | ABSOLUTE | ADD | ALL | ALTER | AND | ANY | ARRAYLEN | AS | ASC | ASSIGN | AUDIT | BEGIN | BETWEEN | BIGDATEDIFF | BOOL | BOTH | BSTRING | BY | BYTE | CALL | CASE | CAST | CHAR | CHECK | CLUSTER | COLUMN | COMMIT | COMMITWORK | COMMENT | CONNECT | CONNECT_BY_ROOT | CONSTRAINT | CONTAINS | CONTEXT | CONVERT | CORRESPONDING | CREATE | CRYPTO | CURRENT | CURSOR | DATEADD | DATEDIFF | DATEPART | DECIMAL | DECLARE | DECODE | DEFAULT | DELETE | DESC | DISTINCT | DISTRIBUTED | DOUBLE | DROP | ELSE | ELSEIF | END | EXECUTE | EXISTS | EXIT | EXPLAIN | EXTRACT | FETCH | FINAL | FIRST | FLOAT | FOR | FOREIGN | FROM | FULLY | FUNCTION | GOTO | GRANT | GROUP | HAVING | IDENTITY | IF | IMMEDIATE | IN | INDEX | INSERT | INT | INTERVAL | INTO | IS | LEAD | LIKE | LOGIN | LOOP | MEMBER | NEW | NEXT | NOT | NULL | OBJECT | OF | ON | OR | ORDER | OUT | PARTITION | PENDANT | PERCENT | PRIMARY | PRINT | PRIOR | PRIVILEGES | PROCEDURE | PUBLIC | RAISE | RECORD | REF | REFERENCES | REFERENCE | REFERENCING | RELATIVE | REPEAT | RETURN | REVERSE | REVOKE | ROLLBACK | ROW | ROWNUM | ROWS | SAVEPOINT | SCHEMA | SELECT | SET | SOME | SUBPARTITION | SWITCH | SYNONYM | TABLE | TIMESTAMPADD | TIMESTAMPDIFF | TO | TOP | TRAIL | TRIGGER | TRIM | TRUNCATE | UNION | UNIQUE | UNTIL | UPDATE | USER | USING | VALUES | VARRAY | VIEW | WHEN | WHENEVER | WHILE | WITH | DISKSPACE | RETURNING | SBYTE | SHORT | USHORT | UINT | ULONG | VOID | CONST | DO | BREAK | CONTINUE | THROW | FINALLY | TRY | CATCH | PROTECTED | PRIVATE | ABSTRACT | SEALED | STATIC | VIRTUAL | OVERRIDE | EXTERN | CLASS | STRUCT | GET | SIZEOF | TYPEOF | ADMIN | REPLICATE | VERIFY | EQU | EXCHANGE | CLUSTERBTR | LIST | ARRAY | ROLLUP | CUBE | GROUPING | OVER | SECTION | SETS | DOMAIN | COLLATION | OVERLAY | EVERY | KEEP | WITHIN | LNNVL | NOCOPY | INLINE | TYPEDEF | XMLTABLE | XMLPARSE | XMLAGG | AUTO_INCREMENT | BINARY_KEYWORD | XMLELEMENT | XMLATTRIBUTES | EVALNAME | LEXER | FLASHBACK | NOCYCLE | NOSORT | OPTIMIZE | VERSIONS | LARGE | WITHOUT | PIPE | XML | JSON_TABLE | SUBSCRIBE | LESS | THAN ; new_none_reserved_word : ACROSS | ABORT | ROWID | ACTION | AFTER | ALLOW_DATETIME | ALLOW_IP | ANALYZE | ARCHIVEDIR | ARCHIVELOG | ARCHIVESTYLE | AT_KEYWORD | ATTACH | AUTO | AVG | BACKUP | BACKUPDIR | BACKUPINFO | BAKFILE | BEFORE | BIGINT | DEVICE | PARMS | TRACE | FILE | BIT | BITMAP | BLOB | BLOCK | BOOLEAN | CACHE | CASCADE | CASCADED | CATALOG | CHAIN | CALCULATE | CHARACTER | CIPHER | CLOB | COMMITTED | COMPILE | DUMP | JOB | COMPRESS | COMPRESSED | CONNECT_BY_IS_CYCLE | CONNECT_BY_IS_LEAF | CONNECT_IDLE_TIME | COUNT | COUNTER | CTLFILE | CYCLE | SEARCH | DEPTH | BREADTH | DANGLING | DATAFILE | DATE | DATETIME | DBFILE | DEBUG | DEC | DEFERRABLE | DEFERRED | DELETING | DELTA | DEREF | DETACH | DISCONNECT | DOWN | EACH | ENCRYPT | ENCRYPTION | ESCAPE | EVENTINFO | EXCLUSIVE | EXTERNAL | EXTERNALLY | FAILED_LOGIN_ATTEMPS | FAILED_LOGIN_ATTEMPTS | FILEGROUP | FILLFACTOR | FORCE | FREQUENCE | GLOBAL | GLOBALLY | HASH | HEXTORAW | IDENTIFIED | IDENTITY_INSERT | IMAGE | INCREASE | INCREMENT | INITIAL | INITIALLY | INNERID | INSERTING | INSTEAD | INTEGER | INTENT | ISOLATION | KEY | LABEL | LOCAL | LOCALLY | LOGFILE | LOGOUT | LONG | LONGVARBINARY | LONGVARCHAR | MANUAL | MATCH | MATCHED | MAX | MAXSIZE | MAXVALUE | MERGE | MIN | MINEXTENTS | MINVALUE | MODE | MODIFY | MONEY | MOUNT | NO | NOARCHIVELOG | NOAUDIT | NOCACHE | NOMAXVALUE | NOMINVALUE | NOORDER | NOT_ALLOW_DATETIME | NOT_ALLOW_IP | NOWAIT | NUMBER | NUMERIC | OFF | OFFLINE | CORRUPT | ONLY | OPTION | OUTER | OVERLAPS | CONSTANT | PAGE | PARTIAL | PARTITIONS | PASSWORD_GRACE_TIME | PASSWORD_LIFE_TIME | PARALLEL | CPU_PER_CALL | CPU_PER_SESSION | MEM_SPACE | READ_PER_CALL | READ_PER_SESSION | PASSWORD_LOCK_TIME | PASSWORD_POLICY | PASSWORD_REUSE_MAX | PASSWORD_REUSE_TIME | PRECISION | PRESERVE | RAWTOHEX | READ | REAL | REBUILD | RELATED | RENAME | REPEATABLE | REPLACE | RESTORE | RESTRICT | PLACING | ROLE | ROLLFILE | ROOT | ROWCOUNT | RULE | SALT | SCOPE | SERERR | SERIALIZABLE | SESSION_PER_USER | SHARE | SHUTDOWN | SIBLINGS | SMALLINT | SNAPSHOT | SOUND | SPATIAL | SPLIT | SQL | STARTUP | STATEMENT | STORAGE | STRING | STYLE | SUBSTRING | SUCCESSFUL | SUM | SUSPEND | SYNC | SYS_CONNECT_BY_PATH | TEMPORARY | TEXT | THEN | TIES | TIME | TIMES | TIMESTAMP | TINYINT | TRANSACTION | TRIGGERS | TRUNCSIZE | UNCOMMITTED | UNDER | UNLIMITED | UP | UPDATING | VALUE | VARBINARY_KEYWORD | VARCHAR | VARCHAR2 | STDDEV | VARIANCE | VARYING | VSIZE | WORK | WRITE | SEQUENCE | SERVER | TIMER | WEEK | ONCE | ZONE | VERTICAL | QUOTA | LOG | NONE | LOB | ERROR | PASSWORD | EXPIRE | BACKUPSET | MAXPIECESIZE | BACKED | SINCE | DDL_CLONE | CUMULATIVE | NORMAL | STANDBY | TRANSACTIONAL | STORE | BRANCH | NOBRANCH | READONLY | UNBOUNDED | PRECEDING | FOLLOWING | AUTOEXTEND | WRAPPED | BTREE | CONNECT_TIME | TRXID | THROUGH | SCN | VERSIONS_STARTTIME | VERSIONS_ENDTIME | VERSIONS_STARTTRXID | VERSIONS_ENDTRXID | VERSIONS_OPERATION | RANDOMLY | COPY | PATH | HUGE | FILESIZE | SESSION | QUERY_REWRITE_INTEGRITY | REFRESH | MATERIALIZED | FAST | COMPLETE | DEMAND | MIRROR | NEVER | BUILD | PURGE | SYNCHRONOUS | ASYNCHRONOUS | PREBUILT | REDUCED | BASE | SELF | INDEXES | EXCEPTION_INIT | AUTONOMOUS_TRANSACTION | INDICES | EXCEPTIONS | SAVE | RESULT | COLLATE | PAD | SPACE_KEYWORD | EVENTS | NCHAR | NCHARACTER | NATIONAL | USE_HASH | USE_MERGE | USE_NL | USE_NL_WITH_INDEX | TIME_ZONE | DIAGNOSTICS | SIMPLE | CHARACTERISTICS | INSENSITIVE | ASENSITIVE | SENSITIVE | SCROLL | HOLD | SUBPARTITIONS | TEMPLATE | NULLS | DENSE_RANK | SYSTEM | MEMORY | SPFILE | AUTHID | CURRENT_USER | CURRENT_SCHEMA | DEFINER | ACCESSED | INITIALIZED | LOGGING | NOLOGGING | DETERMINISTIC | TABLESPACE | COLUMNS | WAIT | SKIP_KEYWORD | LOCKED | PARALLEL_ENABLE | AGGREGATE | SIZE | LEVEL | REPLAY | DICTIONARY | PRIVILEGE | BUFFER | MOVE | MOVEMENT | ACCOUNT | UNLOCK | INCLUDING | EXCLUDING | JAVA | INVISIBLE | VISIBLE | UNUSABLE | DATA | CONSTRAINTS | OLD | MAPPED | LOGON | LOGOFF | RANGE | ARCHIVE | FIELDS | DELIMITED | RECORDS | ERRORS | LSN | INPUT | INCLUDE | EXCLUDE | DDL | DIRECTORY | LOCATION | RESULT_CACHE | PIPELINED | MONITORING | NOMONITORING | EXTENDS | NODE | STRICT | LAX | FORMAT | JSON | KEYS | ASCII | PRETTY | WRAPPER | EMPTY | CONDITIONAL | UNCONDITIONAL | TASK | THREAD | BADFILE | ADVANCED | ROWDEPENDENCIES | NOROWDEPENDENCIES | SPAN | MON | TUE | WED | THU | FRI | SAT | SUN | JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | YEARLY | MONTHLY | WEEKLY | DAILY | HOURLY | MINUTELY | SECONDLY | BYMONTH | BYWEEKNO | BYYEARDAY | BYMONTHDAY | BYDAY | BYHOUR | BYMINUTE | BYSECOND | USAGE | EXCEPTION | DATABASE | LAST | PACKAGE | PASSING | GREAT | MICRO | LOCAL_OBJECT | LINK | RESTRICT_REFERENCES | REJECT | PROFILE | HASHPARTMAP | SPEED | STOP | INSTANCE | IGNORE_ROW_ON_DUPKEY_INDEX | EDITIONABLE | NONEDITIONABLE | BATCH | ORDINALITY | STRIPING | HIGH | DISKGROUP | SHADOW | CASE_SENSITIVE | LEFTARG | RIGHTARG | OPERATOR | RESIZE | SCHEMABINDING | CHANGE | TRACKING | SUBSTITUTABLE | LEVELS | IDENTIFIER_KEYWORD | GENERATED | OIDINDEX | NOPARALLEL | COLLECT | DML | APPLY | CHECKPOINT | NOVALIDATE | QUERY ; interval_nresvd_word : YEAR | MONTH | DAY | HOUR | MINUTE | SECOND ; variable_resvd_word : TYPE | SUBTYPE | MAP | INSTANTIABLE | CONSTRUCTOR | OVERRIDING | PRAGMA | CLOSE | OPEN | LOCK | STAT | FORALL | DISABLE | ENABLE ; alias_resvd_word : interval_nresvd_word | LEFT | RIGHT | EXCEPT | MINUS | INTERSECT | CROSS | FULL | INNER | JOIN | NATURAL | WHERE | BULK | OFFSET | MOD | SEED | SAMPLE | PIVOT | ONLINE | UNPIVOT | LIMIT | MULTISET ; schname_resvd_word : AUTHORIZATION ; raw_id : LT_IDENTIFIER ; id : raw_id | new_none_reserved_word | schname_resvd_word | alias_resvd_word | variable_resvd_word ; qualified_name : id ('.' id)* ; qualified_name2 : id ('.' id)* ; variable_name : raw_id | new_none_reserved_word | schname_resvd_word | alias_resvd_word ; end_loop_label_null : END LOOP label_name_options? ; label_name_options : label_name ; label_name : id ; database_name : id ; backup_name : id ; full_proc_name : qualified_name ; full_proc_name2 : qualified_name2 ; full_fun_name : qualified_name ; full_table_name : qualified_name ; full_grp_name : qualified_name ; full_table_name2 : qualified_name2 ; full_partition_name : raw_id ; full_schema_name : schema_name | database_name '.' schema_name ; table_name : id ; column_name : id ; constraint_name : id ; full_trigger_name : qualified_name ; full_trigger_name2 : qualified_name2 ; full_view_name : qualified_name ; full_view_name2 : qualified_name2 ; cursor_name : raw_id ; trigger_name : id ; login_name : id ; profile_name : DEFAULT | id ; user_name : id ; role_name : id | PUBLIC ; user_role_name : role_name ; role_name_list : role_name | role_name COMMA role_name_list ; full_func_name : qualified_name2 ; param_name : id ; index_name : id | id '.' id ; index_name2 : id | id '.' id | id '.' id '.' id ; trig_old_name : variable_name | NEW ; trig_new_name : variable_name | variable_resvd_word | NEW ; full_tv_name : qualified_name dblink_clause2? ((PARTITION | SUBPARTITION) ('(' full_partition_name ')' | FOR '(' value_list ')'))? | qualified_name INDEX (id | LT_INTEGER) ; full_object_name : qualified_name ; orient_option : LEAD | TRAIL | BOTH ; datepart : raw_id | YEAR | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND ; datepart_op : datepart ; datead_fun : DATEADD | DATEDIFF | BIGDATEDIFF | TIMESTAMPADD | TIMESTAMPDIFF ; returning : RETURNING dtype double_length_option? ; pretty : ASCII | PRETTY | PRETTY ASCII ; wrapper_flag : WRAPPER | ARRAY WRAPPER ; array_wrapper : WITHOUT wrapper_flag | WITH wrapper_flag | WITH UNCONDITIONAL wrapper_flag | WITH CONDITIONAL wrapper_flag ; json_tail_on_empty : empty_handle | DEFAULT exp ON EMPTY ; empty_handle : NULL ON EMPTY | ERROR ON EMPTY ; json_tail_on_error_null : error_handle? | DEFAULT exp ON ERROR ; error_handle : NULL ON ERROR | ERROR ON ERROR | EMPTY ON ERROR | TRUE ON ERROR | FALSE ON ERROR ; savepoint_name : id ; alias : raw_id | new_none_reserved_word | schname_resvd_word | '*' | variable_resvd_word | interval_nresvd_word ; alias_2 : id ; full_column_name : qualified_name ; schema_name : raw_id | new_none_reserved_word | variable_resvd_word ; not_tag : NOT ; debug_tag : DEBUG ; column_tag : COLUMN ; pendant_tag : PENDANT ; unique_tag : UNIQUE | BITMAP | SPATIAL | ARRAY ; partition_tag : CLUSTER | NOT PARTIAL ; row_tag : ROW ; as_tag : AS ; from_tag : FROM ; into_tag : INTO ; work_tag : WORK ; with_grant_option : WITH GRANT OPTION ; with_admin_option : WITH ADMIN OPTION ; time_zone_or_local : TIME ZONE | LOCAL TIME ZONE ; sub_plsql_datatype : datatype | qualified_name dblink_clause? '%' TYPE | qualified_name dblink_clause? '%' ROWTYPE ; datatype_list : datatype (COMMA datatype)* ; datatype : dtype double_length_option? (WITH time_zone_or_local | WITHOUT TIME ZONE)? | INTERVAL interval_qualifier | dtype LARGE OBJECT double_length_option? ; datatype2 : dtype1 double_length_option? | INTERVAL interval_qualifier ; opr_dtype : dtype | NULL ; opr_datatype_lst : opr_dtype COMMA opr_dtype ; interval_qualifier : interval_nresvd_word double_length_option? (TO interval_nresvd_word double_length_option?)? ; dtype : dtype1 | dtype2 ; dtype1 : qualified_name | BINARY_KEYWORD | sql_builtin_types ; dtype2 : CHAR VARYING | CHARACTER VARYING | NCHAR VARYING | NATIONAL CHAR VARYING | NATIONAL CHAR | NCHARACTER VARYING | NATIONAL CHARACTER VARYING | NATIONAL CHARACTER | DOUBLE PRECISION | REF '(' qualified_name ')' ; double_length_option : '(' LT_INTEGER size_unit_caluse? ')' | '(' LT_INTEGER COMMA LT_INTEGER ')' | '(' '*' COMMA LT_INTEGER ')' ; size_unit_caluse : CHAR | BYTE ; lt_integer_negative : LT_INTEGER | '-' LT_INTEGER ; create_contextindex_stmt : CREATE replace_option? CONTEXT INDEX not_exist? index_name ON full_table_name '(' index_column_list ')' storage_tag? lexer_clause? sync? ; lexer_name : id ; lexer_clause : LEXER lexer_name ; lexer_clause2 : LEXER lexer_name ; sync : SYNC | SYNC TRANSACTION ; drop_contextindex_stmt : DROP CONTEXT INDEX exist? index_name ON full_table_name ; alter_contextindex_stmt : alter_tag CONTEXT INDEX index_name ON full_table_name cti_sync_option online_options? lexer_clause2? ; cti_sync_option : REBUILD | INCREMENT | OPTIMIZE ; type_name : qualified_name | BINARY_KEYWORD ; sizeof_type : type_name | builtin_types ; type : sizeof_type | array_type ; array_type : sizeof_type rank_specifiers ; builtin_types : OBJECT | BSTRING | BOOL | DECIMAL | FLOAT | DOUBLE | integral_type ; integral_type : SBYTE | BYTE | SHORT | USHORT | INT | UINT | ULONG | CHAR | VOID ; sql_builtin_types : BOOL | DECIMAL | FLOAT | DOUBLE | INT | CHAR | BYTE ; cursor_declaration : CURSOR cursor_name cursor_attrs_options? cursor_option? ; cursor_declaration_2 : cursor_declaration | variable_name_list CURSOR cursor_attrs_options? cursor_option_2 ; cursor_attrs_options : cursor_attrs ; cursor_attrs : cursor_attr | cursor_attrs cursor_attr ; cursor_attr : INSENSITIVE | SENSITIVE | ASENSITIVE | NO SCROLL | SCROLL | WITHOUT HOLD | WITH HOLD | WITHOUT RETURN | WITH RETURN | FAST | NO FAST ; opt_rank_specifier : rank_specifiers ; rank_specifiers : rank_specifier ; rank_specifier : '[' opt_dim_separators? ']' ; opt_dim_separators : dim_separators ; opt_rank_specifier2 : opt_rank_specifier? | '[' lt_int_lst ']' ; dim_separators : COMMA+ ; opt_argument_list : mixed_param_list json_fun_tail | bool_exp FROM exp (FOR exp)? | all_distinct_option_2 exp | all_distinct_option_2 exp_list_2 | '*' | '+' | without_into_select ; json_fun_tail : returning? pretty? array_wrapper? json_tail_on_error_null | returning? pretty? array_wrapper? json_tail_on_empty json_tail_on_error_null ; ignore_nulls_clause : IGNORE NULLS | RESPECT NULLS ; mixed_param_list : mixed_param (COMMA mixed_param)* ; mixed_param : argument as_alias? | param ; argument : bool_exp (FORMAT JSON)? ; cursor_option : cursor_option_2 ; without_into_select2 : without_into_select | select_with_paran ; cursor_option_2 : IS without_into_select2 | IS joined_table | IS TABLE full_tv_name | FOR without_into_select2 | FOR joined_table | FOR TABLE full_tv_name | '(' param_def_list ')' IS without_into_select2 | '(' param_def_list ')' RETURN plsql_datatype IS without_into_select2 | RETURN plsql_datatype IS without_into_select2 ; region_size : GREAT | MICRO ; copy_num : COPY LT_INTEGER ; redundancy_clause : EXTERNAL | NORMAL | HIGH ; striping_clause : STRIPING LT_INTEGER ; with_huge_clause : WITH HUGE PATH pathname region_size? ; ================================================ FILE: superior-dameng-parser/src/main/kotlin/io/github/melin/superior/parser/dameng/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.dameng import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.dameng.antlr4.DmSqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(DmSqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: DmSqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(DmSqlParser._ATN)) } } ================================================ FILE: superior-dameng-parser/src/main/kotlin/io/github/melin/superior/parser/dameng/DmSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.dameng import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.SQLParserException import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.TableType import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.alter.AlterTable import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.CreateMaterializedView import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.parser.dameng.antlr4.DmSqlParser import io.github.melin.superior.parser.dameng.antlr4.DmSqlParserBaseVisitor import org.antlr.v4.runtime.ParserRuleContext import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/2/8. */ class DmSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : DmSqlParserBaseVisitor() { private var rootTableId: TableId = TableId("") private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private val primaryKeys = ArrayList() private var queryStmt: QueryStmt? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() // 多语句解析结果 private var statements: ArrayList = arrayListOf() // 存储过程和函数中包含的子语句 private var childStatements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun visitDmprogram(ctx: DmSqlParser.DmprogramContext): Statement? { ctx.sql_clauses().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSql_clauses(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) currentOptType = StatementType.UNKOWN } } return null } override fun visitSelect_stmt(ctx: DmSqlParser.Select_stmtContext?): Statement? { currentOptType = StatementType.SELECT super.visitSelect_stmt(ctx) return queryStmt } override fun visitQuery_exp(ctx: DmSqlParser.Query_expContext?): Statement? { super.visitQuery_exp(ctx) queryStmt = QueryStmt(inputTables, limit, offset) val sql = source(ctx) queryStmt?.setSql(sql) return queryStmt } override fun visitMerge_into_stmt(ctx: DmSqlParser.Merge_into_stmtContext?): Statement { currentOptType = StatementType.MERGE super.visitMerge_into_stmt(ctx) return MergeTable(rootTableId, inputTables) } override fun visitInsert_stmt(ctx: DmSqlParser.Insert_stmtContext?): Statement { currentOptType = StatementType.INSERT super.visitInsert_stmt(ctx) var curQueryStmt: QueryStmt = QueryStmt() if (queryStmt != null) { curQueryStmt = queryStmt as QueryStmt } val retObj = InsertTable(InsertMode.INTO, curQueryStmt, rootTableId) retObj.outputTables.clear() retObj.outputTables.addAll(outputTables) return retObj } override fun visitUpdate_stmt(ctx: DmSqlParser.Update_stmtContext?): Statement { currentOptType = StatementType.UPDATE super.visitUpdate_stmt(ctx) return UpdateTable(rootTableId, inputTables) } override fun visitDelete_stmt(ctx: DmSqlParser.Delete_stmtContext?): Statement { currentOptType = StatementType.DELETE super.visitDelete_stmt(ctx) return DeleteTable(rootTableId, inputTables) } override fun visitCreate_table_stmt(ctx: DmSqlParser.Create_table_stmtContext?): Statement { currentOptType = StatementType.CREATE_TABLE super.visitCreate_table_stmt(ctx) return CreateTable(rootTableId, TableType.DAMENG) } override fun visitCreate_view_stmt(ctx: DmSqlParser.Create_view_stmtContext?): Statement { currentOptType = StatementType.CREATE_VIEW super.visitCreate_view_stmt(ctx) return CreateView(rootTableId, QueryStmt(inputTables, limit, offset)) } override fun visitCreate_materialized_view_stmt(ctx: DmSqlParser.Create_materialized_view_stmtContext?): Statement { currentOptType = StatementType.CREATE_MATERIALIZED_VIEW super.visitCreate_materialized_view_stmt(ctx) return CreateMaterializedView(rootTableId, QueryStmt(inputTables, limit, offset)) } override fun visitFull_view_name2(ctx: DmSqlParser.Full_view_name2Context?): Statement? { if (currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.CREATE_MATERIALIZED_VIEW) { if (ctx?.qualified_name2() != null) { rootTableId = parseTableViewName(ctx.qualified_name2()) } } return super.visitFull_view_name2(ctx) } override fun visitComment_stmt(ctx: DmSqlParser.Comment_stmtContext): Statement { super.visitComment_stmt(ctx) var objValue: String? = null val isNull = false var objType: String = "" val text: String = CommonUtils.cleanQuote(ctx.LT_STRING().text) val fullTableName = ctx.full_table_name() val fullColumnName = ctx.full_column_name() val fullViewName = ctx.full_view_name() if (fullTableName != null) { objType = "TABLE" objValue = fullTableName.qualified_name().text } else if(fullColumnName != null) { objType = "COLUMN" objValue = fullColumnName.qualified_name().text } else if(fullViewName != null) { objType = "VIEW" objValue = fullViewName.qualified_name().text } currentOptType = StatementType.COMMENT return CommentStatement(text, isNull, objType, objValue) } override fun visitDrop_stmt(ctx: DmSqlParser.Drop_stmtContext?): Statement? { super.visitDrop_stmt(ctx) val dropDbObject = ctx?.drop_db_object() if (dropDbObject?.db_object()?.text.equals("table")) { currentOptType = StatementType.DROP_TABLE val dropStmtBody = ctx?.drop_stmt_body_1() if (dropStmtBody?.full_object_name() != null) { rootTableId = parseTableViewName(dropStmtBody.full_object_name().qualified_name()) } else if(dropStmtBody?.full_table_name() != null) { rootTableId = parseTableViewName(dropStmtBody.full_table_name().qualified_name()) } val dropTable = DropTable(rootTableId, dropDbObject?.exist()?.text == "ifexists") if (dropStmtBody?.purge_option() != null) { dropTable.purge = true } return dropTable } return null } override fun visitAlter_table_stmt(ctx: DmSqlParser.Alter_table_stmtContext): Statement { currentOptType = StatementType.ALTER_TABLE super.visitAlter_table_stmt(ctx) rootTableId = parseTableViewName(ctx.full_table_name().qualified_name()) return AlterTable(rootTableId) } override fun visitFull_tv_name(ctx: DmSqlParser.Full_tv_nameContext): Statement? { super.visitFull_tv_name(ctx) val tableId = parseTableViewName(ctx.qualified_name()) val parentLv2 = ctx.parent?.parent val parentLv5 = parentLv2?.parent?.parent?.parent val parentLv6 = parentLv5?.parent if (parentLv6 is DmSqlParser.Update_stmt_bodyContext || parentLv5 is DmSqlParser.Delete_stmtContext || parentLv2 is DmSqlParser.Insert_stmtContext || parentLv5 is DmSqlParser.Insert_stmtContext || parentLv5 is DmSqlParser.Insert_stmt_bodyContext || parentLv5 is DmSqlParser.Multi_insert_stmt_bodyContext || parentLv2 is DmSqlParser.Merge_into_stmtContext) { if (rootTableId.tableName == "") { tableId.also { rootTableId = it } } addOutputTableId(tableId) } else { if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } override fun visitFull_table_name(ctx: DmSqlParser.Full_table_nameContext?): Statement? { if (ctx?.qualified_name() != null) { rootTableId = parseTableViewName(ctx.qualified_name()) } return super.visitFull_table_name(ctx) } private fun parseTableViewName(ctx: ParserRuleContext): TableId { if (ctx.childCount == 1) { return TableId(null, null, CommonUtils.cleanQuote(ctx.getChild(0).text)) } else if (ctx.childCount == 3) { return TableId(null, CommonUtils.cleanQuote(ctx.getChild(0).text), CommonUtils.cleanQuote(ctx.getChild(2).text)) } else { throw SQLParserException("not suuport tablename") } } private fun addOutputTableId(tableId: TableId) { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } } ================================================ FILE: superior-dameng-parser/src/main/kotlin/io/github/melin/superior/parser/dameng/DmSqlHelper.kt ================================================ package com.github.melin.superior.sql.parser.mysql import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.dameng.AbstractSqlParser import io.github.melin.superior.parser.dameng.DmSqlAntlr4Visitor import io.github.melin.superior.parser.dameng.antlr4.DmSqlLexer import io.github.melin.superior.parser.dameng.antlr4.DmSqlParser import io.github.melin.superior.parser.dameng.antlr4.DmSqlParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object DmSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until DmSqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = DmSqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = DmSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = DmSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = DmSqlParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: DmSqlParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = DmSqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = DmSqlParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visitDmprogram(parser.dmprogram()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visitDmprogram(parser.dmprogram()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-dameng-parser/src/test/kotlin/io/github/melin/superior/parser/dameng/DmSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.dameng import com.github.melin.superior.sql.parser.mysql.DmSqlHelper import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.alter.AlterTable import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.create.CreateMaterializedView import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.drop.DropTable import org.junit.Assert import org.junit.Test class DmSqlParserDdlTest { @Test fun createTableTest0() { val sql = """ CREATE TABLE employees( employee_id number(10) NOT NULL, employee_name varchar2(50) NOT NULL, city varchar2(50), CONSTRAINT employees_pk PRIMARY KEY (employee_id) ) """.trimIndent() DmSqlHelper.splitSql(sql) val statement = DmSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) // Assert.assertEquals(3, statement.columnRels?.size) // Assert.assertTrue(statement.columnRels?.get(0)?.primaryKey!!) // Assert.assertFalse(statement.columnRels?.get(1)?.primaryKey!!) } else { Assert.fail() } } @Test fun createView0() { val sql = """ CREATE OR REPLACE VIEW comedies AS SELECT f.*, country_code_to_name(f.country_code) AS country, (SELECT avg(r.rating) FROM user_ratings r WHERE r.film_id = f.id) AS avg_rating FROM films f WHERE f.kind = 'Comedy' """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("comedies", statement.tableId.tableName) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun createMatView0() { val sql = """ CREATE MATERIALIZED VIEW sales_summary AS SELECT seller_no, invoice_date, sum(invoice_amt) as sales_amt FROM invoice WHERE invoice_date < CURRENT_DATE GROUP BY seller_no, invoice_date; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is CreateMaterializedView) { Assert.assertEquals(StatementType.CREATE_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals("sales_summary", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun commentTest0() { val sql = """ COMMENT ON COLUMN employees.job_id IS 'abbreviated job title'; COMMENT ON COLUMN employees1.job_id IS 'abbreviated1 job title' """.trimIndent() val statement = DmSqlHelper.parseMultiStatement(sql) val st1 = statement[0] val st2 = statement[1] if (st1 is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, st1.statementType) Assert.assertEquals("employees.job_id", st1.objValue) Assert.assertEquals("abbreviated job title", st1.comment) Assert.assertFalse(st1.isNull) } if (st2 is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, st2.statementType) Assert.assertEquals("employees1.job_id", st2.objValue) Assert.assertEquals("abbreviated1 job title", st2.comment) Assert.assertFalse(st2.isNull) } } @Test fun dropTableTest() { val sql = """ drop table employees purge; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertTrue(statement.purge) } else { Assert.fail() } } @Test fun alterTableTest() { val sql = """ ALTER TABLE "t1" RENAME COLUMN "old_column" TO "new_column_temp"; ALTER TABLE "t2" ADD "new_column" VARCHAR(8000); ALTER TABLE "t3" DROP COLUMN "new_column_temp"; """.trimIndent() val statement = DmSqlHelper.parseMultiStatement(sql) val st1 = statement[0] val st2 = statement[1] val st3 = statement[2] if (st1 is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, st1.statementType) Assert.assertEquals("t1", st1.tableId.tableName) } else { Assert.fail() } if (st2 is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, st2.statementType) Assert.assertEquals("t2", st2.tableId.tableName) } else { Assert.fail() } if (st3 is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, st3.statementType) Assert.assertEquals("t3", st3.tableId.tableName) } else { Assert.fail() } } } ================================================ FILE: superior-dameng-parser/src/test/kotlin/io/github/melin/superior/parser/dameng/DmSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.dameng import com.github.melin.superior.sql.parser.mysql.DmSqlHelper import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.dml.DeleteTable import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.MergeTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.dml.UpdateTable import org.apache.commons.io.FileUtils import org.junit.Assert import org.junit.Test import java.io.File /** Created by libinsong on 2018/1/10. */ class DmSqlParserDmlTest { @Test fun querySqlTest0() { val sql1 = FileUtils.readFileToString(File("./src/test/resources/insert.sql"), "UTF-8") val statement = DmSqlHelper.parseStatement(sql1) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(27, statement.queryStmt.inputTables.size) Assert.assertEquals(TableId("dwd", "dwd_d03_contract_det_s"), statement.outputTables.get(0)) } else { Assert.fail() } } @Test fun querySqlTest1() { val sql = """ select 1 from db.t1; """.trimIndent() try { val statement = DmSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId(null, "db", "t1"), statement.inputTables[0]) } else { Assert.fail() } } catch (e: Exception) { Assert.fail() } } @Test fun cteSqlTest0() { val sql = """ WITH cte1 AS (SELECT 'a' AS a, 'b' AS b), cte2 AS (SELECT 'c' AS c, 'd' AS d) SELECT b, d FROM cte1 JOIN cte2 ON cte1.a = cte2.c; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(TableId("cte1"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun deleteTest() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun insertTest0() { val sql = """ INSERT ALL INTO pivot_dest (id, day, val) VALUES (id, 'mon', mon_val) INTO pivot_dest (id, day, val) VALUES (id, 'tue', tue_val) INTO pivot_dest (id, day, val) VALUES (id, 'wed', wed_val) INTO pivot_dest (id, day, val) VALUES (id, 'thu', thu_val) INTO pivot_dest (id, day, val) VALUES (id, 'fri', fri_val) SELECT * FROM pivot_source; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("pivot_dest", statement.outputTables.get(0).tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest1() { val sql = """ INSERT ALL INTO dest_tab1 (id, description) VALUES (id, description) INTO dest_tab2 (id, description) VALUES (id, description) INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest2() { val sql = """ INSERT ALL WHEN id <= 3 THEN INTO dest_tab1 (id, description) VALUES (id, description) WHEN id BETWEEN 4 AND 7 THEN INTO dest_tab2 (id, description) VALUES (id, description) WHEN id >= 8 THEN INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest3() { val sql = """ INSERT FIRST WHEN id <= 3 THEN INTO dest_tab1 (id, description) VALUES (id, description) WHEN id <= 5 THEN INTO dest_tab2 (id, description) VALUES (id, description) ELSE INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest4() { val sql = """ INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest() { val sql = """ MERGE INTO bonuses D USING (SELECT employee_id, salary, department_id FROM hr.employees WHERE department_id = 80) S ON (D.employee_id = S.employee_id) WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01 DELETE WHERE (S.salary > 8000) WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus) VALUES (S.employee_id, S.salary*.01) WHERE (S.salary <= 8000); """.trimIndent() val statement = DmSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("bonuses", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-dameng-parser/src/test/kotlin/io/github/melin/superior/parser/dameng/DmSqlProcedureParserTest.kt ================================================ package io.github.melin.superior.parser.dameng class DmSqlProcedureParserTest {} ================================================ FILE: superior-dameng-parser/src/test/resources/insert.sql ================================================ insert into dwd.dwd_d03_contract_det_s select to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') stt_date ,to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') end_date ,'01' cont_source_cd -- 合同来源编码: 01-通用核心; 02-商用车 ,'通用核心' cont_source_nm -- 合同来源:通用核心/商用车 ,cc.pk_contract -- 合同主键 ,cc.cont_code -- 合同编码 ,cc.cont_name -- 合同名称 ,cc.cont_type cont_type_cd -- 合同类型编码 ,pt2.param_name cont_type_nm -- 合同类型名称 ,cc.cont_status cont_status_cd -- 合同状态编码 ,pt1.param_name cont_status_nm -- 合同状态名称 ,pt3.param_value economic_style_cd -- 控股类型编码 ,replace(replace(pt3.param_name ,'绝对',''),'相对','') economic_style_nm -- 控股类型 ,cc.cont_amount -- 合同金额 ,cc.lease_date_fact -- 起租日 ,cc.cont_end_date -- 到期日 ,lc.lease_times lease_times -- 租赁期(月数) ,round(lc.lease_times/12,2) lease_year -- 租赁期(年数) ,case when cc.cont_amount >= 100000000 then '大型' when cc.cont_amount >= 10000000 and cc.cont_amount < 100000000 then '中型' else '小型' end cont_scala -- 合同规模 ,case when cc.if_adjust = 0 then '是' when cc.if_adjust = 1 then '否' else null end if_adjust -- 是否调息 ,sjtf.fact_cash_loan -- 已投放金额 ,sjtf.pay_date -- 首次投放日期 ,ba1.name pay_province -- 投放地区省 ,ba2.name pay_city -- 投放地区市 ,ba3.name pay_area -- 客户所属区 ,coalesce(nn.assets_classify, cc.assets_classify, 0) assets_classify_cd -- 五级分类代码 ,case coalesce(nn.assets_classify, cc.assets_classify, 0) when 0 then '正常' when 1 then '关注' when 2 then '次级' when 3 then '可疑' when 4 then '损失' else '正常' end assets_classify_nm -- 五级分类名称 ,pi.pk_project_info -- 项目编号 ,pi.project_name -- 项目名称 ,pi.lease_categry lease_categry_cd -- 租赁类型代码 ,case when pi.lease_categry = 0 then '融资租赁' when pi.lease_categry = 1 then '经营性租赁' else null end lease_categry_nm -- 租赁类型名称 ,case when pbl.if_group_company = 0 then '是' else '否' end if_group_company -- 是否集团客户 ,pbl.vesting_group -- 集团客户名称 ,lc.lease_method lease_method_cd -- 业务类型代码 ,case when lc.lease_method = 0 then '直租' when lc.lease_method = 1 then '回租' when lc.lease_method = 4 then '转租赁' else null end lease_method_nm -- 业务类型名称 ,main_thing.fixed_assets -- 固定资产门类 ,main_thing.fixed_assets_lag -- 固定资产门类-大类 ,main_thing.fixed_assets_mid -- 固定资产门类--中类 ,main_thing.fixed_assets_sml -- 固定资产门类--小类 ,main_thing.thing_name -- 租赁物名称 -- 主办人相关信息 ,su.user_code main_user_code -- 主办项目经理编号 ,su.user_name main_user_name -- 主办项目经理 ,su.dept_code main_dept_code -- 主办业务部门编号 ,su.dept_name main_dept_name -- 主办业务部门名称 -- 协办人相关信息 ,su2.user_code help_user_code -- 协办项目经理编号 ,su2.user_name help_user_name -- 协办项目经理 ,su2.dept_code help_dept_code -- 协办业务部门编号 ,su2.dept_name help_dept_name -- 协办业务部门名称 ,coalesce(pa.sponsor_performance, pa.sponsor_performance_sh * 100) sponsor_performance -- 主办分成比例(两位整数) ,coalesce(pa.help_performance, pa.help_performance_one * 100) help_performance -- 协办分成比例(两位整数) ,pn.investment investment_cd -- 城建类分类 ,case when coalesce(pn.investment, cu.investment) = 0 then '是' else '否' end investment_nm -- 是否城建类 ,vc.customer_name -- 承租人名称 ,case when vc.identity_type = 4 then vc.identity_no else null end identity_no -- 统一社会信用代码 ,vc.risk_level risk_level_cd -- 客户洗钱风险评级代码 ,case when vc.risk_level = '1001' then '低风险' when vc.risk_level = '1002' then '较低风险' when vc.risk_level = '1003' then '中风险' when vc.risk_level = '1004' then '较高风险' when vc.risk_level = '1005' then '高风险' when vc.risk_level = '1006' then '无结果' when vc.risk_level = '1007' then '查询失败' else null end risk_level_nm -- 客户洗钱风险评级名称 ,cu.organization_code organization_code -- 组织机构代码 ,hy.param_name industry -- 国标行业门类 ,hy1.param_name industry_lag -- 国标行业大类 ,hy2.param_name industry_mid -- 国标行业中类 ,hy3.param_name industry_sml -- 国标行业小类 ,coalesce(cc.business_module, dm1.business_mode_nm, '其他') industry_mod -- 业务板块——9大分类 ,case when cc.cont_status = 8 or (cc.cont_status = 2 and '${yyyy-mm-dd}' <= cc.lease_date_fact) or (cc.cont_status = 2 and '${yyyy-mm-dd}' >= cc.lease_date_fact and coalesce(sjtf.fact_cash_loan,0) < coalesce(ipc.lease_corpus,0) and planc.plan_count >= 2 ) then coalesce(sjtf.fact_cash_loan,0) - coalesce(gather.gather_corpus,0) - coalesce(sfk.inner_deduct_cash,0) else coalesce(ipc.lease_corpus,0) - coalesce(gather.gather_corpus,0) - coalesce(sfk.inner_deduct_cash,0) end corpus_balance -- 剩余本金 ,coalesce(history.lease_interest,ipc.lease_interest) - coalesce(gather.gather_interest,0) interest_balance -- 剩余利息 ,case when yoc.pk_contract is not null then coalesce(lpb.deposit_balance,0) else 0 end deposit_balance -- 剩余保证金 -- 调整剩余保证金逻辑, 保持和源端取值一样 11.22(剩余风险抵押金 按照逻辑把字段衍生出来) -- ,coalesce(lpb.deposit_balance,0) deposit_balance -- 剩余保证金 ,case when yoc.pk_contract is null then coalesce(lpb.deposit_balance,0) else 0 end mortgage_balance -- 剩余风险抵押金 ,COALESCE(adj.INTERRATE_FACT_AFTER,lc.FINAL_RATE, 0) contract_rate -- 合同利率 ,COALESCE(adj.PROJECT_IRR,lc.PROJECT_IRR, 0) * 100.0 PROJECT_IRR -- IRR(现行) ,COALESCE(adj.CONTRACT_XIRR,lc.CONTRACT_XIRR, 0) * 100.0 CONTRACT_XIRR -- XIRR(含税) -- 增加字段 ,case when yoc.pk_contract is null then '是' else '否' end is_mortgage -- 是否风险抵押金 ,case when cc.cont_status = 8 and coalesce(ipo.overdue_days_zqx, 0) >= 1 then '是' when cc.cont_status <> 8 and coalesce(ipo.overdue_days, 0) >= 1 then '是' else '否' end if_overdue -- 是否逾期 ,yq.OVERDUE_DATE overdue_days -- 最大逾期天数(含历史) ,magum.param_name pledge_name -- 担保方式 ,case when lc.interrate_type = 0 then '浮动利率' else '固定利率' end interrate_type -- 利率类型 ,ipc.lease_cash1 handling_fee -- 手续费/咨询费 ,ipc.lease_cash11 fixed_rent -- 固定租金 ,ipc.lease_cash2 deposit_amt -- 保证金金额 ,ipc.lease_cash22 margin_bal -- 保证金余额 ,ipc.lease_cash3 margin_off_amt -- 保证金冲抵金额 ,ipc.lease_cash33 refund_deposit -- 退还保证金 ,nn.accrue_cash -- 拨备余额 ,vc.customer_code -- 承租人编号 from dwd.dg1_yls_contract_c_c cc -- 合同表 -- 补全9大分类 left join dim.dim_d99_business_mode_cd dm1 on cc.industry3 = dm1.pk_parameter and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between dm1.stt_date and dm1.end_date -- 合同状态 left join dwd.dg1_yls_parameter_c pt1 on cc.cont_status = pt1.param_value and pt1.pk_param_type = upper('0001AA1000000001RC3C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt1.stt_date and pt1.end_date -- 合同类型 left join dwd.dg1_yls_parameter_c pt2 on cc.cont_type = pt2.param_value and pt2.pk_param_type = upper('0001AA1000000001VJBS') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt2.stt_date and pt2.end_date -- 控股类型 left join dwd.dg1_yls_parameter_c pt3 on cc.economic_style1 = pt3.pk_parameter and pt3.pk_param_type = upper('0001AA10000000041633') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt3.stt_date and pt3.end_date -- 担保方式 left join dwd.dg1_yls_parameter_c magum on cc.major_guarantee_method = magum.pk_parameter and magum.pk_param_type = upper('0001AA1000000002K3MQ') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt3.stt_date and pt3.end_date -- 逾期情况 left join ( select ipc.pk_contract ,coalesce(max(case when ipc.trans_type = upper('0001AA100000000AUBPA') and ipc.charge_off_status = 2 and gab.check_date > '${yyyy-mm-dd}' then to_date(gab.check_date, 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') when ipc.trans_type = upper('0001AA100000000AUBPA') and ipc.charge_off_status <> 2 and ipc.plan_date <= '${yyyy-mm-dd}' then to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') end), 0) as overdue_days_zqx ,coalesce(max(case when ipc.charge_off_status = 2 and gab.check_date > '${yyyy-mm-dd}' then to_date(gab.check_date, 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') when ipc.charge_off_status <> 2 and ipc.plan_date <= '${yyyy-mm-dd}' then to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') end), 0) as overdue_days /*租金逾期天数*/ from dwd.dg1_yls_inout_plan_c_c ipc left join (select gab.pk_inout_plan ,coalesce(max(gap.trade_date), '${yyyy-mm-dd}') as check_date from dwd.dg1_yls_gather_account_b_c gab inner join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date inner join dwd.dg1_yls_gather_audit_plan_c gap on gap.pk_gather_account_b = gab.pk_gather_account_b and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gap.stt_date and gap.end_date where ga.billstatus = 9 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date group by gab.pk_inout_plan) gab on gab.pk_inout_plan = ipc.pk_inout_plan where ipc.trans_type in (upper('0001AA10000000007NGV'), upper('0001AA100000000AUBPA'), upper('0001AA10000000007NH3')) /* 现金流类型 租金 收租(租前息) 首付款*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and ipc.plan_date <= '${yyyy-mm-dd}' and ipc.lease_cash >= 0.01 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) ipo on cc.pk_contract = ipo.pk_contract left join ( select plan.PK_CONTRACT,max(rec.OVERDUE_DATE) OVERDUE_DATE from dwd.dg1_yls_overdue_record_c rec join dwd.dg1_yls_inout_plan_c_c plan on plan.PK_INOUT_PLAN = rec.PK_INOUT_PLAN and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between plan.stt_date and plan.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between rec.stt_date and rec.end_date group by plan.PK_CONTRACT ) yq on yq.PK_CONTRACT = cc.PK_CONTRACT -- 实际投放金额 left join ( select ipc.pk_contract -- 主键 ,sum(coalesce(lp.real_pay_cash, 0.00)) fact_cash_loan -- 已投放金额 ,min(coalesce(ld.real_pay_date, '${yyyy-mm-dd}')) pay_date -- 首次投放日 from dwd.dg1_yls_inout_plan_c_c ipc left join dwd.dg1_yls_loan_plan_c lp on ipc.pk_inout_plan = lp.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date left join dwd.dg1_yls_loan_deal_c ld on lp.pk_loan_deal = ld.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date and ipc.trans_type in (upper('0001AA10000000005GRC'), upper('0001AA10000000007NGO'), upper('0001AA1000000005AB31'), upper('0001AA1000000005AB32')) and ipc.rent_type = 1 -- 租金表类型-会计表 and lp.if_account = 0 -- 是否核销为是 and lp.if_approve_cancel = 1 -- 是否审核撤销为否时 and lp.if_cancel = 1 -- 是否核销撤销为否时 and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' group by ipc.pk_contract ) sjtf on cc.pk_contract = sjtf.pk_contract -- 首付款 left join ( select ipc.pk_contract ,sum(coalesce(ipc.lease_cash, 0.00)) as inner_deduct_cash ,min(coalesce(ld.real_pay_date, '${yyyy-mm-dd}')) as pay_date from dwd.dg1_yls_inout_plan_c_c ipc left join dwd.dg1_yls_loan_plan_c lp on lp.pk_inout_plan = ipc.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date left join dwd.dg1_yls_loan_deal_c ld on ld.pk_loan_deal = lp.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where ipc.trans_type = '0001AA10000000007NH3' /* 现金流类型 设备款*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and lp.if_inner_deduct = 2 /* 是否内扣为是 */ and lp.if_cancel = 1 /* 是否核销撤销为否时 */ and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) sfk on cc.pk_contract = sfk.pk_contract -- 五级分类 left join ( select i1.pk_contract -- 合同PK ,i1.assets_classify -- 五级分类 ,i1.accrue_cash from dwd.dg1_assets_classify_history_c i1 -- yls_assets_classify_history join ( select ic.pk_contract ,max(ic.pk_assets_classify_history) pk_assets_classify_history from dwd.dg1_assets_classify_history_c ic where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ic.stt_date and ic.end_date and ( case when ic.if_new = 0 then ic.period else coalesce(substr(replace(ic.change_date, '-', ''), 1, 6), ic.period) end ) <= substr(replace('${yyyy-mm-dd}', '-', ''), 1, 6) group by ic.pk_contract ) i2 on i1.pk_assets_classify_history = i2.pk_assets_classify_history where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between i1.stt_date and i1.end_date ) nn on cc.pk_contract = nn.pk_contract -- 项目信息 left join dwd.dg1_yls_project_info_c pi on cc.pk_project = pi.pk_project_info and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pi.stt_date and pi.end_date -- 集团客户 left join ( select distinct source_bill, if_group_company, vesting_group from dwd.dg1_yls_project_both_lessee_c where lessee_type = 0 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between stt_date and end_date ) pbl on pi.pk_project_info = pbl.source_bill -- 主办/协办信息 left join dwd.dg1_yls_project_approval_c pa on pi.pk_project_approval = pa.pk_project_approval and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pa.stt_date and pa.end_date -- 城建类 left join ( select row_number() over(partition by pk_project_info order by ts) rcnt ,i3.pk_project_info ,i3.investment -- 城建类判断 from dwd.dg1_yls_prj_nodecollect_c i3 where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between i3.stt_date and i3.end_date ) pn on pi.pk_project_info = pn.pk_project_info and pn.rcnt = 1 -- 用户信息相关 left join dwd.dg1_yls_customer_c vc on cc.pk_customer_lessee = vc.pk_customer and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between vc.stt_date and vc.end_date -- 企业客户基本信息 left join dwd.dg1_yls_customer_corp_c cu on vc.pk_customer = cu.pk_customer and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between cu.stt_date and cu.end_date -- 投放地区 left join dwd.dg1_bd_areacl_c ba1 on ba1.pk_areacl = cu.PROVINCE and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba1.stt_date and ba1.end_date left join dwd.dg1_bd_areacl_c ba2 on ba2.pk_areacl = cu.CITY and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba2.stt_date and ba2.end_date left join dwd.dg1_bd_areacl_c ba3 on ba3.pk_areacl = cu.DISTRICT and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba3.stt_date and ba3.end_date -- 行业分类 left join dwd.dg1_yls_parameter_c hy on cc.industry = hy.pk_parameter and hy.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy.stt_date and hy.end_date left join dwd.dg1_yls_parameter_c hy1 on cc.industry1 = hy1.pk_parameter and hy1.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy1.stt_date and hy1.end_date left join dwd.dg1_yls_parameter_c hy2 on cc.industry2 = hy2.pk_parameter and hy2.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy2.stt_date and hy2.end_date left join dwd.dg1_yls_parameter_c hy3 on cc.industry3 = hy3.pk_parameter and hy3.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy3.stt_date and hy3.end_date -- 剩余保证金计算 left join ( select ipc.pk_contract ,sum(case when ipc.trans_type = '0001AA10000000007NHR' then (case when lp.pay_cash > ipc.lease_cash then coalesce(ipc.lease_cash, 0.00) else coalesce(lp.pay_cash, 0.00) end) + coalesce(gac.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NHT' then -coalesce(gab.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NI5' then coalesce(gac.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NHX' then -coalesce(lp.pay_cash, 0) else 0 end) as deposit_balance from dwd.dg1_yls_inout_plan_c_c ipc left join (select ipc.pk_inout_plan ,coalesce(ga.charge_off_cash, 0) as gather_cash from dwd.dg1_yls_inout_plan_c_c ipc inner join dwd.dg1_yls_gather_account_c ga on ipc.pk_inout_plan = ga.pk_account_bill and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date where ga.billstatus = 9 /*单据状态 审核通过*/ and ga.check_date <= '${yyyy-mm-dd}' and ipc.trans_type = '0001AA10000000007NHT' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date ) gab on gab.pk_inout_plan = ipc.pk_inout_plan left join (select ipc.pk_inout_plan ,coalesce(gab.gather_cash, 0) as gather_cash from dwd.dg1_yls_inout_plan_c_c ipc inner join dwd.dg1_yls_gather_account_b_c gab on ipc.pk_inout_plan = gab.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date inner join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date where ga.billstatus = 9 /*单据状态 审核通过*/ and ga.check_date <= '${yyyy-mm-dd}' and ipc.trans_type in ('0001AA10000000007NHR', '0001AA10000000007NI5') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date ) gac on gac.pk_inout_plan = ipc.pk_inout_plan left join (select lp.pk_inout_plan ,(case when coalesce(ld.real_pay_cash, 0.00) = 0 then coalesce(ld.inner_deduct_cash, 0.00) else coalesce(ld.real_pay_cash, 0.00) end) as pay_cash from dwd.dg1_yls_loan_plan_c lp inner join dwd.dg1_yls_loan_deal_c ld on ld.pk_loan_deal = lp.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where lp.if_approve_cancel = 1 /* 是否审核撤销为否时 */ and lp.if_cancel = 1 /* 是否核销撤销为否时 */ and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date ) lp on lp.pk_inout_plan = ipc.pk_inout_plan where ipc.trans_type in ('0001AA10000000007NHR', '0001AA10000000007NHT', '0001AA10000000007NI5', '0001AA10000000007NHX') /* 现金流类型 收取保证金,保证金冲抵,补足保证金,退还保证金*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) lpb on cc.pk_contract = lpb.pk_contract left join dwd.dg1_yls_old_contract_c yoc on cc.pk_contract = yoc.pk_contract and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between yoc.stt_date and yoc.end_date -- 实收数据 left join ( select sum(case when et.event_code in ('10201', '10203', '10216') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_cash, 0) else 0 end) gather_cash ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_corpus, 0) else 0 end) gather_corpus ,sum(case when et.event_code in ('10201', '10216') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_interest, 0) else 0 end) gather_interest ,sum(case when et.event_code in ('10213') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_cash, 0) else 0 end) gather_penal_cash ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_cash, 0) else 0 end) gather_cash1 ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_corpus, 0) else 0 end) gather_corpus1 ,sum(case when et.event_code in ('10201', '10203', '10216') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_interest, 0) else 0 end) gather_interest1 ,sum(case when et.event_code in ('10213') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_cash, 0) else 0 end) gather_penal_cash1 ,sum(case when gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then 1 else 0 end) cur_year_time ,sum(case when gab.trade_date >= '${yyyy-mm-dd}' and gab.trade_date <= to_char(add_months(date'${yyyy-mm-dd}', 12), 'yyyy-mm-dd') then 1 else 0 end) future_time ,ipc.pk_contract from dwd.dg1_yls_gather_account_b_c gab join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date join dwd.dg1_yls_inout_plan_c_c ipc on ipc.pk_inout_plan = gab.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date join dwd.dg1_yls_event_type_c et on et.pk_event_type = ipc.trans_type and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date where ga.billstatus = 9 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date group by ipc.pk_contract ) gather on cc.pk_contract = gather.pk_contract left join dwd.dg1_yls_lease_calculator_c_c lc on cc.pk_lease_calculator = lc.pk_lease_calculator and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lc.stt_date and lc.end_date -- 实时数据 left join ( select sum(case when et.event_code in ('10201','10202','10203','10216') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash, /* 总租金 */ sum(case when et.event_code in ('10401'/*,'10402','10403'*/,'10606') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash1,/* 手续费/咨询费 */ sum(case when et.event_code in ('10405') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash11,/* 固定租金 */ sum(case when et.event_code in ('10301') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash2, /* 保证金收取 */ sum(case when et.event_code in ('10308') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash22, /* 补住保证金 */ sum(case when et.event_code in ('10302') then coalesce(ipc.fact_cash,0) else 0 end) lease_cash3, /* 保证金冲抵 */ sum(case when et.event_code in ('10304') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash33, /* 退还保证金 */ sum(case when et.event_code in ('10201','10203') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash4, /* 收取总租金 */ sum(case when et.event_code in ('10201','10202','10216') then coalesce(ipc.lease_interest,0) else 0 end) lease_interest, /* 收取总利息 */ sum(case when et.event_code in ('10101','10102') and ycc.cont_status = 8 then coalesce(ipc.fact_cash,0) when et.event_code in ('10201','10203') and ycc.cont_status != 8 then coalesce(ipc.lease_corpus,0) else 0 end) lease_corpus, /* 总本金 */ sum(case when et.event_code in ('10301','10308') then coalesce(ipc.fact_cash,0) else 0 end) fact_cash2, /* 实收:保证金收取、补足 */ sum(case when et.event_code in ('10302','10304') then coalesce(ipc.fact_cash,0) else 0 end) fact_cash3, /* 实际:保证金冲抵、退还保证金 */ ipc.source_bill from dwd.dg1_yls_inout_plan_c_c ipc join dwd.dg1_yls_event_type_c et on et.pk_event_type = ipc.trans_type and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date join dwd.dg1_yls_contract_c_c ycc on ycc.pk_contract = ipc.pk_contract and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ycc.stt_date and ycc.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.source_bill ) ipc on lc.pk_lease_calculator = ipc.source_bill -- 历史数据 left join ( select ch.CONT_CODE,rc.interrate,rc.new_final_rate ,rc.NEW_PROJECT_IRR,rc.NEW_CONTRACT_XIRR,h.lease_cash,h.lease_cash1,h.lease_cash2, h.lease_cash3,lease_cash22,h.lease_cash33,h.LEASE_INTEREST, h.fact_cash2,h.fact_cash3 from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.PK_CONTRACT = ch.PK_CONTRACT and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between rc.stt_date and rc.end_date join ( select iph.SOURCE_BILL, sum(case when et.EVENT_CODE in ('10201','10202','10203','10216') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash, /* 收租总租金 */ sum(case when et.EVENT_CODE in ('10401'/*,'10402','10403'*/,'10405','10606') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash1, /* 手续费/咨询费/固定租金 */ sum(case when et.EVENT_CODE in ('10201','10202','10216') then coalesce(iph.LEASE_INTEREST,0) else 0 end) LEASE_INTEREST, /* 收租总租息 */ sum(case when et.EVENT_CODE in ('10301') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash2, /* 保证金收取 */ sum(case when et.EVENT_CODE in ('10308') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash22, /* 保证金补住 */ sum(case when et.EVENT_CODE in ('10302') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash3, /* 保证金冲抵*/ sum(case when et.EVENT_CODE in ('10304') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash33, /* 保证金退还 */ sum(case when et.EVENT_CODE in ('10301','10308') then coalesce(iph.FACT_CASH,0) else 0 end) fact_cash2, /* 实收:保证金收取、补足 */ sum(case when et.EVENT_CODE in ('10302','10304') then coalesce(iph.FACT_CASH,0) else 0 end) fact_cash3 /* 实际:保证金冲抵、退还保证金 */ from dwd.dg1_yls_inout_plan_h_c iph join dwd.dg1_yls_event_type_c et on et.PK_EVENT_TYPE = iph.TRANS_TYPE and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between iph.stt_date and iph.end_date group by iph.SOURCE_BILL ) h on h.SOURCE_BILL = rc.PK_RENT_CALCULATOR where ch.SOURCE_BILL_VERSIONPK in ( select chh.PK_CONTRACT from dwd.dg1_yls_contract_h_c chh join ( select max(CHECK_DATE)CHECK_DATE,ch.cont_code from dwd.dg1_yls_contract_h_c ch where upper(ch.SOURCE_BILLTYPE) = upper('lease/ContractChange') and ch.SOURCE_BILL_VERSIONPK is null and ch.CHECK_DATE > '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ch.stt_date and ch.end_date group by ch.CONT_CODE )zj_change on zj_change.CHECK_DATE = chh.check_date and zj_change.cont_code = chh.cont_code and upper(chh.SOURCE_BILLTYPE) = upper('lease/ContractChange') and chh.SOURCE_BILL_VERSIONPK is null where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between chh.stt_date and chh.end_date ) and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ch.stt_date and ch.end_date ) history on history.cont_code = cc.cont_code -- 计划投放数量 left join ( select i5.pk_contract ,count(*) plan_count from dwd.dg1_yls_inout_plan_c_c i5 where i5.trans_type in ('0001AA10000000005GRC','0001AA10000000007NGO','0001AA1000000005AB31', '0001AA1000000005AB32') and i5.rent_type = 1 group by i5.pk_contract ) planc on cc.pk_contract = planc.pk_contract -- 租赁物信息 left join ( select ypfa1.param_name fixed_assets ,ypfa2.param_name fixed_assets_lag ,ypfa3.param_name fixed_assets_mid ,ypfa4.param_name fixed_assets_sml ,prtc.thing_name ,prtc.source_bill from dwd.dg1_yls_project_rent_thing_c_c prtc left join dwd.dg1_yls_parameter_c ypfa1 on ypfa1.pk_parameter = prtc.fixed_assets and ypfa1.is_enable = upper('Y') and ypfa1.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa1.stt_date and ypfa1.end_date left join dwd.dg1_yls_parameter_c ypfa2 on ypfa2.pk_parameter = prtc.fixed_assets_large and ypfa2.is_enable = upper('Y') and ypfa2.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa2.stt_date and ypfa2.end_date left join dwd.dg1_yls_parameter_c ypfa3 on ypfa3.pk_parameter = prtc.fixed_assets_middle and ypfa3.is_enable = upper('Y') and ypfa3.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa3.stt_date and ypfa3.end_date left join dwd.dg1_yls_parameter_c ypfa4 on ypfa4.pk_parameter = prtc.fixed_assets_small and ypfa4.is_enable = upper('Y') and ypfa4.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa4.stt_date and ypfa4.end_date where prtc.is_ref_main = 0 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between prtc.stt_date and prtc.end_date ) main_thing on cc.pk_contract = main_thing.source_bill -- 主办 left join dwd.dwd_d01_party_c su on cc.pk_prj_manager = su.cuserid and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between su.stt_date and su.end_date -- 协办 left join dwd.dwd_d01_party_c su2 on cc.pk_cust_help = su2.cuserid and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between su2.stt_date and su2.end_date left join ( select adj3.cont_code, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.interrate_after end) as interrate_after, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.interrate_fact_after end) as interrate_fact_after, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.project_irr end) as project_irr, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.contract_xirr end) as contract_xirr from( select adj.cont_code, adj.response_day, coalesce(min(case when adj.response_day < adj2.response_day then adj2.response_day end),'${yyyy-mm-dd}') response_day_end, min(adj.interrate_after) interrate_after, -- /*调息后基准利率*/ min(adj.interrate_fact_after) interrate_fact_after, -- /*调息后实际利率*/ min(adj.project_irr) project_irr, -- /*调息后合同irr*/ min(adj.contract_xirr) contract_xirr -- /*合同收益xirr*/ from (select ch.cont_code, ch.check_date as response_day, rc.interrate as interrate_after, rc.new_final_rate as interrate_fact_after, rc.new_project_irr as project_irr, rc.new_contract_xirr as contract_xirr from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.pk_contract = ch.pk_contract where upper(ch.source_billtype) = upper('lease/contractchange') and ch.source_bill_versionpk is null and ch.billstatus = 9 and date'${yyyy-mm-dd}' between ch.stt_date and ch.end_date and date'${yyyy-mm-dd}' between rc.stt_date and rc.end_date union all -- /*实际调息*/ select distinct cc.cont_code,aa.response_day, aa.interrate_after, -- /*调息后基准利率*/ aa.interrate_fact_after, -- /*调息后实际利率*/ aa.project_irr, -- /*调息后合同irr*/ aa.contract_xirr -- /*合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date where aa.billstatus = 9 and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date union all -- /*首次调息时,调息前信息*/ select distinct cc.cont_code,to_char(to_date(aa.response_day, 'yyyy-mm-dd') - 1, 'yyyy-mm-dd') as response_day, aa.interrate_before as interrate_after, -- /*调息前基准利率*/ aa.interrate_fact_before as interrate_fact_after, -- /*调息前实际利率*/ aa.cont_irr_befor as project_irr, -- /*调息前合同irr*/ aa.contract_xirr_before as contract_xirr -- /*调息前合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa join (select min(a.response_day) as response_day,a.pk_contract from dwd.dg1_yls_adjust_apply_c a where a.billstatus = 9 and date'${yyyy-mm-dd}' between a.stt_date and a.end_date group by a.pk_contract) minday on minday.pk_contract = aa.pk_contract and minday.response_day = aa.response_day and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date) adj left join ( select ch.cont_code, ch.check_date as response_day, rc.interrate as interrate_after, rc.new_final_rate as interrate_fact_after, rc.new_project_irr as project_irr, rc.new_contract_xirr as contract_xirr from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.pk_contract = ch.pk_contract where upper(ch.source_billtype) = upper('lease/contractchange') and ch.source_bill_versionpk is null and ch.billstatus = 9 and date'${yyyy-mm-dd}' between ch.stt_date and ch.end_date and date'${yyyy-mm-dd}' between rc.stt_date and rc.end_date union all select distinct cc.cont_code,aa.response_day, aa.interrate_after, -- /*调息后基准利率*/ aa.interrate_fact_after, -- /*调息后实际利率*/ aa.project_irr, -- /*调息后合同irr*/ aa.contract_xirr -- /*合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract where aa.billstatus = 9 and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date union all select distinct cc.cont_code,to_char(to_date(aa.response_day, 'yyyy-mm-dd') - 1, 'yyyy-mm-dd') as response_day, aa.interrate_before as interrate_after, -- /*调息前基准利率*/ aa.interrate_fact_before as interrate_fact_after, -- /*调息前实际利率*/ aa.cont_irr_befor as project_irr, -- /*调息前合同irr*/ aa.contract_xirr_before as contract_xirr -- /*调息前合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa join (select min(a.response_day) as response_day,a.pk_contract from dwd.dg1_yls_adjust_apply_c a where a.billstatus = 9 and date'${yyyy-mm-dd}' between a.stt_date and a.end_date group by a.pk_contract) minday on minday.pk_contract = aa.pk_contract and minday.response_day = aa.response_day left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date where date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date ) adj2 on adj2.cont_code = adj.cont_code group by adj.cont_code,adj.response_day ) adj3 group by adj3.cont_code ) adj on adj.cont_code = cc.cont_code where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between cc.stt_date and cc.end_date -- PK_PARAM_TYPE = '0001AA1000000001RC3C' 合同状态 and cc.cont_status > '1' and cc.cont_status not in ('5' ,'7') ================================================ FILE: superior-dameng-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-flink-parser/README.md ================================================ ### 介绍 ### 整库同步 ```sql -- 分布表,合并写入目标库中 CREATE DATABASE IF NOT EXISTS flink_cdc_demos WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://172.18.1.55:3306/flink_cdc_demos?characterEncoding=utf-8&useSSL=false', 'username' = 'root', 'password' = 'Datac@123', 'table-name' = '${'$'}{tableName}', 'sink.buffer-flush.interval' = '2s', 'sink.buffer-flush.max-rows' = '100', 'sink.max-retries' = '5' ) AS DATABASE `cdc_demos_[0-9]+` INCLUDING ALL TABLES OPTIONS( 'connector' = 'mysql-cdc', 'hostname' = '172.18.5.44', 'port' = '3306', 'username' = 'root', 'password' = 'root2023', 'checkpoint' = '10000', 'scan.startup.mode' = 'initial', 'parallelism' = '1' ) ``` ### 分库分表同步 ```sql CREATE TABLE IF NOT EXISTS flink_cdc_demos.account WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://172.18.1.55:3306/flink_cdc_demos?characterEncoding=utf-8&useSSL=false', 'username' = 'root', 'password' = 'Datac@123', 'table-name' = 'account', 'sink.buffer-flush.interval' = '2s', 'sink.buffer-flush.max-rows' = '100', 'sink.max-retries' = '5' ) AS TABLE `cdc_demos_[0-9]*`.`account_[0-9]*` OPTIONS( 'connector' = 'mysql-cdc', 'hostname' = '172.18.5.44', 'port' = '3306', 'username' = 'root', 'password' = 'root2023', 'checkpoint' = '10000', 'scan.startup.mode' = 'initial', 'parallelism' = '2' ) ``` ### 参考 1. [Dinky在Doris实时整库同步和模式演变的探索实践](https://mp.weixin.qq.com/s/OVsbRbfLEIgSNurlP6woAg) 2. [Dinky 数据集成](http://www.dlink.top/docs/next/data_integration_guide/cdcsource_statements) 3. [CREATE DATABASE AS(CDAS)语句](https://help.aliyun.com/document_detail/374304.html) 4. [数据库类型转换](https://www.sqlines.com/oracle-to-mysql) ================================================ FILE: superior-flink-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-flink-parser superior-flink-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-flink-parser/src/main/antlr4/io/github/melin/superior/parser/flink/antlr4/FlinkSqlLexer.g4 ================================================ lexer grammar FlinkSqlLexer; // SKIP WHITE_SPACE : (' ' | '\t' | '\r' | '\n') -> channel(HIDDEN); BRACKETED_COMMENT : '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: (('--' | '#') ~[\r\n]* ('\r'? '\n' | EOF) | '--' ('\r'? '\n' | EOF)) -> channel(HIDDEN); /** * Keywords and Reserved Keywords * Flink uses Calcite as its SQL parser, * The following keywords are derived from the Calcite documentation and Flink's own source code. * First, perform a union between the keyword sets declared in the Flink source code and those in the Calcite documentation, * then calculate the difference between the resulting set and the non-keyword set declared in the Flink source code. * * Calcite Documentation: https://calcite.apache.org/docs/reference.html#keywords * Flink Parser.tdd file: https://github.com/apache/flink/blob/release-1.16/flink-table/flink-sql-parser/src/main/codegen/data/Parser.tdd * * Please keep the keyword in alphabetical order if new keyword is added. * When adding new keywords, please consider whether they should be added to the NonReserved Keywords section below. */ KW_ABS : 'ABS'; KW_ALL : 'ALL'; KW_ALLOCATE : 'ALLOCATE'; KW_ALLOW : 'ALLOW'; KW_ALTER : 'ALTER'; KW_ANALYZE : 'ANALYZE'; KW_AND : 'AND'; KW_ANY : 'ANY'; KW_ARE : 'ARE'; KW_ARRAY : 'ARRAY'; KW_ARRAY_AGG : 'ARRAY_AGG'; KW_ARRAY_CONCAT_AGG : 'ARRAY_CONCAT_AGG'; KW_ARRAY_MAX_CARDINALITY : 'ARRAY_MAX_CARDINALITY'; KW_AS : 'AS'; KW_ASENSITIVE : 'ASENSITIVE'; KW_ASYMMETRIC : 'ASYMMETRIC'; KW_AT : 'AT'; KW_ATOMIC : 'ATOMIC'; KW_AUTHORIZATION : 'AUTHORIZATION'; KW_AVG : 'AVG'; KW_BEGIN : 'BEGIN'; KW_BEGIN_FRAME : 'BEGIN_FRAME'; KW_BEGIN_PARTITION : 'BEGIN_PARTITION'; KW_BETWEEN : 'BETWEEN'; KW_BIGINT : 'BIGINT'; KW_BINARY : 'BINARY'; KW_BIT : 'BIT'; KW_BLOB : 'BLOB'; KW_BOOLEAN : 'BOOLEAN'; KW_BOTH : 'BOTH'; KW_BY : 'BY'; KW_BYTES : 'BYTES'; KW_CALL : 'CALL'; KW_CALLED : 'CALLED'; KW_CARDINALITY : 'CARDINALITY'; KW_CASCADED : 'CASCADED'; KW_CASE : 'CASE'; KW_CAST : 'CAST'; KW_CATALOGS : 'CATALOGS'; KW_CEIL : 'CEIL'; KW_CEILING : 'CEILING'; KW_CHANGELOG_MODE : 'CHANGELOG_MODE'; KW_CHAR : 'CHAR'; KW_CHARACTER : 'CHARACTER'; KW_CHARACTER_LENGTH : 'CHARACTER_LENGTH'; KW_CHAR_LENGTH : 'CHAR_LENGTH'; KW_CHECK : 'CHECK'; KW_CLASSIFIER : 'CLASSIFIER'; KW_CLOB : 'CLOB'; KW_CLOSE : 'CLOSE'; KW_COALESCE : 'COALESCE'; KW_COLLATE : 'COLLATE'; KW_COLLECT : 'COLLECT'; KW_COLUMN : 'COLUMN'; KW_COLUMNS : 'COLUMNS'; KW_COMMENT : 'COMMENT'; KW_COMMIT : 'COMMIT'; KW_COMPUTE : 'COMPUTE'; KW_CONDITION : 'CONDITION'; KW_CONNECT : 'CONNECT'; KW_CONSTRAINT : 'CONSTRAINT'; KW_CONTAINS : 'CONTAINS'; KW_CONVERT : 'CONVERT'; KW_CORR : 'CORR'; KW_CORRESPONDING : 'CORRESPONDING'; KW_COUNT : 'COUNT'; KW_COVAR_POP : 'COVAR_POP'; KW_COVAR_SAMP : 'COVAR_SAMP'; KW_CREATE : 'CREATE'; KW_CROSS : 'CROSS'; KW_CUBE : 'CUBE'; KW_CUME_DIST : 'CUME_DIST'; KW_CURRENT : 'CURRENT'; KW_CURRENT_CATALOG : 'CURRENT_CATALOG'; KW_CURRENT_DATE : 'CURRENT_DATE'; KW_CURRENT_DEFAULT_TRANSFORM_GROUP : 'CURRENT_DEFAULT_TRANSFORM_GROUP'; KW_CURRENT_PATH : 'CURRENT_PATH'; KW_CURRENT_ROLE : 'CURRENT_ROLE'; KW_CURRENT_ROW : 'CURRENT_ROW'; KW_CURRENT_SCHEMA : 'CURRENT_SCHEMA'; KW_CURRENT_TIME : 'CURRENT_TIME'; KW_CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP'; KW_CURRENT_TRANSFORM_GROUP_FOR_TYPE : 'CURRENT_TRANSFORM_GROUP_FOR_TYPE'; KW_CURRENT_USER : 'CURRENT_USER'; KW_CURSOR : 'CURSOR'; KW_CYCLE : 'CYCLE'; KW_DATABASES : 'DATABASES'; KW_DATE : 'DATE'; KW_DATETIME : 'DATETIME'; KW_DATETIME_DIFF : 'DATETIME_DIFF'; KW_DATETIME_TRUNC : 'DATETIME_TRUNC'; KW_DATE_DIFF : 'DATE_DIFF'; KW_DATE_TRUNC : 'DATE_TRUNC'; KW_DAY : 'DAY'; KW_DAYOFWEEK : 'DAYOFWEEK'; KW_DAYOFYEAR : 'DAYOFYEAR'; KW_DEALLOCATE : 'DEALLOCATE'; KW_DEC : 'DEC'; KW_DECIMAL : 'DECIMAL'; KW_DECLARE : 'DECLARE'; KW_DEFAULT : 'DEFAULT'; KW_DEFINE : 'DEFINE'; KW_DELETE : 'DELETE'; KW_DENSE_RANK : 'DENSE_RANK'; KW_DEREF : 'DEREF'; KW_DESCRIBE : 'DESCRIBE'; KW_DETERMINISTIC : 'DETERMINISTIC'; KW_DISALLOW : 'DISALLOW'; KW_DISCONNECT : 'DISCONNECT'; KW_DISTINCT : 'DISTINCT'; KW_DOT : 'DOT'; KW_DOUBLE : 'DOUBLE'; KW_DROP : 'DROP'; KW_DYNAMIC : 'DYNAMIC'; KW_EACH : 'EACH'; KW_ELEMENT : 'ELEMENT'; KW_ELSE : 'ELSE'; KW_EMPTY : 'EMPTY'; KW_END : 'END'; // KW_END_EXEC: 'END-EXEC'; KW_END_FRAME : 'END_FRAME'; KW_END_PARTITION : 'END_PARTITION'; KW_ENFORCED : 'ENFORCED'; KW_EQUALS : 'EQUALS'; KW_ESCAPE : 'ESCAPE'; KW_ESTIMATED_COST : 'ESTIMATED_COST'; KW_EVERY : 'EVERY'; KW_EXCEPT : 'EXCEPT'; KW_EXEC : 'EXEC'; KW_EXECUTE : 'EXECUTE'; KW_EXISTS : 'EXISTS'; KW_EXP : 'EXP'; KW_EXPLAIN : 'EXPLAIN'; KW_EXTEND : 'EXTEND'; KW_EXTENDED : 'EXTENDED'; KW_EXTERNAL : 'EXTERNAL'; KW_EXTRACT : 'EXTRACT'; KW_FALSE : 'FALSE'; KW_FETCH : 'FETCH'; KW_FILTER : 'FILTER'; KW_FIRST_VALUE : 'FIRST_VALUE'; KW_FLOAT : 'FLOAT'; KW_FLOOR : 'FLOOR'; KW_FOR : 'FOR'; KW_FOREIGN : 'FOREIGN'; KW_FRAME_ROW : 'FRAME_ROW'; KW_FREE : 'FREE'; KW_FRIDAY : 'FRIDAY'; KW_FROM : 'FROM'; KW_FULL : 'FULL'; KW_FUNCTION : 'FUNCTION'; KW_FUNCTIONS : 'FUNCTIONS'; KW_FUSION : 'FUSION'; KW_GET : 'GET'; KW_GLOBAL : 'GLOBAL'; KW_GRANT : 'GRANT'; KW_GROUP : 'GROUP'; KW_GROUPING : 'GROUPING'; KW_GROUPS : 'GROUPS'; KW_GROUP_CONCAT : 'GROUP_CONCAT'; KW_HAVING : 'HAVING'; KW_HOLD : 'HOLD'; KW_HOUR : 'HOUR'; KW_IDENTITY : 'IDENTITY'; KW_IF : 'IF'; KW_ILIKE : 'ILIKE'; KW_IMPORT : 'IMPORT'; KW_IN : 'IN'; KW_INCLUDE : 'INCLUDE'; KW_INDICATOR : 'INDICATOR'; KW_INITIAL : 'INITIAL'; KW_INNER : 'INNER'; KW_INOUT : 'INOUT'; KW_INSENSITIVE : 'INSENSITIVE'; KW_INSERT : 'INSERT'; KW_INT : 'INT'; KW_INTEGER : 'INTEGER'; KW_INTERSECT : 'INTERSECT'; KW_INTERSECTION : 'INTERSECTION'; KW_INTERVAL : 'INTERVAL'; KW_INTO : 'INTO'; KW_IS : 'IS'; KW_JOIN : 'JOIN'; KW_JSON : 'JSON'; KW_JSON_ARRAY : 'JSON_ARRAY'; KW_JSON_ARRAYAGG : 'JSON_ARRAYAGG'; KW_JSON_EXECUTION_PLAN : 'JSON_EXECUTION_PLAN'; KW_JSON_EXISTS : 'JSON_EXISTS'; KW_JSON_OBJECT : 'JSON_OBJECT'; KW_JSON_OBJECTAGG : 'JSON_OBJECTAGG'; KW_JSON_QUERY : 'JSON_QUERY'; KW_JSON_VALUE : 'JSON_VALUE'; KW_LAG : 'LAG'; KW_LANGUAGE : 'LANGUAGE'; KW_LARGE : 'LARGE'; KW_LAST_VALUE : 'LAST_VALUE'; KW_LATERAL : 'LATERAL'; KW_LEAD : 'LEAD'; KW_LEADING : 'LEADING'; KW_LEFT : 'LEFT'; KW_LIKE : 'LIKE'; KW_LIKE_REGEX : 'LIKE_REGEX'; KW_LIMIT : 'LIMIT'; KW_LN : 'LN'; KW_LOCAL : 'LOCAL'; KW_LOCALTIME : 'LOCALTIME'; KW_LOCALTIMESTAMP : 'LOCALTIMESTAMP'; KW_LOWER : 'LOWER'; KW_MATCH : 'MATCH'; KW_MATCHES : 'MATCHES'; KW_MATCH_NUMBER : 'MATCH_NUMBER'; KW_MATCH_RECOGNIZE : 'MATCH_RECOGNIZE'; KW_MAX : 'MAX'; KW_MEASURES : 'MEASURES'; KW_MEMBER : 'MEMBER'; KW_MERGE : 'MERGE'; KW_METADATA : 'METADATA'; KW_METHOD : 'METHOD'; KW_MIN : 'MIN'; KW_MINUS : 'MINUS'; KW_MINUTE : 'MINUTE'; KW_MOD : 'MOD'; KW_MODIFIES : 'MODIFIES'; KW_MODIFY : 'MODIFY'; KW_MODULE : 'MODULE'; KW_MODULES : 'MODULES'; KW_MONDAY : 'MONDAY'; KW_MONTH : 'MONTH'; KW_MORE : 'MORE'; KW_MULTISET : 'MULTISET'; KW_NATIONAL : 'NATIONAL'; KW_NATURAL : 'NATURAL'; KW_NCHAR : 'NCHAR'; KW_NCLOB : 'NCLOB'; KW_NEW : 'NEW'; KW_NEXT : 'NEXT'; KW_NO : 'NO'; KW_NONE : 'NONE'; KW_NORMALIZE : 'NORMALIZE'; KW_NOT : 'NOT'; KW_NTH_VALUE : 'NTH_VALUE'; KW_NTILE : 'NTILE'; KW_NULL : 'NULL'; KW_NULLIF : 'NULLIF'; KW_NUMERIC : 'NUMERIC'; KW_OCCURRENCES_REGEX : 'OCCURRENCES_REGEX'; KW_OCTET_LENGTH : 'OCTET_LENGTH'; KW_OF : 'OF'; KW_OFFSET : 'OFFSET'; KW_OLD : 'OLD'; KW_OMIT : 'OMIT'; KW_ON : 'ON'; KW_ONE : 'ONE'; KW_ONLY : 'ONLY'; KW_OPEN : 'OPEN'; KW_OR : 'OR'; KW_ORDER : 'ORDER'; KW_ORDINAL : 'ORDINAL'; KW_OUT : 'OUT'; KW_OUTER : 'OUTER'; KW_OVER : 'OVER'; KW_OVERLAPS : 'OVERLAPS'; KW_OVERLAY : 'OVERLAY'; KW_OVERWRITE : 'OVERWRITE'; KW_OVERWRITING : 'OVERWRITING'; KW_PARAMETER : 'PARAMETER'; KW_PARTITION : 'PARTITION'; KW_PARTITIONED : 'PARTITIONED'; KW_PARTITIONS : 'PARTITIONS'; KW_PATTERN : 'PATTERN'; KW_PER : 'PER'; KW_PERCENT : 'PERCENT'; KW_PERCENTILE_CONT : 'PERCENTILE_CONT'; KW_PERCENTILE_DISC : 'PERCENTILE_DISC'; KW_PERCENT_RANK : 'PERCENT_RANK'; KW_PERIOD : 'PERIOD'; KW_PERMUTE : 'PERMUTE'; KW_PLAN_ADVICE : 'PLAN_ADVICE'; KW_PIVOT : 'PIVOT'; KW_PORTION : 'PORTION'; KW_POSITION : 'POSITION'; KW_POSITION_REGEX : 'POSITION_REGEX'; KW_POWER : 'POWER'; KW_PRECEDES : 'PRECEDES'; KW_PRECISION : 'PRECISION'; KW_PREPARE : 'PREPARE'; KW_PREV : 'PREV'; KW_PRIMARY : 'PRIMARY'; KW_PROCEDURE : 'PROCEDURE'; KW_QUALIFY : 'QUALIFY'; KW_QUARTERS : 'QUARTERS'; KW_RANGE : 'RANGE'; KW_RANK : 'RANK'; KW_RAW : 'RAW'; KW_READS : 'READS'; KW_REAL : 'REAL'; KW_RECURSIVE : 'RECURSIVE'; KW_REF : 'REF'; KW_REFERENCES : 'REFERENCES'; KW_REFERENCING : 'REFERENCING'; KW_REGR_AVGX : 'REGR_AVGX'; KW_REGR_AVGY : 'REGR_AVGY'; KW_REGR_COUNT : 'REGR_COUNT'; KW_REGR_INTERCEPT : 'REGR_INTERCEPT'; KW_REGR_R2 : 'REGR_R2'; KW_REGR_SLOPE : 'REGR_SLOPE'; KW_REGR_SXX : 'REGR_SXX'; KW_REGR_SXY : 'REGR_SXY'; KW_REGR_SYY : 'REGR_SYY'; KW_RELEASE : 'RELEASE'; KW_RENAME : 'RENAME'; KW_RESET : 'RESET'; KW_RESULT : 'RESULT'; KW_RETURN : 'RETURN'; KW_RETURNS : 'RETURNS'; KW_REVOKE : 'REVOKE'; KW_RIGHT : 'RIGHT'; KW_RLIKE : 'RLIKE'; KW_ROLLBACK : 'ROLLBACK'; KW_ROLLUP : 'ROLLUP'; KW_ROW : 'ROW'; KW_ROWS : 'ROWS'; KW_ROW_NUMBER : 'ROW_NUMBER'; KW_RUNNING : 'RUNNING'; KW_SAFE_CAST : 'SAFE_CAST'; KW_SAFE_OFFSET : 'SAFE_OFFSET'; KW_SAFE_ORDINAL : 'SAFE_ORDINAL'; KW_SATURDAY : 'SATURDAY'; KW_SAVEPOINT : 'SAVEPOINT'; KW_SCALA : 'SCALA'; KW_SCOPE : 'SCOPE'; KW_SCROLL : 'SCROLL'; KW_SEARCH : 'SEARCH'; KW_SECOND : 'SECOND'; KW_SEEK : 'SEEK'; KW_SELECT : 'SELECT'; KW_SENSITIVE : 'SENSITIVE'; KW_SEPARATOR : 'SEPARATOR'; KW_SESSION_USER : 'SESSION_USER'; KW_SET : 'SET'; KW_SHOW : 'SHOW'; KW_SIMILAR : 'SIMILAR'; KW_SKIP : 'SKIP'; KW_SMALLINT : 'SMALLINT'; KW_SOME : 'SOME'; KW_SPECIFIC : 'SPECIFIC'; KW_SPECIFICTYPE : 'SPECIFICTYPE'; KW_SQL : 'SQL'; KW_SQLEXCEPTION : 'SQLEXCEPTION'; KW_SQLSTATE : 'SQLSTATE'; KW_SQLWARNING : 'SQLWARNING'; KW_SQRT : 'SQRT'; KW_START : 'START'; KW_STATEMENT : 'STATEMENT'; KW_STATIC : 'STATIC'; KW_STATISTICS : 'STATISTICS'; KW_STDDEV_POP : 'STDDEV_POP'; KW_STDDEV_SAMP : 'STDDEV_SAMP'; KW_STREAM : 'STREAM'; KW_STRING : 'STRING'; KW_STRING_AGG : 'STRING_AGG'; KW_SUBMULTISET : 'SUBMULTISET'; KW_SUBSET : 'SUBSET'; KW_SUBSTRING : 'SUBSTRING'; KW_SUBSTRING_REGEX : 'SUBSTRING_REGEX'; KW_SUCCEEDS : 'SUCCEEDS'; KW_SUM : 'SUM'; KW_SUNDAY : 'SUNDAY'; KW_SYMMETRIC : 'SYMMETRIC'; KW_SYSTEM : 'SYSTEM'; KW_SYSTEM_TIME : 'SYSTEM_TIME'; KW_SYSTEM_USER : 'SYSTEM_USER'; KW_TABLE : 'TABLE'; KW_TABLES : 'TABLES'; KW_TABLESAMPLE : 'TABLESAMPLE'; KW_THEN : 'THEN'; KW_THURSDAY : 'THURSDAY'; KW_TIME : 'TIME'; KW_TIMESTAMP : 'TIMESTAMP'; KW_TIMESTAMP_DIFF : 'TIMESTAMP_DIFF'; KW_TIMESTAMP_LTZ : 'TIMESTAMP_LTZ'; KW_TIMESTAMP_TRUNC : 'TIMESTAMP_TRUNC'; KW_TIMEZONE_HOUR : 'TIMEZONE_HOUR'; KW_TIMEZONE_MINUTE : 'TIMEZONE_MINUTE'; KW_TIME_DIFF : 'TIME_DIFF'; KW_TIME_TRUNC : 'TIME_TRUNC'; KW_TINYINT : 'TINYINT'; KW_TO : 'TO'; KW_TRAILING : 'TRAILING'; KW_TRANSLATE : 'TRANSLATE'; KW_TRANSLATE_REGEX : 'TRANSLATE_REGEX'; KW_TRANSLATION : 'TRANSLATION'; KW_TREAT : 'TREAT'; KW_TRIGGER : 'TRIGGER'; KW_TRIM : 'TRIM'; KW_TRIM_ARRAY : 'TRIM_ARRAY'; KW_TRUE : 'TRUE'; KW_TRUNCATE : 'TRUNCATE'; KW_TRY_CAST : 'TRY_CAST'; KW_TUESDAY : 'TUESDAY'; KW_UESCAPE : 'UESCAPE'; KW_UNION : 'UNION'; KW_UNIQUE : 'UNIQUE'; KW_UNKNOWN : 'UNKNOWN'; KW_UNNEST : 'UNNEST'; KW_UNPIVOT : 'UNPIVOT'; KW_UPDATE : 'UPDATE'; KW_UPPER : 'UPPER'; KW_UPSERT : 'UPSERT'; KW_USE : 'USE'; KW_USER : 'USER'; KW_USING : 'USING'; KW_VALUE : 'VALUE'; KW_VALUES : 'VALUES'; KW_VALUE_OF : 'VALUE_OF'; KW_VARBINARY : 'VARBINARY'; KW_VARCHAR : 'VARCHAR'; KW_VARYING : 'VARYING'; KW_VAR_POP : 'VAR_POP'; KW_VAR_SAMP : 'VAR_SAMP'; KW_VERSIONING : 'VERSIONING'; KW_VIEWS : 'VIEWS'; KW_VIRTUAL : 'VIRTUAL'; KW_WATERMARK : 'WATERMARK'; KW_WATERMARKS : 'WATERMARKS'; KW_WEDNESDAY : 'WEDNESDAY'; KW_WEEKS : 'WEEKS'; KW_WHEN : 'WHEN'; KW_WHENEVER : 'WHENEVER'; KW_WHERE : 'WHERE'; KW_WIDTH_BUCKET : 'WIDTH_BUCKET'; KW_WINDOW : 'WINDOW'; KW_WITH : 'WITH'; KW_WITHIN : 'WITHIN'; KW_WITHOUT : 'WITHOUT'; KW_YEAR : 'YEAR'; /** * Non-Reserved Keywords * Keywords that are used in the syntax rules but do not exist in the above keyword list section. * Please keep the keyword in alphabetical order if new keyword is added. * New non-reserved keywords should also be added to the nonReservedKeywords rule in FlinkSqlParser.g4 file. */ KW_ADD : 'ADD'; KW_AFTER : 'AFTER'; KW_ASC : 'ASC'; KW_CASCADE : 'CASCADE'; KW_CATALOG : 'CATALOG'; KW_CENTURY : 'CENTURY'; KW_CONFIG : 'CONFIG'; KW_CONSTRAINTS : 'CONSTRAINTS'; KW_CUMULATE : 'CUMULATE'; KW_DATA : 'DATA'; KW_DATABASE : 'DATABASE'; KW_DAYS : 'DAYS'; KW_DECADE : 'DECADE'; KW_DESC : 'DESC'; KW_DESCRIPTOR : 'DESCRIPTOR'; KW_DIV : 'DIV'; KW_ENGINE : 'ENGINE'; KW_EPOCH : 'EPOCH'; KW_EXCLUDING : 'EXCLUDING'; KW_FILE : 'FILE'; KW_FIRST : 'FIRST'; KW_GENERATED : 'GENERATED'; KW_HOP : 'HOP'; KW_HOURS : 'HOURS'; KW_IGNORE : 'IGNORE'; KW_INCLUDING : 'INCLUDING'; KW_JAR : 'JAR'; KW_JARS : 'JARS'; KW_JAVA : 'JAVA'; KW_KEY : 'KEY'; KW_LAST : 'LAST'; KW_LOAD : 'LOAD'; KW_MAP : 'MAP'; KW_MICROSECOND : 'MICROSECOND'; KW_MILLENNIUM : 'MILLENNIUM'; KW_MILLISECOND : 'MILLISECOND'; KW_MINUTES : 'MINUTES'; KW_MONTHS : 'MONTHS'; KW_NANOSECOND : 'NANOSECOND'; KW_NULLS : 'NULLS'; KW_OPTIONS : 'OPTIONS'; KW_PAST : 'PAST'; KW_PLAN : 'PLAN'; KW_PRECEDING : 'PRECEDING'; KW_PYTHON : 'PYTHON'; KW_PYTHON_ARCHIVES : 'PYTHON_ARCHIVES'; KW_PYTHON_DEPENDENCIES : 'PYTHON_DEPENDENCIES'; KW_PYTHON_FILES : 'PYTHON_FILES'; KW_PYTHON_JAR : 'PYTHON_JAR'; KW_PYTHON_PARAMETER : 'PYTHON_PARAMETER'; KW_PYTHON_REQUIREMENTS : 'PYTHON_REQUIREMENTS'; KW_QUARTER : 'QUARTER'; KW_REMOVE : 'REMOVE'; KW_RESTRICT : 'RESTRICT'; KW_SECONDS : 'SECONDS'; KW_SESSION : 'SESSION'; KW_SETS : 'SETS'; KW_SIZE : 'SIZE'; KW_SLIDE : 'SLIDE'; KW_STEP : 'STEP'; KW_TEMPORARY : 'TEMPORARY'; KW_TIMECOL : 'TIMECOL'; KW_TUMBLE : 'TUMBLE'; KW_UNLOAD : 'UNLOAD'; KW_VIEW : 'VIEW'; KW_WEEK : 'WEEK'; KW_YEARS : 'YEARS'; KW_ZONE : 'ZONE'; // Operators. Comparation EQUAL_SYMBOL : '='; GREATER_SYMBOL : '>'; LESS_SYMBOL : '<'; EXCLAMATION_SYMBOL : '!'; // Operators. Bit BIT_NOT_OP : '~'; BIT_OR_OP : '|'; BIT_AND_OP : '&'; BIT_XOR_OP : '^'; // Constructors symbols DOT : '.'; LS_BRACKET : '['; RS_BRACKET : ']'; LR_BRACKET : '('; RR_BRACKET : ')'; LB_BRACKET : '{'; RB_BRACKET : '}'; COMMA : ','; SEMICOLON : ';'; AT_SIGN : '@'; SINGLE_QUOTE_SYMB : '\''; DOUBLE_QUOTE_SYMB : '"'; REVERSE_QUOTE_SYMB : '`'; COLON_SYMB : ':'; ASTERISK_SIGN : '*'; UNDERLINE_SIGN : '_'; HYPHEN_SIGN : '-'; ADD_SIGN : '+'; PERCENT_SIGN : '%'; DOUBLE_VERTICAL_SIGN : '||'; DOUBLE_HYPHEN_SIGN : '--'; SLASH_SIGN : '/'; QUESTION_MARK_SIGN : '?'; DOUBLE_RIGHT_ARROW : '=>'; STRING_LITERAL : DQUOTA_STRING | SQUOTA_STRING | BQUOTA_STRING; DIG_LITERAL : DEC_DIGIT+; REAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT+ | DEC_DIGIT+ '.' EXPONENT_NUM_PART | (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART) | DEC_DIGIT+ EXPONENT_NUM_PART; BIT_STRING : BIT_STRING_L; ID_LITERAL : ID_LITERAL_FRAG; fragment JAR_FILE_PARTTARN : '`' ( '\\' . | '``' | ~('`' | '\\'))* '`'; fragment EXPONENT_NUM_PART : 'E' [-+]? DEC_DIGIT+; fragment ID_LITERAL_FRAG : [A-Z_0-9]*? [A-Z_]+? [A-Z_0-9]*; fragment DEC_DIGIT : [0-9]; fragment DEC_LETTER : [A-Z]; fragment DQUOTA_STRING : '"' ( '\\' . | '""' | ~('"' | '\\'))* '"'; fragment SQUOTA_STRING : '\'' ('\\' . | '\'\'' | ~('\'' | '\\'))* '\''; fragment BIT_STRING_L : 'B' '\'' [01]+ '\''; fragment BQUOTA_STRING : '`' ( '\\' . | '``' | ~('`' | '\\'))* '`'; ================================================ FILE: superior-flink-parser/src/main/antlr4/io/github/melin/superior/parser/flink/antlr4/FlinkSqlParser.g4 ================================================ parser grammar FlinkSqlParser; options { tokenVocab=FlinkSqlLexer; } sqlStatements : singleStatement* EOF ; singleStatement : sqlStatement SEMICOLON? | emptyStatement ; sqlStatement : ddlStatement | dmlStatement | describeStatement | explainStatement | useStatement | showStatement | loadStatement | unloadStatement | setStatement | resetStatement | jarStatement | dtAddStatement ; emptyStatement : SEMICOLON ; ddlStatement : createTable | createDatabase | createView | createFunction | createCatalog | alterTable | alterView | alterDatabase | alterFunction | dropCatalog | dropTable | dropDatabase | dropView | dropFunction ; dmlStatement : queryStatement | insertStatement ; // some statement describeStatement : (KW_DESCRIBE | KW_DESC) tablePath ; explainStatement : KW_EXPLAIN (explainDetails | KW_PLAN KW_FOR)? ( dmlStatement | insertSimpleStatement | insertMulStatement ) ; explainDetails : explainDetail (COMMA explainDetail)* ; explainDetail : KW_CHANGELOG_MODE | KW_PLAN_ADVICE | KW_JSON_EXECUTION_PLAN | KW_ESTIMATED_COST ; useStatement : KW_USE KW_CATALOG catalogPath | KW_USE databasePath | useModuleStatement ; useModuleStatement : KW_USE KW_MODULES uid (COMMA uid)* ; showStatement : KW_SHOW (KW_CATALOGS | KW_DATABASES | KW_VIEWS | KW_JARS) | KW_SHOW KW_CURRENT (KW_CATALOG | KW_DATABASE) | KW_SHOW KW_TABLES (( KW_FROM | KW_IN) databasePath)? likePredicate? | KW_SHOW KW_COLUMNS ( KW_FROM | KW_IN) (viewPath | tablePath) likePredicate? | KW_SHOW KW_CREATE (KW_TABLE tablePath | KW_VIEW viewPath) | KW_SHOW KW_USER? KW_FUNCTIONS | KW_SHOW KW_FULL? KW_MODULES ; loadStatement : KW_LOAD KW_MODULE uid (KW_WITH tablePropertyList)? ; unloadStatement : KW_UNLOAD KW_MODULE uid ; setStatement : KW_SET (tableProperty)? ; resetStatement : KW_RESET tablePropertyKey? ; jarStatement : (KW_ADD | KW_REMOVE) KW_JAR jarFileName ; // 数栈平台自研的添加文件语法 dtAddStatement : KW_ADD KW_JAR KW_WITH dtFilePath (KW_AS uid)? | KW_ADD KW_FILE KW_WITH dtFilePath (KW_AS uid)? (KW_RENAME uid)? | KW_ADD ( KW_PYTHON_FILES | KW_PYTHON_REQUIREMENTS | KW_PYTHON_DEPENDENCIES | KW_PYTHON_JAR | KW_PYTHON_ARCHIVES ) KW_WITH dtFilePath KW_RENAME uid | KW_ADD KW_PYTHON_PARAMETER dtFilePath | KW_ADD KW_ENGINE KW_FILE KW_WITH dtFilePath KW_RENAME uid KW_KEY uid | KW_ADD KW_CONFIG KW_FILE KW_WITH dtFilePath KW_FOR uid KW_AS uid ; dtFilePath : (SLASH_SIGN? uid)+ ; // Create statements createTable : (simpleCreateTable | createTableAsSelect) ; simpleCreateTable : KW_CREATE KW_TEMPORARY? KW_TABLE ifNotExists? tablePathCreate LR_BRACKET columnOptionDefinition ( COMMA columnOptionDefinition )* (COMMA watermarkDefinition)? (COMMA tableConstraint)? (COMMA selfDefinitionClause)? RR_BRACKET ( KW_COMMENT comment=STRING_LITERAL )? partitionDefinition? withOption likeDefinition? ; /* * 详见 https://nightlies.apache.org/flink/flink-docs-release-1.16/docs/dev/table/sql/create/#as-select_statement * CTAS 不支持指定显示指定列,不支持创建分区表,临时表 */ createTableAsSelect : KW_CREATE KW_TABLE ifNotExists? tablePathCreate withOption (KW_AS queryStatement)? ; columnOptionDefinition : physicalColumnDefinition | metadataColumnDefinition | computedColumnDefinition ; physicalColumnDefinition : columnNameCreate columnType columnConstraint? (KW_COMMENT comment=STRING_LITERAL)? ; columnNameCreate : uid | expression ; columnName : uid ; columnNamePath : uid ; columnNameList : LR_BRACKET columnName (COMMA columnName)* RR_BRACKET ; columnType : colType=(KW_DATE | KW_BOOLEAN | KW_NULL) | colType=( KW_CHAR | KW_VARCHAR | KW_STRING | KW_BINARY | KW_VARBINARY | KW_BYTES | KW_TINYINT | KW_SMALLINT | KW_INT | KW_INTEGER | KW_BIGINT | KW_TIME | KW_TIMESTAMP_LTZ | KW_DATETIME ) lengthOneDimension? | colType=KW_TIMESTAMP lengthOneDimension? ((KW_WITHOUT | KW_WITH) KW_LOCAL? KW_TIME KW_ZONE)? | colType=(KW_DECIMAL | KW_DEC | KW_NUMERIC | KW_FLOAT | KW_DOUBLE) lengthTwoOptionalDimension? | colType=(KW_ARRAY | KW_MULTISET) lengthOneTypeDimension? | colType=KW_MAP mapTypeDimension? | colType=KW_ROW rowTypeDimension? | colType=KW_RAW lengthTwoStringDimension? ; lengthOneDimension : LR_BRACKET decimalLiteral RR_BRACKET ; lengthTwoOptionalDimension : LR_BRACKET decimalLiteral (COMMA decimalLiteral)? RR_BRACKET ; lengthTwoStringDimension : LR_BRACKET stringLiteral (COMMA stringLiteral)? RR_BRACKET ; lengthOneTypeDimension : LESS_SYMBOL columnType GREATER_SYMBOL ; mapTypeDimension : LESS_SYMBOL columnType (COMMA columnType) GREATER_SYMBOL ; rowTypeDimension : LESS_SYMBOL columnName columnType (COMMA columnName columnType)* GREATER_SYMBOL | LR_BRACKET columnName columnType (COMMA columnName columnType)* RR_BRACKET ; columnConstraint : (KW_CONSTRAINT constraintName)? KW_PRIMARY KW_KEY (KW_NOT KW_ENFORCED)? | KW_NOT? KW_NULL ; metadataColumnDefinition : columnNameCreate columnType KW_METADATA (KW_FROM metadataKey)? KW_VIRTUAL? ; metadataKey : STRING_LITERAL ; computedColumnDefinition : columnNameCreate KW_AS computedColumnExpression (KW_COMMENT comment=STRING_LITERAL)? ; // 计算表达式 computedColumnExpression : expression ; watermarkDefinition : KW_WATERMARK KW_FOR columnName KW_AS expression ; tableConstraint : (KW_CONSTRAINT constraintName)? KW_PRIMARY KW_KEY columnNameList KW_NOT KW_ENFORCED ; constraintName : identifier ; selfDefinitionClause // 数栈自定义语句 ‘PERIOD KW_FOR SYSTEM_TIME’ : KW_PERIOD KW_FOR KW_SYSTEM_TIME ; partitionDefinition : KW_PARTITIONED KW_BY transformList ; transformList : LR_BRACKET transform (COMMA transform)* RR_BRACKET ; transform : columnName # identityTransform | LR_BRACKET transformArgument (COMMA transformArgument)* RR_BRACKET # applyTransform ; transformArgument : qualifiedName | constant ; likeDefinition : KW_LIKE tablePath (LR_BRACKET likeOption* RR_BRACKET)? ; likeOption : ((KW_INCLUDING | KW_EXCLUDING) (KW_ALL | KW_CONSTRAINTS | KW_PARTITIONS)) | ((KW_INCLUDING | KW_EXCLUDING | KW_OVERWRITING) (KW_GENERATED | KW_OPTIONS | KW_WATERMARKS)) ; createCatalog : KW_CREATE KW_CATALOG catalogPathCreate withOption ; createDatabase : KW_CREATE KW_DATABASE ifNotExists? databasePathCreate (KW_COMMENT comment=STRING_LITERAL)? withOption ; createView : KW_CREATE KW_TEMPORARY? KW_VIEW ifNotExists? viewPathCreate columnNameList? ( KW_COMMENT comment=STRING_LITERAL )? KW_AS queryStatement ; createFunction : KW_CREATE (KW_TEMPORARY | KW_TEMPORARY KW_SYSTEM)? KW_FUNCTION ifNotExists? functionNameCreate KW_AS identifier ( KW_LANGUAGE (KW_JAVA | KW_SCALA | KW_PYTHON) )? usingClause? ; usingClause : KW_USING KW_JAR jarFileName (COMMA KW_JAR jarFileName)* ; jarFileName : STRING_LITERAL ; // Alter statements // Just for simple alter table statements, // it only includes rename, set key, add constraint, drop constraint, add unique alterTable : KW_ALTER KW_TABLE ifExists? tablePath ( renameDefinition | setKeyValueDefinition | addConstraint | dropConstraint | addUnique ) ; renameDefinition : KW_RENAME uid? KW_TO uid ; setKeyValueDefinition : KW_SET tablePropertyList ; addConstraint : KW_ADD KW_CONSTRAINT constraintName KW_PRIMARY KW_KEY columnNameList notForced? ; dropConstraint : KW_DROP KW_CONSTRAINT constraintName ; addUnique : KW_ADD KW_UNIQUE columnNameList ; notForced : KW_NOT KW_ENFORCED ; alterView : KW_ALTER KW_VIEW viewPath (renameDefinition | KW_AS queryStatement) ; alterDatabase : KW_ALTER KW_DATABASE databasePath setKeyValueDefinition ; alterFunction : KW_ALTER (KW_TEMPORARY | KW_TEMPORARY KW_SYSTEM)? KW_FUNCTION ifExists? functionName KW_AS identifier ( KW_LANGUAGE (KW_JAVA | KW_SCALA | KW_PYTHON) )? // TODO ; // Drop statements dropCatalog : KW_DROP KW_CATALOG ifExists? catalogPath ; dropTable : KW_DROP KW_TEMPORARY? KW_TABLE ifExists? tablePath ; dropDatabase : KW_DROP KW_DATABASE ifExists? databasePath dropType=(KW_RESTRICT | KW_CASCADE)? ; dropView : KW_DROP KW_TEMPORARY? KW_VIEW ifExists? viewPath ; dropFunction : KW_DROP (KW_TEMPORARY | KW_TEMPORARY KW_SYSTEM)? KW_FUNCTION ifExists? functionName ; // Insert statements insertStatement : (KW_EXECUTE? insertSimpleStatement) | insertMulStatementCompatibility | (KW_EXECUTE insertMulStatement) ; insertSimpleStatement : KW_INSERT (KW_INTO | KW_OVERWRITE) tablePath ( insertPartitionDefinition? columnNameList? queryStatement | valuesDefinition ) ; insertPartitionDefinition : KW_PARTITION tablePropertyList ; valuesDefinition : KW_VALUES valuesRowDefinition (COMMA valuesRowDefinition)* ; valuesRowDefinition : LR_BRACKET valueDefinition (COMMA valueDefinition)* RR_BRACKET ; valueDefinition : constant | functionCallExpression ; insertMulStatementCompatibility : KW_BEGIN KW_STATEMENT KW_SET SEMICOLON (insertSimpleStatement SEMICOLON)+ KW_END ; insertMulStatement : KW_STATEMENT KW_SET KW_BEGIN (insertSimpleStatement SEMICOLON)+ KW_END ; // Select statements queryStatement : valuesClause | withClause queryStatement | LR_BRACKET queryStatement RR_BRACKET | left=queryStatement operator=(KW_INTERSECT | KW_UNION | KW_EXCEPT) KW_ALL? right=queryStatement orderByClause? limitClause? | selectClause orderByClause? limitClause? | selectStatement orderByClause? limitClause? ; valuesClause : KW_VALUES expression (COMMA expression)* ; withClause : KW_WITH withItem (COMMA withItem)* ; withItem : withItemName (LR_BRACKET columnName (COMMA columnName)* RR_BRACKET)? KW_AS LR_BRACKET queryStatement RR_BRACKET ; withItemName : identifier ; selectStatement : selectClause fromClause? whereClause? groupByClause? havingClause? windowClause? | selectClause fromClause matchRecognizeClause ; selectClause : KW_SELECT setQuantifier? ( ASTERISK_SIGN | projectItemDefinition (COMMA projectItemDefinition)* ) ; projectItemDefinition : overWindowItem | expression (KW_AS? columnName)? | columnName (KW_AS? expression)? ; overWindowItem : primaryExpression KW_OVER windowSpec KW_AS identifier | primaryExpression KW_OVER errorCapturingIdentifier KW_AS identifier ; fromClause : KW_FROM tableExpression ; tableExpression : tableReference (COMMA tableReference)* | tableExpression KW_NATURAL? (KW_LEFT | KW_RIGHT | KW_FULL | KW_INNER)? KW_OUTER? KW_JOIN tableExpression joinCondition? | tableExpression KW_CROSS KW_JOIN tableExpression | inlineDataValueClause | windowTVFClause ; tableReference : tablePrimary tableAlias? ; tablePrimary : KW_TABLE? tablePath systemTimePeriod? | viewPath systemTimePeriod? | KW_LATERAL KW_TABLE LR_BRACKET functionCallExpression RR_BRACKET | KW_LATERAL? LR_BRACKET queryStatement RR_BRACKET | KW_UNNEST LR_BRACKET expression RR_BRACKET ; systemTimePeriod : KW_FOR KW_SYSTEM_TIME KW_AS KW_OF dateTimeExpression ; dateTimeExpression : expression ; inlineDataValueClause : LR_BRACKET valuesDefinition RR_BRACKET tableAlias ; windowTVFClause : KW_TABLE LR_BRACKET windowTVFExpression RR_BRACKET ; windowTVFExpression : windowTVFName LR_BRACKET windowTVFParam (COMMA windowTVFParam)* RR_BRACKET ; windowTVFName : KW_TUMBLE | KW_HOP | KW_CUMULATE ; windowTVFParam : KW_TABLE timeAttrColumn | columnDescriptor | timeIntervalExpression | KW_DATA DOUBLE_RIGHT_ARROW KW_TABLE timeAttrColumn | KW_TIMECOL DOUBLE_RIGHT_ARROW columnDescriptor | timeIntervalParamName DOUBLE_RIGHT_ARROW timeIntervalExpression ; timeIntervalParamName : KW_DATA | KW_TIMECOL | KW_SIZE | KW_OFFSET | KW_STEP | KW_SLIDE ; columnDescriptor : KW_DESCRIPTOR LR_BRACKET columnName RR_BRACKET ; joinCondition : KW_ON booleanExpression | KW_USING columnNameList ; whereClause : KW_WHERE booleanExpression ; groupByClause : KW_GROUP KW_BY groupItemDefinition (COMMA groupItemDefinition)* ; groupItemDefinition : columnName | groupWindowFunction | LR_BRACKET RR_BRACKET | LR_BRACKET expression (COMMA expression)* RR_BRACKET | groupingSetsNotationName LR_BRACKET expression (COMMA expression)* RR_BRACKET | groupingSets LR_BRACKET groupItemDefinition (COMMA groupItemDefinition)* RR_BRACKET | expression ; groupingSets : KW_GROUPING KW_SETS ; groupingSetsNotationName : KW_CUBE | KW_ROLLUP ; groupWindowFunction : groupWindowFunctionName LR_BRACKET timeAttrColumn COMMA timeIntervalExpression RR_BRACKET ; groupWindowFunctionName : KW_TUMBLE | KW_HOP | KW_SESSION ; timeAttrColumn : uid ; havingClause : KW_HAVING booleanExpression ; windowClause : KW_WINDOW namedWindow (COMMA namedWindow)* ; namedWindow : name=errorCapturingIdentifier KW_AS windowSpec ; windowSpec : name=errorCapturingIdentifier? LR_BRACKET partitionByClause? orderByClause? windowFrame? RR_BRACKET ; matchRecognizeClause : KW_MATCH_RECOGNIZE LR_BRACKET partitionByClause? orderByClause? measuresClause? outputMode? afterMatchStrategy? patternDefinition? patternVariablesDefinition RR_BRACKET (KW_AS? identifier)? ; orderByClause : KW_ORDER KW_BY orderItemDefinition (COMMA orderItemDefinition)* ; orderItemDefinition : columnName ordering=(KW_ASC | KW_DESC)? (KW_NULLS nullOrder=(KW_LAST | KW_FIRST))? ; limitClause : KW_LIMIT (KW_ALL | limit=expression) ; partitionByClause : KW_PARTITION KW_BY (columnName | primaryExpression) (COMMA (columnName | primaryExpression))* ; quantifiers : (ASTERISK_SIGN) | (ADD_SIGN) | (QUESTION_MARK_SIGN) | (LB_BRACKET DIG_LITERAL COMMA DIG_LITERAL RB_BRACKET) | (LB_BRACKET DIG_LITERAL COMMA RB_BRACKET) | (LB_BRACKET COMMA DIG_LITERAL RB_BRACKET) ; measuresClause : KW_MEASURES projectItemDefinition (COMMA projectItemDefinition)* ; patternDefinition : KW_PATTERN LR_BRACKET patternVariable+ RR_BRACKET withinClause? ; patternVariable : unquotedIdentifier quantifiers? ; outputMode : KW_ALL KW_ROWS KW_PER KW_MATCH | KW_ONE KW_ROW KW_PER KW_MATCH ; afterMatchStrategy : KW_AFTER KW_MATCH KW_SKIP KW_PAST KW_LAST KW_ROW | KW_AFTER KW_MATCH KW_SKIP KW_TO KW_NEXT KW_ROW | KW_AFTER KW_MATCH KW_SKIP KW_TO KW_LAST unquotedIdentifier | KW_AFTER KW_MATCH KW_SKIP KW_TO KW_FIRST unquotedIdentifier ; patternVariablesDefinition : KW_DEFINE projectItemDefinition (COMMA projectItemDefinition)* ; windowFrame : KW_RANGE KW_BETWEEN timeIntervalExpression frameBound | KW_ROWS KW_BETWEEN DIG_LITERAL frameBound ; frameBound : KW_PRECEDING KW_AND KW_CURRENT KW_ROW ; withinClause : KW_WITHIN timeIntervalExpression ; // expression expression : booleanExpression ; booleanExpression : KW_NOT booleanExpression # logicalNot | KW_EXISTS LR_BRACKET queryStatement RR_BRACKET # exists | valueExpression predicate? # predicated | left=booleanExpression operator=KW_AND right=booleanExpression # logicalBinary | left=booleanExpression operator=KW_OR right=booleanExpression # logicalBinary | booleanExpression KW_IS KW_NOT? kind=(KW_TRUE | KW_FALSE | KW_UNKNOWN | KW_NULL) # logicalNested ; predicate : KW_NOT? kind=KW_BETWEEN (KW_ASYMMETRIC | KW_SYMMETRIC)? lower=valueExpression KW_AND upper=valueExpression | KW_NOT? kind=KW_IN LR_BRACKET expression (COMMA expression)* RR_BRACKET | KW_NOT? kind=KW_IN LR_BRACKET queryStatement RR_BRACKET | kind=KW_EXISTS LR_BRACKET queryStatement RR_BRACKET | KW_NOT? kind=KW_RLIKE pattern=valueExpression | likePredicate | KW_IS KW_NOT? kind=(KW_TRUE | KW_FALSE | KW_UNKNOWN | KW_NULL) | KW_IS KW_NOT? kind=KW_DISTINCT KW_FROM right=valueExpression | KW_NOT? kind=KW_SIMILAR KW_TO right=valueExpression (KW_ESCAPE stringLiteral)? | KW_IS KW_JSON (KW_VALUE | KW_ARRAY | identifier)? ; jsonFunctionBranch : KW_NULL | KW_EMPTY KW_ARRAY | KW_EMPTY uid | KW_TRUE | KW_FALSE | KW_UNKNOWN ; likePredicate : KW_NOT? kind=KW_LIKE quantifier=(KW_ANY | KW_ALL) ( LR_BRACKET RR_BRACKET | LR_BRACKET expression (COMMA expression)* RR_BRACKET ) | KW_NOT? kind=KW_LIKE pattern=valueExpression (KW_ESCAPE stringLiteral)? ; valueExpression : primaryExpression # valueExpressionDefault | operator=(HYPHEN_SIGN | ADD_SIGN | BIT_NOT_OP) valueExpression # arithmeticUnary | left=valueExpression operator=(ASTERISK_SIGN | SLASH_SIGN | PERCENT_SIGN | KW_DIV) right=valueExpression # arithmeticBinary | left=valueExpression operator=(ADD_SIGN | HYPHEN_SIGN | DOUBLE_VERTICAL_SIGN) right=valueExpression # arithmeticBinary | left=valueExpression operator=BIT_AND_OP right=valueExpression # arithmeticBinary | left=valueExpression operator=BIT_XOR_OP right=valueExpression # arithmeticBinary | left=valueExpression operator=BIT_OR_OP right=valueExpression # arithmeticBinary | left=valueExpression comparisonOperator right=valueExpression # comparison ; functionCallExpression : reservedKeywordsNoParamsUsedAsFuncName | functionNameAndParams | functionNameWithParams LR_BRACKET (setQuantifier? functionParam (COMMA functionParam)*)? RR_BRACKET ; primaryExpression : KW_CASE whenClause+ (KW_ELSE elseExpression=expression)? KW_END # searchedCase | KW_CASE value=expression whenClause+ (KW_ELSE elseExpression=expression)? KW_END # simpleCase | KW_CAST LR_BRACKET expression KW_AS columnType RR_BRACKET # cast // | STRUCT LR_BRACKET (argument+=namedExpression (COMMA argument+=namedExpression)*)? RR_BRACKET #struct | KW_FIRST LR_BRACKET expression (KW_IGNORE KW_NULLS)? RR_BRACKET # first | KW_LAST LR_BRACKET expression (KW_IGNORE KW_NULLS)? RR_BRACKET # last | KW_POSITION LR_BRACKET substr=valueExpression KW_IN str=valueExpression RR_BRACKET # position | constant # constantDefault | ASTERISK_SIGN # star | uid DOT ASTERISK_SIGN # star // | LR_BRACKET namedExpression (COMMA namedExpression)+ RR_BRACKET #rowConstructor | LR_BRACKET queryStatement RR_BRACKET # subqueryExpression | functionCallExpression # functionCall // | identifier '->' expression #lambda // | '(' identifier (',' identifier)+ ')' '->' expression #lambda | value=primaryExpression LS_BRACKET index=valueExpression RS_BRACKET # subscript | columnNamePath # columnReference | dereferenceDefinition # dereference | LR_BRACKET expression RR_BRACKET # parenthesizedExpression // | EXTRACT LR_BRACKET field=identifier KW_FROM source=valueExpression RR_BRACKET #extract // | (SUBSTR | SUBSTRING) LR_BRACKET str=valueExpression (KW_FROM | COMMA) pos=valueExpression // ((KW_FOR | COMMA) len=valueExpression)? RR_BRACKET #substring // | TRIM LR_BRACKET trimOption=(BOTH | LEADING | TRAILING)? (trimStr=valueExpression)? // KW_FROM srcStr=valueExpression RR_BRACKET #trim // | OVERLAY LR_BRACKET input=valueExpression PLACING replace=valueExpression // KW_FROM position=valueExpression (KW_FOR length=valueExpression)? RR_BRACKET #overlay ; functionNameCreate : uid ; functionName : reservedKeywordsUsedAsFuncName | reservedKeywordsNoParamsUsedAsFuncName | reservedKeywordsFollowParamsUsedAsFuncName | uid ; /** * Built-in function name that is following with params directly without parentheses * Reference Link:https://nightlies.apache.org/flink/flink-docs-release-1.16/zh/docs/dev/table/functions/systemfunctions/#%E6%97%B6%E9%97%B4%E5%87%BD%E6%95%B0 */ functionNameAndParams : reservedKeywordsFollowParamsUsedAsFuncName STRING_LITERAL | timeIntervalExpression ; /** * Function name that is need to follow with parentheses and params */ functionNameWithParams : reservedKeywordsUsedAsFuncName | uid ; functionParam : reservedKeywordsUsedAsFuncParam | timeIntervalUnit | timePointUnit | expression | jsonValueParams | jsonQueryParams | jsonObjectParams | jsonArrayParams ; jsonValueParams : columnNamePath (uid columnType)? ( (uid | KW_NULL | KW_DEFAULT valueExpression) KW_ON KW_EMPTY )? ((uid | KW_NULL | KW_DEFAULT valueExpression) KW_ON uid)? ; jsonQueryParams : columnNamePath ((KW_WITHOUT | KW_WITH uid?) KW_ARRAY? uid)? ( jsonFunctionBranch KW_ON KW_EMPTY )? (jsonFunctionBranch KW_ON uid)? ; // JSON 函数只能在 JSON_OBJECT 函数中使用 jsonObjectParams : ( KW_KEY? columnNamePath KW_VALUE? ( valueExpression | KW_JSON LR_BRACKET (valueExpression)* RR_BRACKET ) )* ((KW_NULL | uid) KW_ON KW_NULL)? ; jsonArrayParams : valueExpression* ((KW_NULL | uid) KW_ON KW_NULL)? ; dereferenceDefinition : uid ; // base common correlationName : identifier ; qualifiedName : identifier | dereferenceDefinition ; timeIntervalExpression : KW_INTERVAL (errorCapturingMultiUnitsInterval | errorCapturingUnitToUnitInterval)? ; errorCapturingMultiUnitsInterval : multiUnitsInterval unitToUnitInterval? ; multiUnitsInterval : (intervalValue timeIntervalUnit)+ ; errorCapturingUnitToUnitInterval : body=unitToUnitInterval (error1=multiUnitsInterval | error2=unitToUnitInterval)? ; unitToUnitInterval : value=intervalValue from=timeIntervalUnit KW_TO to=timeIntervalUnit ; intervalValue : (ADD_SIGN | HYPHEN_SIGN)? (DIG_LITERAL | REAL_LITERAL) | STRING_LITERAL ; tableAlias : KW_AS? alias=identifier identifierList? ; errorCapturingIdentifier : identifier errorCapturingIdentifierExtra ; errorCapturingIdentifierExtra : (KW_MINUS identifier)+ # errorIdent | # realIdent ; identifierList : LR_BRACKET identifierSeq RR_BRACKET ; identifierSeq : identifier (COMMA identifier)* ; identifier : unquotedIdentifier # unquotedIdentifierAlternative | quotedIdentifier # quotedIdentifierAlternative | nonReservedKeywords # nonReservedKeywordsAlternative ; unquotedIdentifier : DIG_LITERAL | ID_LITERAL ; quotedIdentifier : STRING_LITERAL ; whenClause : KW_WHEN condition=expression KW_THEN result=expression ; catalogPath : identifier ; catalogPathCreate : identifier ; databasePath : identifier (DOT identifier)? ; databasePathCreate : identifier (DOT identifier)? ; tablePathCreate : identifier (DOT identifier)? | identifier DOT identifier (DOT identifier)? ; tablePath : identifier (DOT identifier)? | identifier DOT identifier (DOT identifier)? ; viewPath : identifier (DOT identifier)? | identifier DOT identifier (DOT identifier)? ; viewPathCreate : identifier (DOT identifier)? | identifier DOT identifier (DOT identifier)? ; uid : identifier (DOT identifier)*? ; withOption : KW_WITH tablePropertyList ; ifNotExists : KW_IF KW_NOT KW_EXISTS ; ifExists : KW_IF KW_EXISTS ; tablePropertyList : LR_BRACKET tableProperty (COMMA tableProperty)* RR_BRACKET ; tableProperty : key=tablePropertyKey (EQUAL_SYMBOL? value=tablePropertyValue)? ; tablePropertyKey : identifier | dereferenceDefinition | STRING_LITERAL ; tablePropertyValue : DIG_LITERAL | REAL_LITERAL | booleanLiteral | STRING_LITERAL ; logicalOperator : KW_AND | BIT_AND_OP BIT_AND_OP | KW_OR | BIT_OR_OP BIT_OR_OP ; comparisonOperator : EQUAL_SYMBOL | GREATER_SYMBOL | LESS_SYMBOL | LESS_SYMBOL EQUAL_SYMBOL | GREATER_SYMBOL EQUAL_SYMBOL | LESS_SYMBOL GREATER_SYMBOL | EXCLAMATION_SYMBOL EQUAL_SYMBOL | LESS_SYMBOL EQUAL_SYMBOL GREATER_SYMBOL ; bitOperator : LESS_SYMBOL LESS_SYMBOL | GREATER_SYMBOL GREATER_SYMBOL | BIT_AND_OP | BIT_XOR_OP | BIT_OR_OP ; mathOperator : ASTERISK_SIGN | SLASH_SIGN | PERCENT_SIGN | KW_DIV | ADD_SIGN | HYPHEN_SIGN | DOUBLE_HYPHEN_SIGN ; unaryOperator : EXCLAMATION_SYMBOL | BIT_NOT_OP | ADD_SIGN | HYPHEN_SIGN | KW_NOT ; constant : timeIntervalExpression | timePointLiteral | stringLiteral // 引号包含的字符串 | HYPHEN_SIGN? decimalLiteral // 正/负整数 | booleanLiteral // 布尔值 | REAL_LITERAL // 小数 | BIT_STRING | KW_NOT? KW_NULL // 空 | 非空 ; timePointLiteral : timePointUnit stringLiteral ; stringLiteral : STRING_LITERAL ; decimalLiteral : DIG_LITERAL ; booleanLiteral : KW_TRUE | KW_FALSE ; setQuantifier : KW_DISTINCT | KW_ALL ; timePointUnit : KW_YEAR | KW_QUARTER | KW_MONTH | KW_WEEK | KW_DAY | KW_HOUR | KW_MINUTE | KW_SECOND | KW_MILLISECOND | KW_MICROSECOND ; timeIntervalUnit : KW_MILLENNIUM | KW_CENTURY | KW_DECADE | KW_YEAR | KW_YEARS | KW_QUARTER | KW_MONTH | KW_MONTHS | KW_WEEK | KW_WEEKS | KW_DAY | KW_DAYS | KW_HOUR | KW_HOURS | KW_MINUTE | KW_MINUTES | KW_SECOND | KW_SECONDS | KW_MILLISECOND | KW_MICROSECOND | KW_NANOSECOND | KW_EPOCH ; reservedKeywordsUsedAsFuncParam : KW_ARRAY | KW_ALL | KW_BOTH | KW_CURRENT_TIMESTAMP | KW_CURRENT_DATE | KW_CURRENT_TIME | KW_LOCALTIME | KW_LOCALTIMESTAMP | KW_DISTINCT | KW_LEADING | KW_TRAILING | KW_VALUE | ASTERISK_SIGN ; /** * Built-in function name without parentheses and params */ reservedKeywordsNoParamsUsedAsFuncName : KW_LOCALTIME | KW_LOCALTIMESTAMP | KW_CURRENT_TIME | KW_CURRENT_DATE | KW_CURRENT_TIMESTAMP ; reservedKeywordsFollowParamsUsedAsFuncName : KW_DATE | KW_TIME | KW_TIMESTAMP ; reservedKeywordsUsedAsFuncName : KW_ABS | KW_ARRAY | KW_AVG | KW_CARDINALITY | KW_CAST | KW_CEIL | KW_CEILING | KW_COALESCE | KW_COLLECT | KW_COUNT | KW_CUME_DIST | KW_DAYOFWEEK | KW_DAYOFYEAR | KW_DENSE_RANK | KW_ELEMENT | KW_EXP | KW_EXTRACT | KW_FIRST_VALUE | KW_FLOOR | KW_GROUPING | KW_HOUR | KW_IF | KW_LAG | KW_LAST_VALUE | KW_LEAD | KW_LEFT | KW_LN | KW_LOWER | KW_MAP | KW_MAX | KW_MIN | KW_MINUTE | KW_MOD | KW_MONTH | KW_NULLIF | KW_NTILE | KW_OVERLAY | KW_PERCENT_RANK | KW_POSITION | KW_POWER | KW_QUARTER | KW_ROW | KW_ROWS | KW_ROW_NUMBER | KW_RANK | KW_RIGHT | KW_SECOND | KW_STDDEV_POP | KW_STDDEV_SAMP | KW_SUBSTRING | KW_SUM | KW_TIMESTAMP_DIFF | KW_TRIM | KW_TRUNCATE | KW_TRY_CAST | KW_UPPER | KW_VAR_POP | KW_VAR_SAMP | KW_WEEK | KW_YEAR | KW_JSON_VALUE | KW_JSON_EXISTS | KW_JSON_QUERY | KW_JSON_OBJECT | KW_JSON_OBJECTAGG | KW_JSON_ARRAY | KW_JSON_ARRAYAGG ; nonReservedKeywords : KW_ADD | KW_AFTER | KW_ASC | KW_CASCADE | KW_CATALOG | KW_CENTURY | KW_CONFIG | KW_CONSTRAINTS | KW_CUMULATE | KW_DATA | KW_DATABASE | KW_DAYS | KW_DECADE | KW_DESC | KW_DESCRIPTOR | KW_DIV | KW_ENGINE | KW_EPOCH | KW_EXCLUDING | KW_FILE | KW_FIRST | KW_GENERATED | KW_HOP | KW_HOURS | KW_IGNORE | KW_INCLUDING | KW_JAR | KW_JARS | KW_JAVA | KW_KEY | KW_LAST | KW_LOAD | KW_MAP | KW_MICROSECOND | KW_MILLENNIUM | KW_MILLISECOND | KW_MINUTES | KW_MONTHS | KW_NANOSECOND | KW_NULLS | KW_OPTIONS | KW_PAST | KW_PLAN | KW_PRECEDING | KW_PYTHON | KW_PYTHON_ARCHIVES | KW_PYTHON_DEPENDENCIES | KW_PYTHON_FILES | KW_PYTHON_JAR | KW_PYTHON_PARAMETER | KW_PYTHON_REQUIREMENTS | KW_QUARTER | KW_REMOVE | KW_RESTRICT | KW_SECONDS | KW_SESSION | KW_SETS | KW_SIZE | KW_SLIDE | KW_STEP | KW_TEMPORARY | KW_TIMECOL | KW_TUMBLE | KW_UNLOAD | KW_VIEW | KW_WEEK | KW_YEARS | KW_ZONE ; ================================================ FILE: superior-flink-parser/src/main/kotlin/io/github/melin/superior/parser/flink/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.flink import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(FlinkSqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: FlinkSqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(FlinkSqlParser._ATN)) } } ================================================ FILE: superior-flink-parser/src/main/kotlin/io/github/melin/superior/parser/flink/FlinkSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.flink import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.* import io.github.melin.superior.common.relational.create.CreateCatalog import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.dml.InsertMode import io.github.melin.superior.common.relational.dml.InsertMultiTable import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.drop.DropCatalog import io.github.melin.superior.common.relational.table.ColumnDefType import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.ComputedColumnDefinitionContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.MetadataColumnDefinitionContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.PhysicalColumnDefinitionContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.TablePropertyContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.TablePropertyListContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParser.UidContext import io.github.melin.superior.parser.flink.antlr4.FlinkSqlParserBaseVisitor import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ class FlinkSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : FlinkSqlParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var currentAlterActionType: AlterActionType = AlterActionType.UNKOWN private var multiInsertToken: String? = null private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() private var functionNames: HashSet = hashSetOf() private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitSqlStatements(ctx: FlinkSqlParser.SqlStatementsContext): Statement? { ctx.singleStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSingleStatement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() functionNames = hashSetOf() } override fun visitSqlStatement(ctx: FlinkSqlParser.SqlStatementContext): Statement? { val statement = super.visitSqlStatement(ctx) if (statement == null) { val startToken = StringUtils.lowerCase(ctx.getStart().text) if ("desc".equals(startToken) || "describe".equals(startToken)) { return DefaultStatement(StatementType.DESC) } else { val sql = source(ctx) throw SQLParserException("不支持的SQL: " + sql) } } return statement } override fun visitSimpleCreateTable(ctx: FlinkSqlParser.SimpleCreateTableContext): Statement { val tableId = parseTable(ctx.tablePathCreate().text) val comment: String? = if (ctx.comment != null) ctx.comment.text else null val properties = parseTableOptions(ctx.withOption().tablePropertyList()) val ifNotExists: Boolean = if (ctx.ifNotExists() != null) true else false val primayKeys = if (ctx.tableConstraint() != null) { ctx.tableConstraint().columnNameList().columnName().map { col -> col.uid().text } } else { listOf() } val columnRels = ctx.columnOptionDefinition().map { val column = it.getChild(0) if (column is PhysicalColumnDefinitionContext) { val colName = column.columnNameCreate().text val dataType = column.columnType().text val primaryKey = if (column.columnConstraint() != null) true else primayKeys.contains(colName) val colComment: String? = if (column.comment != null) column.comment.text else null ColumnRel(colName, dataType, colComment, primaryKey, ColumnDefType.PHYSICAL) } else if (column is MetadataColumnDefinitionContext) { val colName = column.columnNameCreate().text val dataType = column.columnType().text var metadataKey: String? = null if (column.metadataKey() != null) { metadataKey = CommonUtils.cleanQuote(column.metadataKey().text) } val columnRel = ColumnRel(colName, dataType, null, ColumnDefType.METADATA) columnRel.metadataKey = metadataKey columnRel } else { val computedColumn = column as ComputedColumnDefinitionContext val colName = computedColumn.computedColumnExpression().text val colComment: String? = if (computedColumn.comment != null) computedColumn.comment.text else null val computedExpr = source(computedColumn.computedColumnExpression().expression()) val columnRel = ColumnRel(colName, null, colComment, ColumnDefType.COMPUTED) columnRel.computedExpr = computedExpr columnRel } } return CreateTable(tableId, TableType.FLINK, comment, columnRels, ifNotExists, properties) } override fun visitCreateTableAsSelect(ctx: FlinkSqlParser.CreateTableAsSelectContext): Statement { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val tableId = parseTable(ctx.tablePathCreate().text) val properties = parseTableOptions(ctx.withOption().tablePropertyList()) val ifNotExists: Boolean = if (ctx.ifNotExists() != null) true else false val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt return CreateTableAsSelect(tableId, queryStmt, null, ifNotExists, properties) } override fun visitCreateView(ctx: FlinkSqlParser.CreateViewContext): Statement { currentOptType = StatementType.CREATE_VIEW val tableId = parseTable(ctx.viewPathCreate().text) val comment: String? = if (ctx.comment != null) ctx.comment.text else null val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt val ifNotExists: Boolean = if (ctx.ifNotExists() != null) true else false var columnNameList: List? = null if (ctx.columnNameList() != null) { columnNameList = ctx.columnNameList().columnName().map { ColumnRel(CommonUtils.cleanQuote(it.uid().text)) } } return CreateView(tableId, queryStmt, comment, ifNotExists, columnNameList) } override fun visitInsertStatement(ctx: FlinkSqlParser.InsertStatementContext): Statement { if (ctx.insertSimpleStatement() != null) { return this.insertSimpleStatement(ctx.insertSimpleStatement()) } else if (ctx.insertMulStatementCompatibility() != null) { val insertTables = ctx.insertMulStatementCompatibility().insertSimpleStatement().map { insertStmt -> this.insertSimpleStatement(insertStmt) } return InsertMultiTable(insertTables) } else if (ctx.insertMulStatement() != null) { val insertTables = ctx.insertMulStatement().insertSimpleStatement().map { insertStmt -> this.insertSimpleStatement(insertStmt) } return InsertMultiTable(insertTables) } return super.visitInsertStatement(ctx) } private fun insertSimpleStatement(ctx: FlinkSqlParser.InsertSimpleStatementContext): InsertTable { currentOptType = StatementType.INSERT val tableId = parseTable(ctx.tablePath().text) val insertMode = if (ctx.KW_INTO() != null) InsertMode.INTO else InsertMode.OVERWRITE var columnNameList: List? = null if (ctx.columnNameList() != null) { columnNameList = ctx.columnNameList().columnName().map { ColumnRel(CommonUtils.cleanQuote(it.uid().text)) } } var queryStmt = QueryStmt() if (ctx.queryStatement() != null) { queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt } val insertTable = InsertTable(insertMode, queryStmt, tableId, columnNameList) insertTable.outputTables.add(tableId) var sql = source(ctx) insertTable.setSql(sql) return insertTable } override fun visitQueryStatement(ctx: FlinkSqlParser.QueryStatementContext): Statement { if (currentOptType == StatementType.UNKOWN) { currentOptType = StatementType.SELECT } super.visitQueryStatement(ctx) return QueryStmt(inputTables, limit, offset) } override fun visitJarStatement(ctx: FlinkSqlParser.JarStatementContext): Statement { val jarFileName = CommonUtils.cleanQuote(ctx.jarFileName().text) if (ctx.KW_ADD() != null) { return AddResourceStatement(jarFileName, "jar") } else { return RemoveResourceStatement(jarFileName, "jar") } } override fun visitCreateCatalog(ctx: FlinkSqlParser.CreateCatalogContext): Statement { val catalogName: String = CommonUtils.cleanQuote(ctx.catalogPathCreate().text) val properties = parseTableOptions(ctx.withOption().tablePropertyList()) return CreateCatalog(catalogName, properties) } override fun visitDropCatalog(ctx: FlinkSqlParser.DropCatalogContext): Statement { val catalogName: String = CommonUtils.cleanQuote(ctx.catalogPath().text) return DropCatalog(catalogName) } override fun visitExplainStatement(ctx: FlinkSqlParser.ExplainStatementContext?): Statement { return DefaultStatement(StatementType.EXPLAIN) } override fun visitUseStatement(ctx: FlinkSqlParser.UseStatementContext): Statement { val catalogName: String = CommonUtils.cleanQuote(ctx.catalogPath().text) return UseCatalog(catalogName) } override fun visitWindowTVFParam(ctx: FlinkSqlParser.WindowTVFParamContext): Statement? { if (ctx.timeAttrColumn() != null) { val tableId = parseTable(ctx.timeAttrColumn().uid().text) inputTables.add(tableId) } return null } override fun visitTablePath(ctx: FlinkSqlParser.TablePathContext): Statement? { if ( StatementType.SELECT == currentOptType || StatementType.INSERT == currentOptType || StatementType.UPDATE == currentOptType || StatementType.DELETE == currentOptType || StatementType.CREATE_VIEW == currentOptType || StatementType.CREATE_TABLE_AS_SELECT == currentOptType ) { val tableId = parseTable(ctx.text) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } override fun visitWithItem(ctx: FlinkSqlParser.WithItemContext): Statement? { val tableId = TableId(ctx.withItemName().text) cteTempTables.add(tableId) super.visitWithItem(ctx) return null } override fun visitSetStatement(ctx: FlinkSqlParser.SetStatementContext): Statement { val tableProperty = ctx.tableProperty() var key = tableProperty.tablePropertyKey().text var value = tableProperty.tablePropertyValue().text key = CommonUtils.cleanQuote(key) value = CommonUtils.cleanQuote(value) return SetStatement(key, value) } override fun visitLimitClause(ctx: FlinkSqlParser.LimitClauseContext): Statement? { if (ctx.limit != null) { limit = ctx.limit.text.toInt() } return super.visitLimitClause(ctx) } private fun parseTable(path: String): TableId { val path = CommonUtils.cleanQuote(path) val items = StringUtils.split(path, ".") if (items.size == 3) { val catalog = CommonUtils.cleanQuote(items.get(0)) val schema = CommonUtils.cleanQuote(items.get(1)) val tableName = CommonUtils.cleanQuote(items.get(2)) return TableId(catalog, schema, tableName) } else if (items.size == 2) { val schema = CommonUtils.cleanQuote(items.get(0)) val tableName = CommonUtils.cleanQuote(items.get(1)) return TableId(schema, tableName) } else if (items.size == 1) { val tableName = CommonUtils.cleanQuote(items.get(0)) return TableId(tableName) } else { throw SQLParserException("parse multipart error: " + path) } } fun parseDatabase(uid: UidContext): Pair { val nodes = uid.identifier() if (nodes.size == 2) { val database = CommonUtils.cleanQuote(nodes.get(0).text) val schema = CommonUtils.cleanQuote(nodes.get(1).text) return Pair(database, schema) } else if (nodes.size == 1) { val schema = CommonUtils.cleanQuote(nodes.get(0).text) return Pair(null, schema) } else { throw SQLParserException("parse multipart error: " + nodes.size) } } private fun parseTableOptions(ctx: TablePropertyListContext): Map { val properties = HashMap() ctx.tableProperty().forEach { item -> val property = item as TablePropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } return properties } } ================================================ FILE: superior-flink-parser/src/main/kotlin/io/github/melin/superior/parser/flink/FlinkSqlHelper.kt ================================================ package io.github.melin.superior.parser.flink import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.flink.antlr4.* import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object FlinkSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until FlinkSqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = FlinkSqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = FlinkSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = FlinkSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = FlinkSqlParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: FlinkSqlParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = FlinkSqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = FlinkSqlParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.addParseListener(FlinkSqlParserBaseListener()) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) // parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-flink-parser/src/test/kotlin/io/github/melin/superior/parser/flink/FlinkCheckSql.kt ================================================ package io.github.melin.superior.parser.flink import org.junit.Test class FlinkCheckSql { @Test fun selectSqlTest() { val sql = """ CREATE TABLE test ( name VARCHAR(12) ) with(key = 'name') """ .trimIndent() FlinkSqlHelper.checkSqlSyntax(sql) } } ================================================ FILE: superior-flink-parser/src/test/kotlin/io/github/melin/superior/parser/flink/FlinkSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.flink import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.dml.InsertTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class FlinkSqlParserDdlTest { @Test fun parseMultiSqlTest() { val sql = """ CREATE TABLE IF NOT EXISTS `RETEK_XX_ITEM_ATTR_TRANSLATE_PRODUCT_ENRICHMENT`( `ITEM` STRING, `UDA_ID` DECIMAL(5,0), `UDA_VALUE_ID` DECIMAL(3,0), `LANG` DECIMAL(6,0), `TRANSLATED_VALUE` STRING, `LAST_UPDATE_ID` STRING, `CREATE_DATETIME` TIMESTAMP(3), `LAST_UPDATE_DATETIME` TIMESTAMP(3), `KAFKA_PROCESS_TIME` AS PROCTIME(), `record_time` TIMESTAMP_LTZ(3) METADATA FROM 'timestamp', `cost` AS price * quantity ) WITH ( 'connector' = 'kafka', 'properties.acks' = '-1', 'properties.allow.auto.create.topics' = 'true', 'topic' = 'test', 'properties.bootstrap.servers' = 'localhost:9082', 'value.format' = 'changelog-json', 'properties.group.id' = 'test', 'key.fields' = 'ITEM;UDA_ID;LANG', 'key.format'='json', 'scan.startup.mode' = 'earliest-offset', 'value.changelog-json.timestamp-format.standard'='ISO-8601', 'value.changelog-json.ignore-parse-errors' = 'true' ); CREATE VIEW IF NOT EXISTS `MDM_VIEW_PRODUCT_ENRICHMENT` AS (SELECT 'WTCTH' BU_CODE, 'WTCTH' FORMULA_COUNTRY_ID, uif.ITEM PRODUCT_ID, CAST(CAST(uif.UDA_ID AS DECIMAL(5, 0)) AS STRING) ENRICHMENT_ID, uif.UDA_TEXT ENRICHMENT_VALUE, u.UDA_DESC ENRICHMENT_DESC, u.SINGLE_VALUE_IND SINGLE_VALUE_IND, u.DISPLAY_TYPE CONTROL_TYPE, 'EN' LANG, 'FLINKJDBC' CREATE_BY, uif.LAST_UPDATE_ID LAST_UPDATE_BY, uif.CREATE_DATETIME CREATED, uif.LAST_UPDATE_DATETIME LAST_UPDATED FROM RETEK_UDA_ITEM_FF_PRODUCT_ENRICHMENT uif JOIN MDM_DIM_UDA_LOOKUPMAP_ORACLE FOR SYSTEM_TIME AS OF uif.KAFKA_PROCESS_TIME AS u ON CAST(uif.UDA_ID AS DECIMAL(5, 0)) = u.UDA_ID JOIN MDM_DIM_PRODUCT_ATTRIB_TYPE_LOOKUPMAP_MYSQL FOR SYSTEM_TIME AS OF uif.KAFKA_PROCESS_TIME AS pat ON CAST(CAST(uif.UDA_ID AS DECIMAL(5, 0)) AS STRING) = pat.ATTRIB_ID AND pat.ATTRIB_TYPE = 'PRODUCT_ENRICHMENT' ); INSERT INTO PROCESSED_MDM_PRODUCT_ENRICHMENT(PRODUCT_ID, ENRICHMENT_ID, LANG, ENRICHMENT_VALUE,LAST_UPDATED) select PRODUCT_ID, ENRICHMENT_ID, LANG, ENRICHMENT_VALUE,LAST_UPDATED from MDM_VIEW_PRODUCT_ENRICHMENT_TRANSLATE; """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) val createTable = statements.get(0) if (createTable is CreateTable) { Assert.assertEquals("RETEK_XX_ITEM_ATTR_TRANSLATE_PRODUCT_ENRICHMENT", createTable.tableId.tableName) Assert.assertEquals(11, createTable.columnRels?.size) Assert.assertEquals("PROCTIME()", createTable.columnRels?.get(8)?.computedExpr) Assert.assertEquals("timestamp", createTable.columnRels?.get(9)?.metadataKey) Assert.assertEquals("price * quantity", createTable.columnRels?.get(10)?.computedExpr) Assert.assertEquals(12, createTable.properties?.size) } else { Assert.fail() } val createView = statements.get(1) if (createView is CreateView) { Assert.assertEquals("MDM_VIEW_PRODUCT_ENRICHMENT", createView.tableId.tableName) Assert.assertEquals(3, createView.queryStmt.inputTables.size) } else { Assert.fail() } val insertTable = statements.get(2) if (insertTable is InsertTable) { Assert.assertEquals("PROCESSED_MDM_PRODUCT_ENRICHMENT", insertTable.outputTables.get(0).tableName) Assert.assertEquals(1, insertTable.queryStmt.inputTables.size) Assert.assertEquals(5, insertTable.columnRels?.size) } else { Assert.fail() } } @Test fun createTableTest0() { val sql = """ CREATE TABLE Orders ( `user` BIGINT, product STRING, order_time TIMESTAMP(3), WATERMARK FOR order_time AS order_time - INTERVAL '5' SECOND ) WITH ( 'connector' = 'kafka' ) """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) val createTable = statements.get(0) if (createTable is CreateTable) { Assert.assertEquals("Orders", createTable.tableId.tableName) Assert.assertEquals(3, createTable.columnRels?.size) Assert.assertEquals(1, createTable.properties?.size) } else { Assert.fail() } } @Test fun createTableTest1() { val sql = """ CREATE TABLE `Orders` (product STRING PRIMARY KEY NOT ENFORCED, `a.b.c` INT) WITH ('type'='source', 'foo'='bar') """ .trimIndent() val createTable = FlinkSqlHelper.parseStatement(sql) if (createTable is CreateTable) { Assert.assertEquals("Orders", createTable.tableId.tableName) Assert.assertEquals(2, createTable.columnRels?.size) createTable.columnRels?.get(0)?.primaryKey?.let { Assert.assertTrue(it) } Assert.assertEquals(2, createTable.properties?.size) } else { Assert.fail() } } @Test fun createTableTest2() { val sql = """ CREATE TABLE flink_meta_role ( id INT, name STRING, code STRING, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://172.18.5.44:3306/superior', 'table-name' = 'meta_role', 'username' = 'root', 'password' = 'root2023' ); """ .trimIndent() val createTable = FlinkSqlHelper.parseStatement(sql) if (createTable is CreateTable) { Assert.assertEquals("flink_meta_role", createTable.tableId.tableName) Assert.assertEquals(3, createTable.columnRels?.size) createTable.columnRels?.get(0)?.primaryKey?.let { Assert.assertTrue(it) } Assert.assertEquals(5, createTable.properties?.size) } else { Assert.fail() } } } ================================================ FILE: superior-flink-parser/src/test/kotlin/io/github/melin/superior/parser/flink/FlinkSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.flink import io.github.melin.superior.common.relational.common.AddResourceStatement import io.github.melin.superior.common.relational.common.SetStatement import io.github.melin.superior.common.relational.create.CreateCatalog import io.github.melin.superior.common.relational.dml.InsertMultiTable import io.github.melin.superior.common.relational.dml.QueryStmt import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class FlinkSqlParserDmlTest { @Test fun selectSqlTest() { val sql = """ WITH orders_with_total AS ( SELECT order_id, price + tax AS total FROM Orders ) SELECT order_id, SUM(total) FROM orders_with_total GROUP BY order_id limit 10; SELECT order_id, price FROM (VALUES (1, 2.0), (2, 3.1)) AS t (order_id, price); SELECT * FROM TABLE(TUMBLE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES)); SELECT * FROM TABLE( TUMBLE( DATA => TABLE Bid, TIMECOL => DESCRIPTOR(bidtime), SIZE => INTERVAL '10' MINUTES)); SELECT * FROM TABLE( HOP( DATA => TABLE Bid, TIMECOL => DESCRIPTOR(bidtime), SLIDE => INTERVAL '5' MINUTES, SIZE => INTERVAL '10' MINUTES)); SELECT * FROM TABLE( CUMULATE( DATA => TABLE Bid, TIMECOL => DESCRIPTOR(bidtime), STEP => INTERVAL '2' MINUTES, SIZE => INTERVAL '10' MINUTES)); SELECT window_start, window_end, SUM(price) FROM TABLE( TUMBLE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '10' MINUTES, INTERVAL '1' MINUTES)) GROUP BY window_start, window_end; SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS row_num FROM ShopSales) WHERE row_num <= 5; SELECT * FROM Ticker MATCH_RECOGNIZE ( PARTITION BY symbol ORDER BY rowtime MEASURES START_ROW.rowtime AS start_tstamp, LAST(PRICE_DOWN.rowtime) AS bottom_tstamp, LAST(PRICE_UP.rowtime) AS end_tstamp ONE ROW PER MATCH AFTER MATCH SKIP TO LAST PRICE_UP PATTERN (START_ROW PRICE_DOWN+ PRICE_UP) DEFINE PRICE_DOWN AS (LAST(PRICE_DOWN.price, 1) IS NULL AND PRICE_DOWN.price < START_ROW.price) OR PRICE_DOWN.price < LAST(PRICE_DOWN.price, 1), PRICE_UP AS PRICE_UP.price > LAST(PRICE_DOWN.price, 1) ) MR; set sfdf_1 = 'adf'; set sfdf_2 = true; """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) var queryStmt = statements.get(0) if (queryStmt is QueryStmt) { Assert.assertEquals("Orders", queryStmt.inputTables.get(0).tableName) Assert.assertEquals(10, queryStmt.limit) } else { Assert.fail() } queryStmt = statements.get(1) if (queryStmt is QueryStmt) { Assert.assertEquals(0, queryStmt.inputTables.size) } else { Assert.fail() } queryStmt = statements.get(2) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Bid", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(3) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Bid", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(4) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Bid", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(5) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Bid", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(6) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Bid", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(7) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("ShopSales", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } queryStmt = statements.get(8) if (queryStmt is QueryStmt) { Assert.assertEquals(1, queryStmt.inputTables.size) Assert.assertEquals("Ticker", queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun selectSqlTest1() { val sql = """ add jar "flink-connector-jdbc-3.1.1-1.17.jar"; CREATE TABLE flink_meta_role ( id INT, name STRING, code STRING, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://172.18.5.44:3306/superior', 'table-name' = 'meta_role', 'username' = 'root', 'password' = 'root2023' ); set 'execution.checkpointing.checkpoints-after-tasks-finish.enabled' = false; SELECT * FROM flink_meta_role; """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(4, statements.size) val addStmt = statements.get(0) if (addStmt is AddResourceStatement) { Assert.assertEquals("flink-connector-jdbc-3.1.1-1.17.jar", addStmt.first()) } else { Assert.fail() } val setStmt = statements.get(2) if (setStmt is SetStatement) { Assert.assertEquals("execution.checkpointing.checkpoints-after-tasks-finish.enabled", setStmt.key) } else { Assert.fail() } } @Test fun selectSqlTest2() { val sql = """ CREATE CATALOG my_catalog WITH ( 'type' = 'jdbc', 'default-database' = 'demos', 'username' = 'root', 'password' = 'root2023', 'base-url' = 'jdbc:mysql://172.18.5.44:3306' ); USE CATALOG my_catalog; DROP CATALOG IF EXISTS my_catalog EXPLAIN PLAN FOR select * from my_catalog.demos.orders; EXPLAIN ESTIMATED_COST, CHANGELOG_MODE, PLAN_ADVICE, JSON_EXECUTION_PLAN select * from my_catalog.demos.orders; """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(5, statements.size) val createCatalog = statements.get(0) if (createCatalog is CreateCatalog) { Assert.assertEquals("my_catalog", createCatalog.catalogName) } else { Assert.fail() } } @Test fun multiInsertTest() { val sql = """ CREATE TABLE pageviews ( user_id BIGINT, page_id BIGINT, viewtime TIMESTAMP, proctime AS PROCTIME() ) WITH ( 'connector' = 'kafka', 'topic' = 'pageviews', 'properties.bootstrap.servers' = '...', 'format' = 'avro' ); CREATE TABLE pageview ( page_id BIGINT, cnt BIGINT ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://localhost:3306/mydatabase', 'table-name' = 'pageview' ); CREATE TABLE uniqueview ( page_id BIGINT, cnt BIGINT ) WITH ( 'connector' = 'jdbc', 'url' = 'jdbc:mysql://localhost:3306/mydatabase', 'table-name' = 'uniqueview' ); EXECUTE STATEMENT SET BEGIN INSERT INTO pageview SELECT page_id, count(1) FROM pageviews GROUP BY page_id; INSERT INTO uniqueview SELECT page_id, count(distinct user_id) FROM pageviews GROUP BY page_id; END; """ .trimIndent() val statements = FlinkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(4, statements.size) val statement = statements.get(3) if (statement is InsertMultiTable) { Assert.assertEquals(2, statement.insertTables.size) val insertTable = statement.insertTables.get(0) Assert.assertEquals( "INSERT INTO pageview\n" + " SELECT page_id, count(1)\n" + " FROM pageviews\n" + " GROUP BY page_id", insertTable.getSql() ) } else { Assert.fail() } } } ================================================ FILE: superior-flink-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-mysql-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-mysql-parser superior-mysql-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-mysql-parser/src/main/antlr4/io/github/melin/superior/parser/mysql/antlr4/MySqlLexer.g4 ================================================ lexer grammar MySqlLexer; channels { MYSQLCOMMENT, ERRORCHANNEL } // SKIP SPACE : [ \t\r\n]+ -> channel(HIDDEN); SPEC_MYSQL_COMMENT : '/*!' .+? '*/' -> channel(MYSQLCOMMENT); COMMENT_INPUT : '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: (('--' [ \t]* | '#') ~[\r\n]* ('\r'? '\n' | EOF) | '--' ('\r'? '\n' | EOF)) -> channel(HIDDEN) ; // Keywords // Common Keywords ADD : 'ADD'; ALL : 'ALL'; ALTER : 'ALTER'; ALWAYS : 'ALWAYS'; ANALYZE : 'ANALYZE'; AND : 'AND'; ARRAY : 'ARRAY'; AS : 'AS'; ASC : 'ASC'; ATTRIBUTE : 'ATTRIBUTE'; BEFORE : 'BEFORE'; BETWEEN : 'BETWEEN'; BOTH : 'BOTH'; BUCKETS : 'BUCKETS'; BY : 'BY'; CALL : 'CALL'; CASCADE : 'CASCADE'; CASE : 'CASE'; CAST : 'CAST'; CHANGE : 'CHANGE'; CHARACTER : 'CHARACTER'; CHECK : 'CHECK'; COLLATE : 'COLLATE'; COLUMN : 'COLUMN'; CONDITION : 'CONDITION'; CONSTRAINT : 'CONSTRAINT'; CONTINUE : 'CONTINUE'; CONVERT : 'CONVERT'; CREATE : 'CREATE'; CROSS : 'CROSS'; CURRENT : 'CURRENT'; CURRENT_ROLE : 'CURRENT_ROLE'; CURRENT_USER : 'CURRENT_USER'; CURSOR : 'CURSOR'; DATABASE : 'DATABASE'; DATABASES : 'DATABASES'; DECLARE : 'DECLARE'; DEFAULT : 'DEFAULT'; DELAYED : 'DELAYED'; DELETE : 'DELETE'; DESC : 'DESC'; DESCRIBE : 'DESCRIBE'; DETERMINISTIC : 'DETERMINISTIC'; DIAGNOSTICS : 'DIAGNOSTICS'; DISTINCT : 'DISTINCT'; DISTINCTROW : 'DISTINCTROW'; DROP : 'DROP'; EACH : 'EACH'; ELSE : 'ELSE'; ELSEIF : 'ELSEIF'; EMPTY : 'EMPTY'; ENCLOSED : 'ENCLOSED'; ENFORCED : 'ENFORCED'; ESCAPED : 'ESCAPED'; EXCEPT : 'EXCEPT'; EXISTS : 'EXISTS'; EXIT : 'EXIT'; EXPLAIN : 'EXPLAIN'; FALSE : 'FALSE'; FETCH : 'FETCH'; FOR : 'FOR'; FORCE : 'FORCE'; FOREIGN : 'FOREIGN'; FROM : 'FROM'; FULLTEXT : 'FULLTEXT'; GENERATED : 'GENERATED'; GET : 'GET'; GRANT : 'GRANT'; GROUP : 'GROUP'; HAVING : 'HAVING'; HIGH_PRIORITY : 'HIGH_PRIORITY'; HISTOGRAM : 'HISTOGRAM'; IF : 'IF'; IGNORE : 'IGNORE'; IGNORED : 'IGNORED'; IN : 'IN'; INDEX : 'INDEX'; INFILE : 'INFILE'; INNER : 'INNER'; INOUT : 'INOUT'; INSERT : 'INSERT'; INTERVAL : 'INTERVAL'; INTO : 'INTO'; IS : 'IS'; ITERATE : 'ITERATE'; JOIN : 'JOIN'; KEY : 'KEY'; KEYS : 'KEYS'; KILL : 'KILL'; LATERAL : 'LATERAL'; LEADING : 'LEADING'; LEAVE : 'LEAVE'; LEFT : 'LEFT'; LIKE : 'LIKE'; LIMIT : 'LIMIT'; LINEAR : 'LINEAR'; LINES : 'LINES'; LOAD : 'LOAD'; LOCK : 'LOCK'; LOCKED : 'LOCKED'; LOOP : 'LOOP'; LOW_PRIORITY : 'LOW_PRIORITY'; MASTER_BIND : 'MASTER_BIND'; MASTER_SSL_VERIFY_SERVER_CERT : 'MASTER_SSL_VERIFY_SERVER_CERT'; MATCH : 'MATCH'; MAXVALUE : 'MAXVALUE'; MINVALUE : 'MINVALUE'; MODIFIES : 'MODIFIES'; NATURAL : 'NATURAL'; NOT : 'NOT'; NO_WRITE_TO_BINLOG : 'NO_WRITE_TO_BINLOG'; NULL_LITERAL : 'NULL'; NUMBER : 'NUMBER'; ON : 'ON'; OPTIMIZE : 'OPTIMIZE'; OPTION : 'OPTION'; OPTIONAL : 'OPTIONAL'; OPTIONALLY : 'OPTIONALLY'; OR : 'OR'; ORDER : 'ORDER'; OUT : 'OUT'; OUTER : 'OUTER'; OUTFILE : 'OUTFILE'; OVER : 'OVER'; PARTITION : 'PARTITION'; PRIMARY : 'PRIMARY'; PROCEDURE : 'PROCEDURE'; PURGE : 'PURGE'; RANGE : 'RANGE'; READ : 'READ'; READS : 'READS'; REFERENCES : 'REFERENCES'; REGEXP : 'REGEXP'; RELEASE : 'RELEASE'; RENAME : 'RENAME'; REPEAT : 'REPEAT'; REPLACE : 'REPLACE'; REQUIRE : 'REQUIRE'; RESIGNAL : 'RESIGNAL'; RESTRICT : 'RESTRICT'; RETAIN : 'RETAIN'; RETURN : 'RETURN'; REVOKE : 'REVOKE'; RIGHT : 'RIGHT'; RLIKE : 'RLIKE'; SCHEMA : 'SCHEMA'; SCHEMAS : 'SCHEMAS'; SELECT : 'SELECT'; SET : 'SET'; SEPARATOR : 'SEPARATOR'; SHOW : 'SHOW'; SIGNAL : 'SIGNAL'; SKIP_ : 'SKIP'; SKIP_QUERY_REWRITE : 'SKIP_QUERY_REWRITE'; SPATIAL : 'SPATIAL'; SQL : 'SQL'; SQLEXCEPTION : 'SQLEXCEPTION'; SQLSTATE : 'SQLSTATE'; SQLWARNING : 'SQLWARNING'; SQL_BIG_RESULT : 'SQL_BIG_RESULT'; SQL_CALC_FOUND_ROWS : 'SQL_CALC_FOUND_ROWS'; SQL_SMALL_RESULT : 'SQL_SMALL_RESULT'; SSL : 'SSL'; STACKED : 'STACKED'; STARTING : 'STARTING'; STATEMENT : 'STATEMENT'; STRAIGHT_JOIN : 'STRAIGHT_JOIN'; TABLE : 'TABLE'; TERMINATED : 'TERMINATED'; THEN : 'THEN'; TO : 'TO'; TRAILING : 'TRAILING'; TRIGGER : 'TRIGGER'; TRUE : 'TRUE'; UNDO : 'UNDO'; UNION : 'UNION'; UNIQUE : 'UNIQUE'; UNLOCK : 'UNLOCK'; UNSIGNED : 'UNSIGNED'; UPDATE : 'UPDATE'; USAGE : 'USAGE'; USE : 'USE'; USING : 'USING'; VALUES : 'VALUES'; WHEN : 'WHEN'; WHERE : 'WHERE'; WHILE : 'WHILE'; WITH : 'WITH'; WRITE : 'WRITE'; XOR : 'XOR'; ZEROFILL : 'ZEROFILL'; // DATA TYPE Keywords TINYINT : 'TINYINT'; SMALLINT : 'SMALLINT'; MEDIUMINT : 'MEDIUMINT'; MIDDLEINT : 'MIDDLEINT'; INT : 'INT'; INT1 : 'INT1'; INT2 : 'INT2'; INT3 : 'INT3'; INT4 : 'INT4'; INT8 : 'INT8'; INTEGER : 'INTEGER'; BIGINT : 'BIGINT'; REAL : 'REAL'; DOUBLE : 'DOUBLE'; PRECISION : 'PRECISION'; FLOAT : 'FLOAT'; FLOAT4 : 'FLOAT4'; FLOAT8 : 'FLOAT8'; DECIMAL : 'DECIMAL'; DEC : 'DEC'; NUMERIC : 'NUMERIC'; DATE : 'DATE'; TIME : 'TIME'; TIMESTAMP : 'TIMESTAMP'; DATETIME : 'DATETIME'; YEAR : 'YEAR'; CHAR : 'CHAR'; VARCHAR : 'VARCHAR'; NVARCHAR : 'NVARCHAR'; NATIONAL : 'NATIONAL'; BINARY : 'BINARY'; VARBINARY : 'VARBINARY'; TINYBLOB : 'TINYBLOB'; BLOB : 'BLOB'; MEDIUMBLOB : 'MEDIUMBLOB'; LONG : 'LONG'; LONGBLOB : 'LONGBLOB'; TINYTEXT : 'TINYTEXT'; TEXT : 'TEXT'; MEDIUMTEXT : 'MEDIUMTEXT'; LONGTEXT : 'LONGTEXT'; ENUM : 'ENUM'; VARYING : 'VARYING'; SERIAL : 'SERIAL'; VECTOR : 'VECTOR'; // Interval type Keywords YEAR_MONTH : 'YEAR_MONTH'; DAY_HOUR : 'DAY_HOUR'; DAY_MINUTE : 'DAY_MINUTE'; DAY_SECOND : 'DAY_SECOND'; HOUR_MINUTE : 'HOUR_MINUTE'; HOUR_SECOND : 'HOUR_SECOND'; MINUTE_SECOND : 'MINUTE_SECOND'; SECOND_MICROSECOND : 'SECOND_MICROSECOND'; MINUTE_MICROSECOND : 'MINUTE_MICROSECOND'; HOUR_MICROSECOND : 'HOUR_MICROSECOND'; DAY_MICROSECOND : 'DAY_MICROSECOND'; // JSON keywords JSON_ARRAY : 'JSON_ARRAY'; JSON_ARRAYAGG : 'JSON_ARRAYAGG'; JSON_ARRAY_APPEND : 'JSON_ARRAY_APPEND'; JSON_ARRAY_INSERT : 'JSON_ARRAY_INSERT'; JSON_CONTAINS : 'JSON_CONTAINS'; JSON_CONTAINS_PATH : 'JSON_CONTAINS_PATH'; JSON_DEPTH : 'JSON_DEPTH'; JSON_EXTRACT : 'JSON_EXTRACT'; JSON_INSERT : 'JSON_INSERT'; JSON_KEYS : 'JSON_KEYS'; JSON_LENGTH : 'JSON_LENGTH'; JSON_MERGE : 'JSON_MERGE'; JSON_MERGE_PATCH : 'JSON_MERGE_PATCH'; JSON_MERGE_PRESERVE : 'JSON_MERGE_PRESERVE'; JSON_OBJECT : 'JSON_OBJECT'; JSON_OBJECTAGG : 'JSON_OBJECTAGG'; JSON_OVERLAPS : 'JSON_OVERLAPS'; JSON_PRETTY : 'JSON_PRETTY'; JSON_QUOTE : 'JSON_QUOTE'; JSON_REMOVE : 'JSON_REMOVE'; JSON_REPLACE : 'JSON_REPLACE'; JSON_SCHEMA_VALID : 'JSON_SCHEMA_VALID'; JSON_SCHEMA_VALIDATION_REPORT : 'JSON_SCHEMA_VALIDATION_REPORT'; JSON_SEARCH : 'JSON_SEARCH'; JSON_SET : 'JSON_SET'; JSON_STORAGE_FREE : 'JSON_STORAGE_FREE'; JSON_STORAGE_SIZE : 'JSON_STORAGE_SIZE'; JSON_TABLE : 'JSON_TABLE'; JSON_TYPE : 'JSON_TYPE'; JSON_UNQUOTE : 'JSON_UNQUOTE'; JSON_VALID : 'JSON_VALID'; JSON_VALUE : 'JSON_VALUE'; NESTED : 'NESTED'; ORDINALITY : 'ORDINALITY'; PATH : 'PATH'; // Group function Keywords AVG : 'AVG'; BIT_AND : 'BIT_AND'; BIT_OR : 'BIT_OR'; BIT_XOR : 'BIT_XOR'; COUNT : 'COUNT'; CUME_DIST : 'CUME_DIST'; DENSE_RANK : 'DENSE_RANK'; FIRST_VALUE : 'FIRST_VALUE'; GROUP_CONCAT : 'GROUP_CONCAT'; LAG : 'LAG'; LAST_VALUE : 'LAST_VALUE'; LEAD : 'LEAD'; MAX : 'MAX'; MIN : 'MIN'; NTILE : 'NTILE'; NTH_VALUE : 'NTH_VALUE'; PERCENT_RANK : 'PERCENT_RANK'; RANK : 'RANK'; ROW_NUMBER : 'ROW_NUMBER'; STD : 'STD'; STDDEV : 'STDDEV'; STDDEV_POP : 'STDDEV_POP'; STDDEV_SAMP : 'STDDEV_SAMP'; SUM : 'SUM'; VAR_POP : 'VAR_POP'; VAR_SAMP : 'VAR_SAMP'; VARIANCE : 'VARIANCE'; // Common function Keywords CURRENT_DATE : 'CURRENT_DATE'; CURRENT_TIME : 'CURRENT_TIME'; CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP'; LOCALTIME : 'LOCALTIME'; CURDATE : 'CURDATE'; CURTIME : 'CURTIME'; DATE_ADD : 'DATE_ADD'; DATE_SUB : 'DATE_SUB'; EXTRACT : 'EXTRACT'; LOCALTIMESTAMP : 'LOCALTIMESTAMP'; NOW : 'NOW'; POSITION : 'POSITION'; SUBSTR : 'SUBSTR'; SUBSTRING : 'SUBSTRING'; SYSDATE : 'SYSDATE'; TRIM : 'TRIM'; UTC_DATE : 'UTC_DATE'; UTC_TIME : 'UTC_TIME'; UTC_TIMESTAMP : 'UTC_TIMESTAMP'; // Keywords, but can be ID // Common Keywords, but can be ID ACCOUNT : 'ACCOUNT'; ACTION : 'ACTION'; AFTER : 'AFTER'; AGGREGATE : 'AGGREGATE'; ALGORITHM : 'ALGORITHM'; ANY : 'ANY'; AT : 'AT'; AUTHORS : 'AUTHORS'; AUTOCOMMIT : 'AUTOCOMMIT'; AUTOEXTEND_SIZE : 'AUTOEXTEND_SIZE'; AUTO_INCREMENT : 'AUTO_INCREMENT'; AVG_ROW_LENGTH : 'AVG_ROW_LENGTH'; BEGIN : 'BEGIN'; BINLOG : 'BINLOG'; BIT : 'BIT'; BLOCK : 'BLOCK'; BOOL : 'BOOL'; BOOLEAN : 'BOOLEAN'; BTREE : 'BTREE'; CACHE : 'CACHE'; CASCADED : 'CASCADED'; CHAIN : 'CHAIN'; CHANGED : 'CHANGED'; CHANNEL : 'CHANNEL'; CHECKSUM : 'CHECKSUM'; PAGE_CHECKSUM : 'PAGE_CHECKSUM'; CIPHER : 'CIPHER'; CLASS_ORIGIN : 'CLASS_ORIGIN'; CLIENT : 'CLIENT'; CLOSE : 'CLOSE'; CLUSTERING : 'CLUSTERING'; COALESCE : 'COALESCE'; CODE : 'CODE'; COLUMNS : 'COLUMNS'; COLUMN_FORMAT : 'COLUMN_FORMAT'; COLUMN_NAME : 'COLUMN_NAME'; COMMENT : 'COMMENT'; COMMIT : 'COMMIT'; COMPACT : 'COMPACT'; COMPLETION : 'COMPLETION'; COMPRESSED : 'COMPRESSED'; COMPRESSION : 'COMPRESSION' | QUOTE_SYMB? 'COMPRESSION' QUOTE_SYMB?; CONCURRENT : 'CONCURRENT'; CONNECT : 'CONNECT'; CONNECTION : 'CONNECTION'; CONSISTENT : 'CONSISTENT'; CONSTRAINT_CATALOG : 'CONSTRAINT_CATALOG'; CONSTRAINT_SCHEMA : 'CONSTRAINT_SCHEMA'; CONSTRAINT_NAME : 'CONSTRAINT_NAME'; CONTAINS : 'CONTAINS'; CONTEXT : 'CONTEXT'; CONTRIBUTORS : 'CONTRIBUTORS'; COPY : 'COPY'; CPU : 'CPU'; CYCLE : 'CYCLE'; CURSOR_NAME : 'CURSOR_NAME'; DATA : 'DATA'; DATAFILE : 'DATAFILE'; DEALLOCATE : 'DEALLOCATE'; DEFAULT_AUTH : 'DEFAULT_AUTH'; DEFINER : 'DEFINER'; DELAY_KEY_WRITE : 'DELAY_KEY_WRITE'; DES_KEY_FILE : 'DES_KEY_FILE'; DIRECTORY : 'DIRECTORY'; DISABLE : 'DISABLE'; DISCARD : 'DISCARD'; DISK : 'DISK'; DO : 'DO'; DUMPFILE : 'DUMPFILE'; DUPLICATE : 'DUPLICATE'; DYNAMIC : 'DYNAMIC'; ENABLE : 'ENABLE'; ENCRYPTED : 'ENCRYPTED'; ENCRYPTION : 'ENCRYPTION'; ENCRYPTION_KEY_ID : 'ENCRYPTION_KEY_ID'; END : 'END'; ENDS : 'ENDS'; ENGINE : 'ENGINE'; ENGINES : 'ENGINES'; ERROR : 'ERROR'; ERRORS : 'ERRORS'; ESCAPE : 'ESCAPE'; EVEN : 'EVEN'; EVENT : 'EVENT'; EVENTS : 'EVENTS'; EVERY : 'EVERY'; EXCHANGE : 'EXCHANGE'; EXCLUSIVE : 'EXCLUSIVE'; EXPIRE : 'EXPIRE'; EXPORT : 'EXPORT'; EXTENDED : 'EXTENDED'; EXTENT_SIZE : 'EXTENT_SIZE'; FAILED_LOGIN_ATTEMPTS : 'FAILED_LOGIN_ATTEMPTS'; FAST : 'FAST'; FAULTS : 'FAULTS'; FIELDS : 'FIELDS'; FILE_BLOCK_SIZE : 'FILE_BLOCK_SIZE'; FILTER : 'FILTER'; FIRST : 'FIRST'; FIXED : 'FIXED'; FLUSH : 'FLUSH'; FOLLOWING : 'FOLLOWING'; FOLLOWS : 'FOLLOWS'; FOUND : 'FOUND'; FULL : 'FULL'; FUNCTION : 'FUNCTION'; GENERAL : 'GENERAL'; GLOBAL : 'GLOBAL'; GRANTS : 'GRANTS'; GROUP_REPLICATION : 'GROUP_REPLICATION'; HANDLER : 'HANDLER'; HASH : 'HASH'; HELP : 'HELP'; HISTORY : 'HISTORY'; HOST : 'HOST'; HOSTS : 'HOSTS'; IDENTIFIED : 'IDENTIFIED'; IGNORE_SERVER_IDS : 'IGNORE_SERVER_IDS'; IMPORT : 'IMPORT'; INCREMENT : 'INCREMENT'; INDEXES : 'INDEXES'; INITIAL_SIZE : 'INITIAL_SIZE'; INPLACE : 'INPLACE'; INSERT_METHOD : 'INSERT_METHOD'; INSTALL : 'INSTALL'; INSTANCE : 'INSTANCE'; INSTANT : 'INSTANT'; INVISIBLE : 'INVISIBLE'; INVOKER : 'INVOKER'; IO : 'IO'; IO_THREAD : 'IO_THREAD'; IPC : 'IPC'; ISOLATION : 'ISOLATION'; ISSUER : 'ISSUER'; JSON : 'JSON'; KEY_BLOCK_SIZE : 'KEY_BLOCK_SIZE'; LANGUAGE : 'LANGUAGE'; LAST : 'LAST'; LEAVES : 'LEAVES'; LESS : 'LESS'; LEVEL : 'LEVEL'; LIST : 'LIST'; LOCAL : 'LOCAL'; LOGFILE : 'LOGFILE'; LOGS : 'LOGS'; MASTER : 'MASTER'; MASTER_AUTO_POSITION : 'MASTER_AUTO_POSITION'; MASTER_CONNECT_RETRY : 'MASTER_CONNECT_RETRY'; MASTER_DELAY : 'MASTER_DELAY'; MASTER_HEARTBEAT_PERIOD : 'MASTER_HEARTBEAT_PERIOD'; MASTER_HOST : 'MASTER_HOST'; MASTER_LOG_FILE : 'MASTER_LOG_FILE'; MASTER_LOG_POS : 'MASTER_LOG_POS'; MASTER_PASSWORD : 'MASTER_PASSWORD'; MASTER_PORT : 'MASTER_PORT'; MASTER_RETRY_COUNT : 'MASTER_RETRY_COUNT'; MASTER_SSL : 'MASTER_SSL'; MASTER_SSL_CA : 'MASTER_SSL_CA'; MASTER_SSL_CAPATH : 'MASTER_SSL_CAPATH'; MASTER_SSL_CERT : 'MASTER_SSL_CERT'; MASTER_SSL_CIPHER : 'MASTER_SSL_CIPHER'; MASTER_SSL_CRL : 'MASTER_SSL_CRL'; MASTER_SSL_CRLPATH : 'MASTER_SSL_CRLPATH'; MASTER_SSL_KEY : 'MASTER_SSL_KEY'; MASTER_TLS_VERSION : 'MASTER_TLS_VERSION'; MASTER_USER : 'MASTER_USER'; MAX_CONNECTIONS_PER_HOUR : 'MAX_CONNECTIONS_PER_HOUR'; MAX_QUERIES_PER_HOUR : 'MAX_QUERIES_PER_HOUR'; MAX_ROWS : 'MAX_ROWS'; MAX_SIZE : 'MAX_SIZE'; MAX_UPDATES_PER_HOUR : 'MAX_UPDATES_PER_HOUR'; MAX_USER_CONNECTIONS : 'MAX_USER_CONNECTIONS'; MEDIUM : 'MEDIUM'; MEMBER : 'MEMBER'; MERGE : 'MERGE'; MESSAGE_TEXT : 'MESSAGE_TEXT'; MID : 'MID'; MIGRATE : 'MIGRATE'; MIN_ROWS : 'MIN_ROWS'; MODE : 'MODE'; MODIFY : 'MODIFY'; MUTEX : 'MUTEX'; MYSQL : 'MYSQL'; MYSQL_ERRNO : 'MYSQL_ERRNO'; NAME : 'NAME'; NAMES : 'NAMES'; NCHAR : 'NCHAR'; NEVER : 'NEVER'; NEXT : 'NEXT'; NO : 'NO'; NOCACHE : 'NOCACHE'; NOCOPY : 'NOCOPY'; NOCYCLE : 'NOCYCLE'; NOMAXVALUE : 'NOMAXVALUE'; NOMINVALUE : 'NOMINVALUE'; NOWAIT : 'NOWAIT'; NODEGROUP : 'NODEGROUP'; NONE : 'NONE'; ODBC : 'ODBC'; OFFLINE : 'OFFLINE'; OFFSET : 'OFFSET'; OF : 'OF'; OJ : 'OJ'; OLD_PASSWORD : 'OLD_PASSWORD'; ONE : 'ONE'; ONLINE : 'ONLINE'; ONLY : 'ONLY'; OPEN : 'OPEN'; OPTIMIZER_COSTS : 'OPTIMIZER_COSTS'; OPTIONS : 'OPTIONS'; OWNER : 'OWNER'; PACK_KEYS : 'PACK_KEYS'; PAGE : 'PAGE'; PAGE_COMPRESSED : 'PAGE_COMPRESSED'; PAGE_COMPRESSION_LEVEL : 'PAGE_COMPRESSION_LEVEL'; PARSER : 'PARSER'; PARTIAL : 'PARTIAL'; PARTITIONING : 'PARTITIONING'; PARTITIONS : 'PARTITIONS'; PASSWORD : 'PASSWORD'; PASSWORD_LOCK_TIME : 'PASSWORD_LOCK_TIME'; PHASE : 'PHASE'; PLUGIN : 'PLUGIN'; PLUGIN_DIR : 'PLUGIN_DIR'; PLUGINS : 'PLUGINS'; PORT : 'PORT'; PRECEDES : 'PRECEDES'; PRECEDING : 'PRECEDING'; PREPARE : 'PREPARE'; PRESERVE : 'PRESERVE'; PREV : 'PREV'; PROCESSLIST : 'PROCESSLIST'; PROFILE : 'PROFILE'; PROFILES : 'PROFILES'; PROXY : 'PROXY'; QUERY : 'QUERY'; QUICK : 'QUICK'; REBUILD : 'REBUILD'; RECOVER : 'RECOVER'; RECURSIVE : 'RECURSIVE'; REDO_BUFFER_SIZE : 'REDO_BUFFER_SIZE'; REDUNDANT : 'REDUNDANT'; RELAY : 'RELAY'; RELAY_LOG_FILE : 'RELAY_LOG_FILE'; RELAY_LOG_POS : 'RELAY_LOG_POS'; RELAYLOG : 'RELAYLOG'; REMOVE : 'REMOVE'; REORGANIZE : 'REORGANIZE'; REPAIR : 'REPAIR'; REPLICATE_DO_DB : 'REPLICATE_DO_DB'; REPLICATE_DO_TABLE : 'REPLICATE_DO_TABLE'; REPLICATE_IGNORE_DB : 'REPLICATE_IGNORE_DB'; REPLICATE_IGNORE_TABLE : 'REPLICATE_IGNORE_TABLE'; REPLICATE_REWRITE_DB : 'REPLICATE_REWRITE_DB'; REPLICATE_WILD_DO_TABLE : 'REPLICATE_WILD_DO_TABLE'; REPLICATE_WILD_IGNORE_TABLE : 'REPLICATE_WILD_IGNORE_TABLE'; REPLICATION : 'REPLICATION'; RESET : 'RESET'; RESTART : 'RESTART'; RESUME : 'RESUME'; RETURNED_SQLSTATE : 'RETURNED_SQLSTATE'; RETURNING : 'RETURNING'; RETURNS : 'RETURNS'; REUSE : 'REUSE'; ROLE : 'ROLE'; ROLLBACK : 'ROLLBACK'; ROLLUP : 'ROLLUP'; ROTATE : 'ROTATE'; ROW : 'ROW'; ROWS : 'ROWS'; ROW_FORMAT : 'ROW_FORMAT'; RTREE : 'RTREE'; SAVEPOINT : 'SAVEPOINT'; SCHEDULE : 'SCHEDULE'; SECURITY : 'SECURITY'; SEQUENCE : 'SEQUENCE'; SERVER : 'SERVER'; SESSION : 'SESSION'; SHARE : 'SHARE'; SHARED : 'SHARED'; SIGNED : 'SIGNED'; SIMPLE : 'SIMPLE'; SLAVE : 'SLAVE'; SLOW : 'SLOW'; SNAPSHOT : 'SNAPSHOT'; SOCKET : 'SOCKET'; SOME : 'SOME'; SONAME : 'SONAME'; SOUNDS : 'SOUNDS'; SOURCE : 'SOURCE'; SQL_AFTER_GTIDS : 'SQL_AFTER_GTIDS'; SQL_AFTER_MTS_GAPS : 'SQL_AFTER_MTS_GAPS'; SQL_BEFORE_GTIDS : 'SQL_BEFORE_GTIDS'; SQL_BUFFER_RESULT : 'SQL_BUFFER_RESULT'; SQL_CACHE : 'SQL_CACHE'; SQL_NO_CACHE : 'SQL_NO_CACHE'; SQL_THREAD : 'SQL_THREAD'; START : 'START'; STARTS : 'STARTS'; STATS_AUTO_RECALC : 'STATS_AUTO_RECALC'; STATS_PERSISTENT : 'STATS_PERSISTENT'; STATS_SAMPLE_PAGES : 'STATS_SAMPLE_PAGES'; STATUS : 'STATUS'; STOP : 'STOP'; STORAGE : 'STORAGE'; STORED : 'STORED'; STRING : 'STRING'; SUBCLASS_ORIGIN : 'SUBCLASS_ORIGIN'; SUBJECT : 'SUBJECT'; SUBPARTITION : 'SUBPARTITION'; SUBPARTITIONS : 'SUBPARTITIONS'; SUSPEND : 'SUSPEND'; SWAPS : 'SWAPS'; SWITCHES : 'SWITCHES'; TABLE_NAME : 'TABLE_NAME'; TABLESPACE : 'TABLESPACE'; TABLE_TYPE : 'TABLE_TYPE'; TEMPORARY : 'TEMPORARY'; TEMPTABLE : 'TEMPTABLE'; THAN : 'THAN'; TRADITIONAL : 'TRADITIONAL'; TRANSACTION : 'TRANSACTION'; TRANSACTIONAL : 'TRANSACTIONAL'; TRIGGERS : 'TRIGGERS'; TRUNCATE : 'TRUNCATE'; UNBOUNDED : 'UNBOUNDED'; UNDEFINED : 'UNDEFINED'; UNDOFILE : 'UNDOFILE'; UNDO_BUFFER_SIZE : 'UNDO_BUFFER_SIZE'; UNINSTALL : 'UNINSTALL'; UNKNOWN : 'UNKNOWN'; UNTIL : 'UNTIL'; UPGRADE : 'UPGRADE'; USER : 'USER'; USE_FRM : 'USE_FRM'; USER_RESOURCES : 'USER_RESOURCES'; VALIDATION : 'VALIDATION'; VALUE : 'VALUE'; VARIABLES : 'VARIABLES'; VIEW : 'VIEW'; VIRTUAL : 'VIRTUAL'; VISIBLE : 'VISIBLE'; WAIT : 'WAIT'; WARNINGS : 'WARNINGS'; WINDOW : 'WINDOW'; WITHOUT : 'WITHOUT'; WORK : 'WORK'; WRAPPER : 'WRAPPER'; X509 : 'X509'; XA : 'XA'; XML : 'XML'; YES : 'YES'; // Date format Keywords EUR : 'EUR'; USA : 'USA'; JIS : 'JIS'; ISO : 'ISO'; INTERNAL : 'INTERNAL'; // Interval type Keywords QUARTER : 'QUARTER'; MONTH : 'MONTH'; DAY : 'DAY'; HOUR : 'HOUR'; MINUTE : 'MINUTE'; WEEK : 'WEEK'; SECOND : 'SECOND'; MICROSECOND : 'MICROSECOND'; // Azure Database for MySQL Single Server instance: FIREWALL_RULES: 'FIREWALL_RULES'; // PRIVILEGES ADMIN : 'ADMIN'; APPLICATION_PASSWORD_ADMIN : 'APPLICATION_PASSWORD_ADMIN'; AUDIT_ABORT_EXEMPT : 'AUDIT_ABORT_EXEMPT'; AUDIT_ADMIN : 'AUDIT_ADMIN'; AUTHENTICATION_POLICY_ADMIN : 'AUTHENTICATION_POLICY_ADMIN'; BACKUP_ADMIN : 'BACKUP_ADMIN'; BINLOG_ADMIN : 'BINLOG_ADMIN'; BINLOG_ENCRYPTION_ADMIN : 'BINLOG_ENCRYPTION_ADMIN'; CLONE_ADMIN : 'CLONE_ADMIN'; CONNECTION_ADMIN : 'CONNECTION_ADMIN'; ENCRYPTION_KEY_ADMIN : 'ENCRYPTION_KEY_ADMIN'; EXECUTE : 'EXECUTE'; FILE : 'FILE'; FIREWALL_ADMIN : 'FIREWALL_ADMIN'; FIREWALL_EXEMPT : 'FIREWALL_EXEMPT'; FIREWALL_USER : 'FIREWALL_USER'; FLUSH_OPTIMIZER_COSTS : 'FLUSH_OPTIMIZER_COSTS'; FLUSH_STATUS : 'FLUSH_STATUS'; FLUSH_TABLES : 'FLUSH_TABLES'; FLUSH_USER_RESOURCES : 'FLUSH_USER_RESOURCES'; GROUP_REPLICATION_ADMIN : 'GROUP_REPLICATION_ADMIN'; INNODB_REDO_LOG_ARCHIVE : 'INNODB_REDO_LOG_ARCHIVE'; INNODB_REDO_LOG_ENABLE : 'INNODB_REDO_LOG_ENABLE'; INVOKE : 'INVOKE'; LAMBDA : 'LAMBDA'; NDB_STORED_USER : 'NDB_STORED_USER'; PASSWORDLESS_USER_ADMIN : 'PASSWORDLESS_USER_ADMIN'; PERSIST_RO_VARIABLES_ADMIN : 'PERSIST_RO_VARIABLES_ADMIN'; PRIVILEGES : 'PRIVILEGES'; PROCESS : 'PROCESS'; RELOAD : 'RELOAD'; REPLICATION_APPLIER : 'REPLICATION_APPLIER'; REPLICATION_SLAVE_ADMIN : 'REPLICATION_SLAVE_ADMIN'; RESOURCE_GROUP_ADMIN : 'RESOURCE_GROUP_ADMIN'; RESOURCE_GROUP_USER : 'RESOURCE_GROUP_USER'; ROLE_ADMIN : 'ROLE_ADMIN'; ROUTINE : 'ROUTINE'; S3 : 'S3'; SERVICE_CONNECTION_ADMIN : 'SERVICE_CONNECTION_ADMIN'; SESSION_VARIABLES_ADMIN : QUOTE_SYMB? 'SESSION_VARIABLES_ADMIN' QUOTE_SYMB?; SET_USER_ID : 'SET_USER_ID'; SHOW_ROUTINE : 'SHOW_ROUTINE'; SHUTDOWN : 'SHUTDOWN'; SUPER : 'SUPER'; SYSTEM_VARIABLES_ADMIN : 'SYSTEM_VARIABLES_ADMIN'; TABLES : 'TABLES'; TABLE_ENCRYPTION_ADMIN : 'TABLE_ENCRYPTION_ADMIN'; VERSION_TOKEN_ADMIN : 'VERSION_TOKEN_ADMIN'; XA_RECOVER_ADMIN : 'XA_RECOVER_ADMIN'; // Charsets ARMSCII8 : 'ARMSCII8'; ASCII : 'ASCII'; BIG5 : 'BIG5'; CP1250 : 'CP1250'; CP1251 : 'CP1251'; CP1256 : 'CP1256'; CP1257 : 'CP1257'; CP850 : 'CP850'; CP852 : 'CP852'; CP866 : 'CP866'; CP932 : 'CP932'; DEC8 : 'DEC8'; EUCJPMS : 'EUCJPMS'; EUCKR : 'EUCKR'; GB18030 : 'GB18030'; GB2312 : 'GB2312'; GBK : 'GBK'; GEOSTD8 : 'GEOSTD8'; GREEK : 'GREEK'; HEBREW : 'HEBREW'; HP8 : 'HP8'; KEYBCS2 : 'KEYBCS2'; KOI8R : 'KOI8R'; KOI8U : 'KOI8U'; LATIN1 : 'LATIN1'; LATIN2 : 'LATIN2'; LATIN5 : 'LATIN5'; LATIN7 : 'LATIN7'; MACCE : 'MACCE'; MACROMAN : 'MACROMAN'; SJIS : 'SJIS'; SWE7 : 'SWE7'; TIS620 : 'TIS620'; UCS2 : 'UCS2'; UJIS : 'UJIS'; UTF16 : 'UTF16'; UTF16LE : 'UTF16LE'; UTF32 : 'UTF32'; UTF8 : 'UTF8'; UTF8MB3 : 'UTF8MB3'; UTF8MB4 : 'UTF8MB4'; // DB Engines ARCHIVE : 'ARCHIVE'; BLACKHOLE : 'BLACKHOLE'; CSV : 'CSV'; FEDERATED : 'FEDERATED'; INNODB : 'INNODB'; MEMORY : 'MEMORY'; MRG_MYISAM : 'MRG_MYISAM'; MYISAM : 'MYISAM'; NDB : 'NDB'; NDBCLUSTER : 'NDBCLUSTER'; PERFORMANCE_SCHEMA : 'PERFORMANCE_SCHEMA'; TOKUDB : 'TOKUDB'; // Transaction Levels REPEATABLE : 'REPEATABLE'; COMMITTED : 'COMMITTED'; UNCOMMITTED : 'UNCOMMITTED'; SERIALIZABLE : 'SERIALIZABLE'; // Spatial data types GEOMETRYCOLLECTION : 'GEOMETRYCOLLECTION'; GEOMCOLLECTION : 'GEOMCOLLECTION'; GEOMETRY : 'GEOMETRY'; LINESTRING : 'LINESTRING'; MULTILINESTRING : 'MULTILINESTRING'; MULTIPOINT : 'MULTIPOINT'; MULTIPOLYGON : 'MULTIPOLYGON'; POINT : 'POINT'; POLYGON : 'POLYGON'; // Common function names ABS : 'ABS'; ACOS : 'ACOS'; ADDDATE : 'ADDDATE'; ADDTIME : 'ADDTIME'; AES_DECRYPT : 'AES_DECRYPT'; AES_ENCRYPT : 'AES_ENCRYPT'; AREA : 'AREA'; ASBINARY : 'ASBINARY'; ASIN : 'ASIN'; ASTEXT : 'ASTEXT'; ASWKB : 'ASWKB'; ASWKT : 'ASWKT'; ASYMMETRIC_DECRYPT : 'ASYMMETRIC_DECRYPT'; ASYMMETRIC_DERIVE : 'ASYMMETRIC_DERIVE'; ASYMMETRIC_ENCRYPT : 'ASYMMETRIC_ENCRYPT'; ASYMMETRIC_SIGN : 'ASYMMETRIC_SIGN'; ASYMMETRIC_VERIFY : 'ASYMMETRIC_VERIFY'; ATAN : 'ATAN'; ATAN2 : 'ATAN2'; BENCHMARK : 'BENCHMARK'; BIN : 'BIN'; BIT_COUNT : 'BIT_COUNT'; BIT_LENGTH : 'BIT_LENGTH'; BUFFER : 'BUFFER'; CATALOG_NAME : 'CATALOG_NAME'; CEIL : 'CEIL'; CEILING : 'CEILING'; CENTROID : 'CENTROID'; CHARACTER_LENGTH : 'CHARACTER_LENGTH'; CHARSET : 'CHARSET'; CHAR_LENGTH : 'CHAR_LENGTH'; COERCIBILITY : 'COERCIBILITY'; COLLATION : 'COLLATION'; COMPRESS : 'COMPRESS'; CONCAT : 'CONCAT'; CONCAT_WS : 'CONCAT_WS'; CONNECTION_ID : 'CONNECTION_ID'; CONV : 'CONV'; CONVERT_TZ : 'CONVERT_TZ'; COS : 'COS'; COT : 'COT'; CRC32 : 'CRC32'; CREATE_ASYMMETRIC_PRIV_KEY : 'CREATE_ASYMMETRIC_PRIV_KEY'; CREATE_ASYMMETRIC_PUB_KEY : 'CREATE_ASYMMETRIC_PUB_KEY'; CREATE_DH_PARAMETERS : 'CREATE_DH_PARAMETERS'; CREATE_DIGEST : 'CREATE_DIGEST'; CROSSES : 'CROSSES'; DATEDIFF : 'DATEDIFF'; DATE_FORMAT : 'DATE_FORMAT'; DAYNAME : 'DAYNAME'; DAYOFMONTH : 'DAYOFMONTH'; DAYOFWEEK : 'DAYOFWEEK'; DAYOFYEAR : 'DAYOFYEAR'; DECODE : 'DECODE'; DEGREES : 'DEGREES'; DES_DECRYPT : 'DES_DECRYPT'; DES_ENCRYPT : 'DES_ENCRYPT'; DIMENSION : 'DIMENSION'; DISJOINT : 'DISJOINT'; DISTANCE : 'DISTANCE'; ELT : 'ELT'; ENCODE : 'ENCODE'; ENCRYPT : 'ENCRYPT'; ENDPOINT : 'ENDPOINT'; ENGINE_ATTRIBUTE : 'ENGINE_ATTRIBUTE'; ENVELOPE : 'ENVELOPE'; EQUALS : 'EQUALS'; EXP : 'EXP'; EXPORT_SET : 'EXPORT_SET'; EXTERIORRING : 'EXTERIORRING'; EXTRACTVALUE : 'EXTRACTVALUE'; FIELD : 'FIELD'; FIND_IN_SET : 'FIND_IN_SET'; FLOOR : 'FLOOR'; FORMAT : 'FORMAT'; FOUND_ROWS : 'FOUND_ROWS'; FROM_BASE64 : 'FROM_BASE64'; FROM_DAYS : 'FROM_DAYS'; FROM_UNIXTIME : 'FROM_UNIXTIME'; GEOMCOLLFROMTEXT : 'GEOMCOLLFROMTEXT'; GEOMCOLLFROMWKB : 'GEOMCOLLFROMWKB'; GEOMETRYCOLLECTIONFROMTEXT : 'GEOMETRYCOLLECTIONFROMTEXT'; GEOMETRYCOLLECTIONFROMWKB : 'GEOMETRYCOLLECTIONFROMWKB'; GEOMETRYFROMTEXT : 'GEOMETRYFROMTEXT'; GEOMETRYFROMWKB : 'GEOMETRYFROMWKB'; GEOMETRYN : 'GEOMETRYN'; GEOMETRYTYPE : 'GEOMETRYTYPE'; GEOMFROMTEXT : 'GEOMFROMTEXT'; GEOMFROMWKB : 'GEOMFROMWKB'; GET_FORMAT : 'GET_FORMAT'; GET_LOCK : 'GET_LOCK'; GLENGTH : 'GLENGTH'; GREATEST : 'GREATEST'; GTID_SUBSET : 'GTID_SUBSET'; GTID_SUBTRACT : 'GTID_SUBTRACT'; HEX : 'HEX'; IFNULL : 'IFNULL'; INET6_ATON : 'INET6_ATON'; INET6_NTOA : 'INET6_NTOA'; INET_ATON : 'INET_ATON'; INET_NTOA : 'INET_NTOA'; INSTR : 'INSTR'; INTERIORRINGN : 'INTERIORRINGN'; INTERSECTS : 'INTERSECTS'; ISCLOSED : 'ISCLOSED'; ISEMPTY : 'ISEMPTY'; ISNULL : 'ISNULL'; ISSIMPLE : 'ISSIMPLE'; IS_FREE_LOCK : 'IS_FREE_LOCK'; IS_IPV4 : 'IS_IPV4'; IS_IPV4_COMPAT : 'IS_IPV4_COMPAT'; IS_IPV4_MAPPED : 'IS_IPV4_MAPPED'; IS_IPV6 : 'IS_IPV6'; IS_USED_LOCK : 'IS_USED_LOCK'; LAST_INSERT_ID : 'LAST_INSERT_ID'; LCASE : 'LCASE'; LEAST : 'LEAST'; LENGTH : 'LENGTH'; LINEFROMTEXT : 'LINEFROMTEXT'; LINEFROMWKB : 'LINEFROMWKB'; LINESTRINGFROMTEXT : 'LINESTRINGFROMTEXT'; LINESTRINGFROMWKB : 'LINESTRINGFROMWKB'; LN : 'LN'; LOAD_FILE : 'LOAD_FILE'; LOCATE : 'LOCATE'; LOG : 'LOG'; LOG10 : 'LOG10'; LOG2 : 'LOG2'; LOWER : 'LOWER'; LPAD : 'LPAD'; LTRIM : 'LTRIM'; MAKEDATE : 'MAKEDATE'; MAKETIME : 'MAKETIME'; MAKE_SET : 'MAKE_SET'; MASTER_POS_WAIT : 'MASTER_POS_WAIT'; MBRCONTAINS : 'MBRCONTAINS'; MBRDISJOINT : 'MBRDISJOINT'; MBREQUAL : 'MBREQUAL'; MBRINTERSECTS : 'MBRINTERSECTS'; MBROVERLAPS : 'MBROVERLAPS'; MBRTOUCHES : 'MBRTOUCHES'; MBRWITHIN : 'MBRWITHIN'; MD5 : 'MD5'; MLINEFROMTEXT : 'MLINEFROMTEXT'; MLINEFROMWKB : 'MLINEFROMWKB'; MONTHNAME : 'MONTHNAME'; MPOINTFROMTEXT : 'MPOINTFROMTEXT'; MPOINTFROMWKB : 'MPOINTFROMWKB'; MPOLYFROMTEXT : 'MPOLYFROMTEXT'; MPOLYFROMWKB : 'MPOLYFROMWKB'; MULTILINESTRINGFROMTEXT : 'MULTILINESTRINGFROMTEXT'; MULTILINESTRINGFROMWKB : 'MULTILINESTRINGFROMWKB'; MULTIPOINTFROMTEXT : 'MULTIPOINTFROMTEXT'; MULTIPOINTFROMWKB : 'MULTIPOINTFROMWKB'; MULTIPOLYGONFROMTEXT : 'MULTIPOLYGONFROMTEXT'; MULTIPOLYGONFROMWKB : 'MULTIPOLYGONFROMWKB'; NAME_CONST : 'NAME_CONST'; NULLIF : 'NULLIF'; NUMGEOMETRIES : 'NUMGEOMETRIES'; NUMINTERIORRINGS : 'NUMINTERIORRINGS'; NUMPOINTS : 'NUMPOINTS'; OCT : 'OCT'; OCTET_LENGTH : 'OCTET_LENGTH'; ORD : 'ORD'; OVERLAPS : 'OVERLAPS'; PERCONA_SEQUENCE_TABLE : 'PERCONA_SEQUENCE_TABLE'; PERIOD_ADD : 'PERIOD_ADD'; PERIOD_DIFF : 'PERIOD_DIFF'; PI : 'PI'; POINTFROMTEXT : 'POINTFROMTEXT'; POINTFROMWKB : 'POINTFROMWKB'; POINTN : 'POINTN'; POLYFROMTEXT : 'POLYFROMTEXT'; POLYFROMWKB : 'POLYFROMWKB'; POLYGONFROMTEXT : 'POLYGONFROMTEXT'; POLYGONFROMWKB : 'POLYGONFROMWKB'; POW : 'POW'; POWER : 'POWER'; QUOTE : 'QUOTE'; RADIANS : 'RADIANS'; RAND : 'RAND'; RANDOM : 'RANDOM'; RANDOM_BYTES : 'RANDOM_BYTES'; RELEASE_LOCK : 'RELEASE_LOCK'; REVERSE : 'REVERSE'; ROUND : 'ROUND'; ROW_COUNT : 'ROW_COUNT'; RPAD : 'RPAD'; RTRIM : 'RTRIM'; SEC_TO_TIME : 'SEC_TO_TIME'; SECONDARY_ENGINE : 'SECONDARY_ENGINE'; SECONDARY_ENGINE_ATTRIBUTE : 'SECONDARY_ENGINE_ATTRIBUTE'; SEQUENCE_TABLE : 'SEQUENCE_TABLE'; SESSION_USER : 'SESSION_USER'; SHA : 'SHA'; SHA1 : 'SHA1'; SHA2 : 'SHA2'; SCHEMA_NAME : 'SCHEMA_NAME'; SIGN : 'SIGN'; SIN : 'SIN'; SLEEP : 'SLEEP'; SOUNDEX : 'SOUNDEX'; SQL_THREAD_WAIT_AFTER_GTIDS : 'SQL_THREAD_WAIT_AFTER_GTIDS'; SQRT : 'SQRT'; SRID : 'SRID'; STARTPOINT : 'STARTPOINT'; STRCMP : 'STRCMP'; STR_TO_DATE : 'STR_TO_DATE'; ST_AREA : 'ST_AREA'; ST_ASBINARY : 'ST_ASBINARY'; ST_ASTEXT : 'ST_ASTEXT'; ST_ASWKB : 'ST_ASWKB'; ST_ASWKT : 'ST_ASWKT'; ST_BUFFER : 'ST_BUFFER'; ST_CENTROID : 'ST_CENTROID'; ST_CONTAINS : 'ST_CONTAINS'; ST_CROSSES : 'ST_CROSSES'; ST_DIFFERENCE : 'ST_DIFFERENCE'; ST_DIMENSION : 'ST_DIMENSION'; ST_DISJOINT : 'ST_DISJOINT'; ST_DISTANCE : 'ST_DISTANCE'; ST_ENDPOINT : 'ST_ENDPOINT'; ST_ENVELOPE : 'ST_ENVELOPE'; ST_EQUALS : 'ST_EQUALS'; ST_EXTERIORRING : 'ST_EXTERIORRING'; ST_GEOMCOLLFROMTEXT : 'ST_GEOMCOLLFROMTEXT'; ST_GEOMCOLLFROMTXT : 'ST_GEOMCOLLFROMTXT'; ST_GEOMCOLLFROMWKB : 'ST_GEOMCOLLFROMWKB'; ST_GEOMETRYCOLLECTIONFROMTEXT : 'ST_GEOMETRYCOLLECTIONFROMTEXT'; ST_GEOMETRYCOLLECTIONFROMWKB : 'ST_GEOMETRYCOLLECTIONFROMWKB'; ST_GEOMETRYFROMTEXT : 'ST_GEOMETRYFROMTEXT'; ST_GEOMETRYFROMWKB : 'ST_GEOMETRYFROMWKB'; ST_GEOMETRYN : 'ST_GEOMETRYN'; ST_GEOMETRYTYPE : 'ST_GEOMETRYTYPE'; ST_GEOMFROMTEXT : 'ST_GEOMFROMTEXT'; ST_GEOMFROMWKB : 'ST_GEOMFROMWKB'; ST_INTERIORRINGN : 'ST_INTERIORRINGN'; ST_INTERSECTION : 'ST_INTERSECTION'; ST_INTERSECTS : 'ST_INTERSECTS'; ST_ISCLOSED : 'ST_ISCLOSED'; ST_ISEMPTY : 'ST_ISEMPTY'; ST_ISSIMPLE : 'ST_ISSIMPLE'; ST_LINEFROMTEXT : 'ST_LINEFROMTEXT'; ST_LINEFROMWKB : 'ST_LINEFROMWKB'; ST_LINESTRINGFROMTEXT : 'ST_LINESTRINGFROMTEXT'; ST_LINESTRINGFROMWKB : 'ST_LINESTRINGFROMWKB'; ST_NUMGEOMETRIES : 'ST_NUMGEOMETRIES'; ST_NUMINTERIORRING : 'ST_NUMINTERIORRING'; ST_NUMINTERIORRINGS : 'ST_NUMINTERIORRINGS'; ST_NUMPOINTS : 'ST_NUMPOINTS'; ST_OVERLAPS : 'ST_OVERLAPS'; ST_POINTFROMTEXT : 'ST_POINTFROMTEXT'; ST_POINTFROMWKB : 'ST_POINTFROMWKB'; ST_POINTN : 'ST_POINTN'; ST_POLYFROMTEXT : 'ST_POLYFROMTEXT'; ST_POLYFROMWKB : 'ST_POLYFROMWKB'; ST_POLYGONFROMTEXT : 'ST_POLYGONFROMTEXT'; ST_POLYGONFROMWKB : 'ST_POLYGONFROMWKB'; ST_SRID : 'ST_SRID'; ST_STARTPOINT : 'ST_STARTPOINT'; ST_SYMDIFFERENCE : 'ST_SYMDIFFERENCE'; ST_TOUCHES : 'ST_TOUCHES'; ST_UNION : 'ST_UNION'; ST_WITHIN : 'ST_WITHIN'; ST_X : 'ST_X'; ST_Y : 'ST_Y'; STRING_TO_VECTOR : 'STRING_TO_VECTOR'; SUBDATE : 'SUBDATE'; SUBSTRING_INDEX : 'SUBSTRING_INDEX'; SUBTIME : 'SUBTIME'; SYSTEM_USER : 'SYSTEM_USER'; TAN : 'TAN'; TELEMETRY_LOG_ADMIN : 'TELEMETRY_LOG_ADMIN'; TIMEDIFF : 'TIMEDIFF'; TIMESTAMPADD : 'TIMESTAMPADD'; TIMESTAMPDIFF : 'TIMESTAMPDIFF'; TIME_FORMAT : 'TIME_FORMAT'; TIME_TO_SEC : 'TIME_TO_SEC'; TOUCHES : 'TOUCHES'; TO_BASE64 : 'TO_BASE64'; TO_DAYS : 'TO_DAYS'; TO_SECONDS : 'TO_SECONDS'; TP_CONNECTION_ADMIN : 'TP_CONNECTION_ADMIN'; UCASE : 'UCASE'; UNCOMPRESS : 'UNCOMPRESS'; UNCOMPRESSED_LENGTH : 'UNCOMPRESSED_LENGTH'; UNHEX : 'UNHEX'; UNIX_TIMESTAMP : 'UNIX_TIMESTAMP'; UPDATEXML : 'UPDATEXML'; UPPER : 'UPPER'; UUID : 'UUID'; UUID_SHORT : 'UUID_SHORT'; VALIDATE_PASSWORD_STRENGTH : 'VALIDATE_PASSWORD_STRENGTH'; VECTOR_DIM : 'VECTOR_DIM'; VECTOR_TO_STRING : 'VECTOR_TO_STRING'; VERSION : 'VERSION'; WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS : 'WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS'; WEEKDAY : 'WEEKDAY'; WEEKOFYEAR : 'WEEKOFYEAR'; WEIGHT_STRING : 'WEIGHT_STRING'; WITHIN : 'WITHIN'; YEARWEEK : 'YEARWEEK'; Y_FUNCTION : 'Y'; X_FUNCTION : 'X'; // Operators // Operators. Assigns VAR_ASSIGN : ':='; PLUS_ASSIGN : '+='; MINUS_ASSIGN : '-='; MULT_ASSIGN : '*='; DIV_ASSIGN : '/='; MOD_ASSIGN : '%='; AND_ASSIGN : '&='; XOR_ASSIGN : '^='; OR_ASSIGN : '|='; // Operators. Arithmetics STAR : '*'; DIVIDE : '/'; MODULE : '%'; PLUS : '+'; MINUS : '-'; DIV : 'DIV'; MOD : 'MOD'; // Operators. Comparation EQUAL_SYMBOL : '='; GREATER_SYMBOL : '>'; LESS_SYMBOL : '<'; EXCLAMATION_SYMBOL : '!'; // Operators. Bit BIT_NOT_OP : '~'; BIT_OR_OP : '|'; BIT_AND_OP : '&'; BIT_XOR_OP : '^'; // Constructors symbols DOT : '.'; LR_BRACKET : '('; RR_BRACKET : ')'; COMMA : ','; SEMI : ';'; AT_SIGN : '@'; ZERO_DECIMAL : '0'; ONE_DECIMAL : '1'; TWO_DECIMAL : '2'; SINGLE_QUOTE_SYMB : '\''; DOUBLE_QUOTE_SYMB : '"'; REVERSE_QUOTE_SYMB : '`'; COLON_SYMB : ':'; fragment QUOTE_SYMB: SINGLE_QUOTE_SYMB | DOUBLE_QUOTE_SYMB | REVERSE_QUOTE_SYMB; // Charsets CHARSET_REVERSE_QOUTE_STRING: '`' CHARSET_NAME '`'; // File's sizes FILESIZE_LITERAL: DEC_DIGIT+ ('K' | 'M' | 'G' | 'T'); // Literal Primitives START_NATIONAL_STRING_LITERAL : 'N' SQUOTA_STRING; STRING_LITERAL : DQUOTA_STRING | SQUOTA_STRING | BQUOTA_STRING; DECIMAL_LITERAL : DEC_DIGIT+; HEXADECIMAL_LITERAL : 'X' '\'' (HEX_DIGIT HEX_DIGIT)+ '\'' | '0X' HEX_DIGIT+; REAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT* | DEC_DIGIT+ '.' EXPONENT_NUM_PART | (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART) | DEC_DIGIT+ EXPONENT_NUM_PART ; NULL_SPEC_LITERAL : '\\' 'N'; BIT_STRING : BIT_STRING_L; STRING_CHARSET_NAME : '_' CHARSET_NAME; // Hack for dotID // Prevent recognize string: .123somelatin AS ((.123), FLOAT_LITERAL), ((somelatin), ID) // it must recoginze: .123somelatin AS ((.), DOT), (123somelatin, ID) DOT_ID: '.' ID_LITERAL; // Identifiers ID: ID_LITERAL; // DOUBLE_QUOTE_ID: '"' ~'"'+ '"'; REVERSE_QUOTE_ID : BQUOTA_STRING; HOST_IP_ADDRESS : (AT_SIGN IP_ADDRESS); LOCAL_ID : AT_SIGN ( STRING_LITERAL | [A-Z0-9._$\u0080-\uFFFF]+); GLOBAL_ID : AT_SIGN AT_SIGN ( [A-Z0-9._$\u0080-\uFFFF]+ | BQUOTA_STRING); // Fragments for Literal primitives fragment CHARSET_NAME: ARMSCII8 | ASCII | BIG5 | BINARY | CP1250 | CP1251 | CP1256 | CP1257 | CP850 | CP852 | CP866 | CP932 | DEC8 | EUCJPMS | EUCKR | GB2312 | GBK | GEOSTD8 | GREEK | HEBREW | HP8 | KEYBCS2 | KOI8R | KOI8U | LATIN1 | LATIN2 | LATIN5 | LATIN7 | MACCE | MACROMAN | SJIS | SWE7 | TIS620 | UCS2 | UJIS | UTF16 | UTF16LE | UTF32 | UTF8 | UTF8MB3 | UTF8MB4 ; fragment EXPONENT_NUM_PART : 'E' [-+]? DEC_DIGIT+; fragment ID_LITERAL : [A-Z_$0-9\u0080-\uFFFF]*? [A-Z_$\u0080-\uFFFF]+? [A-Z_$0-9\u0080-\uFFFF]*; fragment DQUOTA_STRING : '"' ( '\\' . | '""' | ~('"' | '\\'))* '"'; fragment SQUOTA_STRING : '\'' ('\\' . | '\'\'' | ~('\'' | '\\'))* '\''; fragment BQUOTA_STRING : '`' ( ~'`' | '``')* '`'; fragment HEX_DIGIT : [0-9A-F]; fragment DEC_DIGIT : [0-9]; fragment BIT_STRING_L : 'B' '\'' [01]+ '\''; fragment IP_ADDRESS : [0-9]+ '.' [0-9.]+ | [0-9A-F]* ':' [0-9A-F]* ':' [0-9A-F:]+; // Last tokens must generate Errors ERROR_RECONGNIGION: . -> channel(ERRORCHANNEL); ================================================ FILE: superior-mysql-parser/src/main/antlr4/io/github/melin/superior/parser/mysql/antlr4/MySqlParser.g4 ================================================ /* MySQL (Positive Technologies) grammar The MIT License (MIT). Copyright (c) 2015-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. Copyright (c) 2017, Ivan Khudyashev (IHudyashov@ptsecurity.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false // $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging parser grammar MySqlParser; options { tokenVocab = MySqlLexer; } // Top Level Description root : sqlStatements? (MINUS MINUS)? EOF ; sqlStatements : (sqlStatement (MINUS MINUS)? SEMI? | emptyStatement_)* ( sqlStatement ((MINUS MINUS)? SEMI)? | emptyStatement_ ) ; sqlStatement : ddlStatement | withStatement? dmlStatement | transactionStatement | replicationStatement | preparedStatement | administrationStatement | utilityStatement ; emptyStatement_ : SEMI ; ddlStatement : createDatabase | createEvent | createIndex | createLogfileGroup | createProcedure | createFunction | createServer | createTable | createTablespaceInnodb | createTablespaceNdb | createTrigger | createView | createRole | alterDatabase | alterEvent | alterFunction | alterInstance | alterLogfileGroup | alterProcedure | alterServer | alterTable | alterTablespace | alterView | dropDatabase | dropEvent | dropIndex | dropLogfileGroup | dropProcedure | dropFunction | dropServer | dropTable | dropTablespace | dropTrigger | dropView | dropRole | setRole | renameTable | truncateTable ; dmlStatement : selectStatement | insertStatement | updateStatement | deleteStatement | replaceStatement | callStatement | loadDataStatement | loadXmlStatement | doStatement | handlerStatement | valuesStatement | tableStatement ; transactionStatement : startTransaction | beginWork | commitWork | rollbackWork | savepointStatement | rollbackStatement | releaseStatement | lockTables | unlockTables ; replicationStatement : changeMaster | changeReplicationFilter | purgeBinaryLogs | resetMaster | resetSlave | startSlave | stopSlave | startGroupReplication | stopGroupReplication | xaStartTransaction | xaEndTransaction | xaPrepareStatement | xaCommitWork | xaRollbackWork | xaRecoverWork ; preparedStatement : prepareStatement | executeStatement | deallocatePrepare ; // remark: NOT INCLUDED IN sqlStatement, but include in body // of routine's statements compoundStatement : blockStatement | caseStatement | ifStatement | leaveStatement | loopStatement | repeatStatement | whileStatement | iterateStatement | returnStatement | cursorStatement ; administrationStatement : alterUser | createUser | dropUser | grantStatement | grantProxy | renameUser | revokeStatement | revokeProxy | analyzeTable | checkTable | checksumTable | optimizeTable | repairTable | createUdfunction | installPlugin | uninstallPlugin | setStatement | showStatement | binlogStatement | cacheIndexStatement | flushStatement | killStatement | loadIndexIntoCache | resetStatement | shutdownStatement ; utilityStatement : simpleDescribeStatement | fullDescribeStatement | helpStatement | useStatement | signalStatement | resignalStatement | diagnosticsStatement ; // Data Definition Language // Create statements createDatabase : CREATE dbFormat = (DATABASE | SCHEMA) ifNotExists? uid createDatabaseOption* ; createEvent : CREATE ownerStatement? EVENT ifNotExists? fullId ON SCHEDULE scheduleExpression ( ON COMPLETION NOT? PRESERVE )? enableType? (COMMENT STRING_LITERAL)? DO routineBody ; createIndex : CREATE intimeAction = (ONLINE | OFFLINE)? indexCategory = (UNIQUE | FULLTEXT | SPATIAL)? INDEX uid indexType? ON tableName indexColumnNames indexOption* ( ALGORITHM EQUAL_SYMBOL? algType = (DEFAULT | INPLACE | COPY) | LOCK EQUAL_SYMBOL? lockType = (DEFAULT | NONE | SHARED | EXCLUSIVE) )* ; createLogfileGroup : CREATE LOGFILE GROUP uid ADD UNDOFILE undoFile = STRING_LITERAL ( INITIAL_SIZE '='? initSize = fileSizeLiteral )? (UNDO_BUFFER_SIZE '='? undoSize = fileSizeLiteral)? ( REDO_BUFFER_SIZE '='? redoSize = fileSizeLiteral )? (NODEGROUP '='? uid)? WAIT? (COMMENT '='? comment = STRING_LITERAL)? ENGINE '='? engineName ; createProcedure : CREATE ownerStatement? PROCEDURE ifNotExists? fullId '(' procedureParameter? (',' procedureParameter)* ')' routineOption* routineBody ; createFunction : CREATE ownerStatement? AGGREGATE? FUNCTION ifNotExists? fullId '(' functionParameter? ( ',' functionParameter )* ')' RETURNS dataType routineOption* (routineBody | returnStatement) ; createRole : CREATE ROLE ifNotExists? roleName (',' roleName)* ; createServer : CREATE SERVER uid FOREIGN DATA WRAPPER wrapperName = (MYSQL | STRING_LITERAL) OPTIONS '(' serverOption ( ',' serverOption )* ')' ; createTable : CREATE TEMPORARY? TABLE ifNotExists? tableName ( LIKE tableName | '(' LIKE parenthesisTable = tableName ')' ) # copyCreateTable | CREATE TEMPORARY? TABLE ifNotExists? tableName createDefinitions? ( tableOption (','? tableOption)* )? partitionDefinitions? keyViolate = (IGNORE | REPLACE)? AS? selectStatement # queryCreateTable | CREATE TEMPORARY? TABLE ifNotExists? tableName createDefinitions ( tableOption (','? tableOption)* )? partitionDefinitions? # columnCreateTable ; createTablespaceInnodb : CREATE TABLESPACE uid ADD DATAFILE datafile = STRING_LITERAL ( FILE_BLOCK_SIZE '=' fileBlockSize = fileSizeLiteral )? (ENGINE '='? engineName)? ; createTablespaceNdb : CREATE TABLESPACE uid ADD DATAFILE datafile = STRING_LITERAL USE LOGFILE GROUP uid ( EXTENT_SIZE '='? extentSize = fileSizeLiteral )? (INITIAL_SIZE '='? initialSize = fileSizeLiteral)? ( AUTOEXTEND_SIZE '='? autoextendSize = fileSizeLiteral )? (MAX_SIZE '='? maxSize = fileSizeLiteral)? (NODEGROUP '='? uid)? WAIT? ( COMMENT '='? comment = STRING_LITERAL )? ENGINE '='? engineName ; createTrigger : CREATE ownerStatement? TRIGGER ifNotExists? thisTrigger = fullId triggerTime = ( BEFORE | AFTER ) triggerEvent = (INSERT | UPDATE | DELETE) ON tableName FOR EACH ROW ( triggerPlace = (FOLLOWS | PRECEDES) otherTrigger = fullId )? routineBody ; withClause : WITH RECURSIVE? commonTableExpressions ; commonTableExpressions : cteName ('(' cteColumnName (',' cteColumnName)* ')')? AS '(' dmlStatement ')' ( ',' commonTableExpressions )? ; cteName : uid ; cteColumnName : uid ; createView : CREATE orReplace? (ALGORITHM '=' algType = (UNDEFINED | MERGE | TEMPTABLE))? ownerStatement? ( SQL SECURITY secContext = (DEFINER | INVOKER) )? VIEW fullId ('(' uidList ')')? AS ( '(' withClause? selectStatement ')' | withClause? selectStatement (WITH checkOption = (CASCADED | LOCAL)? CHECK OPTION)? ) ; // details createDatabaseOption : DEFAULT? charSet '='? (charsetName | DEFAULT) | DEFAULT? COLLATE '='? collationName | DEFAULT? ENCRYPTION '='? STRING_LITERAL | READ ONLY '='? (DEFAULT | ZERO_DECIMAL | ONE_DECIMAL) ; charSet : CHARACTER SET | CHARSET | CHAR SET ; currentUserExpression : CURRENT_USER ('(' ')')? ; ownerStatement : DEFINER '=' (userName | currentUserExpression) ; scheduleExpression : AT timestampValue intervalExpr* # preciseSchedule | EVERY (decimalLiteral | expression) intervalType ( STARTS startTimestamp = timestampValue (startIntervals += intervalExpr)* )? (ENDS endTimestamp = timestampValue (endIntervals += intervalExpr)*)? # intervalSchedule ; timestampValue : CURRENT_TIMESTAMP | stringLiteral | decimalLiteral | expression ; intervalExpr : '+' INTERVAL (decimalLiteral | expression) intervalType ; intervalType : intervalTypeBase | YEAR | YEAR_MONTH | DAY_HOUR | DAY_MINUTE | DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND | SECOND_MICROSECOND | MINUTE_MICROSECOND | HOUR_MICROSECOND | DAY_MICROSECOND ; enableType : ENABLE | DISABLE | DISABLE ON SLAVE ; indexType : USING (BTREE | HASH) ; indexOption : KEY_BLOCK_SIZE EQUAL_SYMBOL? fileSizeLiteral | indexType | WITH PARSER uid | COMMENT STRING_LITERAL | (VISIBLE | INVISIBLE) | ENGINE_ATTRIBUTE EQUAL_SYMBOL? STRING_LITERAL | SECONDARY_ENGINE_ATTRIBUTE EQUAL_SYMBOL? STRING_LITERAL ; procedureParameter : direction = (IN | OUT | INOUT)? uid dataType ; functionParameter : uid dataType ; routineOption : COMMENT STRING_LITERAL # routineComment | LANGUAGE SQL # routineLanguage | NOT? DETERMINISTIC # routineBehavior | ( CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA) # routineData | SQL SECURITY context = (DEFINER | INVOKER) # routineSecurity ; serverOption : HOST STRING_LITERAL | DATABASE STRING_LITERAL | USER STRING_LITERAL | PASSWORD STRING_LITERAL | SOCKET STRING_LITERAL | OWNER STRING_LITERAL | PORT decimalLiteral ; createDefinitions : '(' createDefinition (',' createDefinition)* ')' ; createDefinition : fullColumnName columnDefinition # columnDeclaration | tableConstraint NOT? ENFORCED? # constraintDeclaration | indexColumnDefinition # indexDeclaration ; columnDefinition : dataType columnConstraint* NOT? ENFORCED? ; columnConstraint : nullNotnull # nullColumnConstraint | DEFAULT defaultValue # defaultColumnConstraint | VISIBLE # visibilityColumnConstraint | INVISIBLE # invisibilityColumnConstraint | (AUTO_INCREMENT | ON UPDATE currentTimestamp) # autoIncrementColumnConstraint | PRIMARY? KEY # primaryKeyColumnConstraint | CLUSTERING KEY # clusteringKeyColumnConstraint // Tokudb-specific only | UNIQUE KEY? # uniqueKeyColumnConstraint | COMMENT STRING_LITERAL # commentColumnConstraint | COLUMN_FORMAT colformat = (FIXED | DYNAMIC | DEFAULT) # formatColumnConstraint | STORAGE storageval = (DISK | MEMORY | DEFAULT) # storageColumnConstraint | referenceDefinition # referenceColumnConstraint | COLLATE collationName # collateColumnConstraint | (GENERATED ALWAYS)? AS '(' expression ')' (VIRTUAL | STORED)? # generatedColumnConstraint | SERIAL DEFAULT VALUE # serialDefaultColumnConstraint | (CONSTRAINT name = uid?)? CHECK '(' expression ')' # checkColumnConstraint ; tableConstraint : (CONSTRAINT name = uid?)? PRIMARY KEY index = uid? indexType? indexColumnNames indexOption* # primaryKeyTableConstraint | (CONSTRAINT name = uid?)? UNIQUE indexFormat = (INDEX | KEY)? index = uid? indexType? indexColumnNames indexOption* # uniqueKeyTableConstraint | (CONSTRAINT name = uid?)? FOREIGN KEY index = uid? indexColumnNames referenceDefinition # foreignKeyTableConstraint | (CONSTRAINT name = uid?)? CHECK '(' expression ')' # checkTableConstraint | CLUSTERING KEY index = uid? indexColumnNames # clusteringKeyTableConstraint // Tokudb-specific only ; referenceDefinition : REFERENCES tableName indexColumnNames? (MATCH matchType = (FULL | PARTIAL | SIMPLE))? referenceAction? ; referenceAction : ON DELETE onDelete = referenceControlType (ON UPDATE onUpdate = referenceControlType)? | ON UPDATE onUpdate = referenceControlType (ON DELETE onDelete = referenceControlType)? ; referenceControlType : RESTRICT | CASCADE | SET NULL_LITERAL | NO ACTION | SET DEFAULT ; indexColumnDefinition : indexFormat = (INDEX | KEY) uid? indexType? indexColumnNames indexOption* # simpleIndexDeclaration | (FULLTEXT | SPATIAL) indexFormat = (INDEX | KEY)? uid? indexColumnNames indexOption* # specialIndexDeclaration ; tableOption : ENGINE '='? engineName? # tableOptionEngine | ENGINE_ATTRIBUTE '='? STRING_LITERAL # tableOptionEngineAttribute | AUTOEXTEND_SIZE '='? decimalLiteral # tableOptionAutoextendSize | AUTO_INCREMENT '='? decimalLiteral # tableOptionAutoIncrement | AVG_ROW_LENGTH '='? decimalLiteral # tableOptionAverage | DEFAULT? charSet '='? (charsetName | DEFAULT) # tableOptionCharset | (CHECKSUM | PAGE_CHECKSUM) '='? boolValue = ('0' | '1') # tableOptionChecksum | DEFAULT? COLLATE '='? collationName # tableOptionCollate | COMMENT '='? STRING_LITERAL # tableOptionComment | COMPRESSION '='? (STRING_LITERAL | ID) # tableOptionCompression | CONNECTION '='? STRING_LITERAL # tableOptionConnection | (DATA | INDEX) DIRECTORY '='? STRING_LITERAL # tableOptionDataDirectory | DELAY_KEY_WRITE '='? boolValue = ('0' | '1') # tableOptionDelay | ENCRYPTION '='? STRING_LITERAL # tableOptionEncryption | (PAGE_COMPRESSED | STRING_LITERAL) '='? ('0' | '1') # tableOptionPageCompressed | (PAGE_COMPRESSION_LEVEL | STRING_LITERAL) '='? decimalLiteral # tableOptionPageCompressionLevel | ENCRYPTION_KEY_ID '='? decimalLiteral # tableOptionEncryptionKeyId | INDEX DIRECTORY '='? STRING_LITERAL # tableOptionIndexDirectory | INSERT_METHOD '='? insertMethod = (NO | FIRST | LAST) # tableOptionInsertMethod | KEY_BLOCK_SIZE '='? fileSizeLiteral # tableOptionKeyBlockSize | MAX_ROWS '='? decimalLiteral # tableOptionMaxRows | MIN_ROWS '='? decimalLiteral # tableOptionMinRows | PACK_KEYS '='? extBoolValue = ('0' | '1' | DEFAULT) # tableOptionPackKeys | PASSWORD '='? STRING_LITERAL # tableOptionPassword | ROW_FORMAT '='? rowFormat = ( DEFAULT | DYNAMIC | FIXED | COMPRESSED | REDUNDANT | COMPACT | ID ) # tableOptionRowFormat | START TRANSACTION # tableOptionStartTransaction | SECONDARY_ENGINE '='? (ID | STRING_LITERAL) # tableOptionSecondaryEngine // HeatWave-specific only | SECONDARY_ENGINE_ATTRIBUTE '='? STRING_LITERAL # tableOptionSecondaryEngineAttribute | STATS_AUTO_RECALC '='? extBoolValue = (DEFAULT | '0' | '1') # tableOptionRecalculation | STATS_PERSISTENT '='? extBoolValue = (DEFAULT | '0' | '1') # tableOptionPersistent | STATS_SAMPLE_PAGES '='? (DEFAULT | decimalLiteral) # tableOptionSamplePage | TABLESPACE uid tablespaceStorage? # tableOptionTablespace | TABLE_TYPE '=' tableType # tableOptionTableType | tablespaceStorage # tableOptionTablespace | TRANSACTIONAL '='? ('0' | '1') # tableOptionTransactional | UNION '='? '(' tables ')' # tableOptionUnion ; tableType : MYSQL | ODBC ; tablespaceStorage : STORAGE (DISK | MEMORY | DEFAULT) ; partitionDefinitions : PARTITION BY partitionFunctionDefinition (PARTITIONS count = decimalLiteral)? ( SUBPARTITION BY subpartitionFunctionDefinition (SUBPARTITIONS subCount = decimalLiteral)? )? ('(' partitionDefinition (',' partitionDefinition)* ')')? ; partitionFunctionDefinition : LINEAR? HASH '(' expression ')' # partitionFunctionHash | LINEAR? KEY (ALGORITHM '=' algType = ('1' | '2'))? '(' uidList? ')' # partitionFunctionKey // Optional uidList for MySQL only | RANGE ('(' expression ')' | COLUMNS '(' uidList ')') # partitionFunctionRange | LIST ('(' expression ')' | COLUMNS '(' uidList ')') # partitionFunctionList ; subpartitionFunctionDefinition : LINEAR? HASH '(' expression ')' # subPartitionFunctionHash | LINEAR? KEY (ALGORITHM '=' algType = ('1' | '2'))? '(' uidList ')' # subPartitionFunctionKey ; partitionDefinition : PARTITION uid VALUES LESS THAN '(' partitionDefinerAtom (',' partitionDefinerAtom)* ')' partitionOption* ( '(' subpartitionDefinition (',' subpartitionDefinition)* ')' )? # partitionComparison | PARTITION uid VALUES LESS THAN partitionDefinerAtom partitionOption* ( '(' subpartitionDefinition (',' subpartitionDefinition)* ')' )? # partitionComparison | PARTITION uid VALUES IN '(' partitionDefinerAtom (',' partitionDefinerAtom)* ')' partitionOption* ( '(' subpartitionDefinition (',' subpartitionDefinition)* ')' )? # partitionListAtom | PARTITION uid VALUES IN '(' partitionDefinerVector (',' partitionDefinerVector)* ')' partitionOption* ( '(' subpartitionDefinition (',' subpartitionDefinition)* ')' )? # partitionListVector | PARTITION uid partitionOption* ('(' subpartitionDefinition (',' subpartitionDefinition)* ')')? # partitionSimple ; partitionDefinerAtom : constant | expression | MAXVALUE ; partitionDefinerVector : '(' partitionDefinerAtom (',' partitionDefinerAtom)+ ')' ; subpartitionDefinition : SUBPARTITION uid partitionOption* ; partitionOption : DEFAULT? STORAGE? ENGINE '='? engineName # partitionOptionEngine | COMMENT '='? comment = STRING_LITERAL # partitionOptionComment | DATA DIRECTORY '='? dataDirectory = STRING_LITERAL # partitionOptionDataDirectory | INDEX DIRECTORY '='? indexDirectory = STRING_LITERAL # partitionOptionIndexDirectory | MAX_ROWS '='? maxRows = decimalLiteral # partitionOptionMaxRows | MIN_ROWS '='? minRows = decimalLiteral # partitionOptionMinRows | TABLESPACE '='? tablespace = uid # partitionOptionTablespace | NODEGROUP '='? nodegroup = uid # partitionOptionNodeGroup ; // Alter statements alterDatabase : ALTER dbFormat = (DATABASE | SCHEMA) uid? createDatabaseOption+ # alterSimpleDatabase | ALTER dbFormat = (DATABASE | SCHEMA) uid UPGRADE DATA DIRECTORY NAME # alterUpgradeName ; alterEvent : ALTER ownerStatement? EVENT fullId (ON SCHEDULE scheduleExpression)? ( ON COMPLETION NOT? PRESERVE )? (RENAME TO fullId)? enableType? (COMMENT STRING_LITERAL)? (DO routineBody)? ; alterFunction : ALTER FUNCTION fullId routineOption* ; alterInstance : ALTER INSTANCE ROTATE INNODB MASTER KEY ; alterLogfileGroup : ALTER LOGFILE GROUP uid ADD UNDOFILE STRING_LITERAL (INITIAL_SIZE '='? fileSizeLiteral)? WAIT? ENGINE '='? engineName ; alterProcedure : ALTER PROCEDURE fullId routineOption* ; alterServer : ALTER SERVER uid OPTIONS '(' serverOption (',' serverOption)* ')' ; alterTable : ALTER intimeAction = (ONLINE | OFFLINE)? IGNORE? TABLE tableName ( alterSpecification (',' alterSpecification)* )? partitionDefinitions? ; alterTablespace : ALTER TABLESPACE uid objectAction = (ADD | DROP) DATAFILE STRING_LITERAL ( INITIAL_SIZE '=' fileSizeLiteral )? WAIT? ENGINE '='? engineName ; alterView : ALTER (ALGORITHM '=' algType = (UNDEFINED | MERGE | TEMPTABLE))? ownerStatement? ( SQL SECURITY secContext = (DEFINER | INVOKER) )? VIEW fullId ('(' uidList ')')? AS selectStatement ( WITH checkOpt = (CASCADED | LOCAL)? CHECK OPTION )? ; // details alterSpecification : tableOption (','? tableOption)* # alterByTableOption | ADD COLUMN? uid columnDefinition (FIRST | AFTER uid)? # alterByAddColumn | ADD COLUMN? '(' uid columnDefinition (',' uid columnDefinition)* ')' # alterByAddColumns | ADD indexFormat = (INDEX | KEY) uid? indexType? indexColumnNames indexOption* # alterByAddIndex | ADD (CONSTRAINT name = uid?)? PRIMARY KEY index = uid? indexType? indexColumnNames indexOption* # alterByAddPrimaryKey | ADD (CONSTRAINT name = uid?)? UNIQUE indexFormat = (INDEX | KEY)? indexName = uid? indexType? indexColumnNames indexOption* # alterByAddUniqueKey | ADD keyType = (FULLTEXT | SPATIAL) indexFormat = (INDEX | KEY)? uid? indexColumnNames indexOption* # alterByAddSpecialIndex | ADD (CONSTRAINT name = uid?)? FOREIGN KEY indexName = uid? indexColumnNames referenceDefinition # alterByAddForeignKey | ADD (CONSTRAINT name = uid?)? CHECK (uid | stringLiteral | '(' expression ')') NOT? ENFORCED? # alterByAddCheckTableConstraint | ALTER (CONSTRAINT name = uid?)? CHECK (uid | stringLiteral | '(' expression ')') NOT? ENFORCED? # alterByAlterCheckTableConstraint | ADD (CONSTRAINT name = uid?)? CHECK '(' expression ')' # alterByAddCheckTableConstraint | ALGORITHM '='? algType = (DEFAULT | INSTANT | INPLACE | COPY) # alterBySetAlgorithm | ALTER COLUMN? uid (SET DEFAULT defaultValue | DROP DEFAULT) # alterByChangeDefault | CHANGE COLUMN? oldColumn = uid newColumn = uid columnDefinition ( FIRST | AFTER afterColumn = uid )? # alterByChangeColumn | RENAME COLUMN oldColumn = uid TO newColumn = uid # alterByRenameColumn | LOCK '='? lockType = (DEFAULT | NONE | SHARED | EXCLUSIVE) # alterByLock | MODIFY COLUMN? uid columnDefinition (FIRST | AFTER uid)? # alterByModifyColumn | DROP COLUMN? uid RESTRICT? # alterByDropColumn | DROP (CONSTRAINT | CHECK) uid # alterByDropConstraintCheck | DROP PRIMARY KEY # alterByDropPrimaryKey | DROP indexFormat = (INDEX | KEY) uid # alterByDropIndex | RENAME indexFormat = (INDEX | KEY) uid TO uid # alterByRenameIndex | ALTER COLUMN? uid ( SET DEFAULT ( stringLiteral | '(' expression ')') | SET (VISIBLE | INVISIBLE) | DROP DEFAULT ) # alterByAlterColumnDefault | ALTER INDEX uid (VISIBLE | INVISIBLE) # alterByAlterIndexVisibility | DROP FOREIGN KEY uid dottedId? # alterByDropForeignKey | DISABLE KEYS # alterByDisableKeys | ENABLE KEYS # alterByEnableKeys | RENAME renameFormat = (TO | AS)? (uid | fullId) # alterByRename | ORDER BY uidList # alterByOrder | CONVERT TO (CHARSET | CHARACTER SET) charsetName (COLLATE collationName)? # alterByConvertCharset | DEFAULT? CHARACTER SET '=' charsetName (COLLATE '=' collationName)? # alterByDefaultCharset | DISCARD TABLESPACE # alterByDiscardTablespace | IMPORT TABLESPACE # alterByImportTablespace | FORCE # alterByForce | validationFormat = (WITHOUT | WITH) VALIDATION # alterByValidate | ADD COLUMN? '(' createDefinition (',' createDefinition)* ')' # alterByAddDefinitions | alterPartitionSpecification # alterPartition ; alterPartitionSpecification : ADD PARTITION '(' partitionDefinition (',' partitionDefinition)* ')' # alterByAddPartition | DROP PARTITION uidList # alterByDropPartition | DISCARD PARTITION (uidList | ALL) TABLESPACE # alterByDiscardPartition | IMPORT PARTITION (uidList | ALL) TABLESPACE # alterByImportPartition | TRUNCATE PARTITION (uidList | ALL) # alterByTruncatePartition | COALESCE PARTITION decimalLiteral # alterByCoalescePartition | REORGANIZE PARTITION uidList INTO '(' partitionDefinition (',' partitionDefinition)* ')' # alterByReorganizePartition | EXCHANGE PARTITION uid WITH TABLE tableName (validationFormat = (WITH | WITHOUT) VALIDATION)? # alterByExchangePartition | ANALYZE PARTITION (uidList | ALL) # alterByAnalyzePartition | CHECK PARTITION (uidList | ALL) # alterByCheckPartition | OPTIMIZE PARTITION (uidList | ALL) # alterByOptimizePartition | REBUILD PARTITION (uidList | ALL) # alterByRebuildPartition | REPAIR PARTITION (uidList | ALL) # alterByRepairPartition | REMOVE PARTITIONING # alterByRemovePartitioning | UPGRADE PARTITIONING # alterByUpgradePartitioning ; // Drop statements dropDatabase : DROP dbFormat = (DATABASE | SCHEMA) ifExists? uid ; dropEvent : DROP EVENT ifExists? fullId ; dropIndex : DROP INDEX intimeAction = (ONLINE | OFFLINE)? uid ON tableName ( ALGORITHM '='? algType = (DEFAULT | INPLACE | COPY) | LOCK '='? lockType = (DEFAULT | NONE | SHARED | EXCLUSIVE) )* ; dropLogfileGroup : DROP LOGFILE GROUP uid ENGINE '=' engineName ; dropProcedure : DROP PROCEDURE ifExists? fullId ; dropFunction : DROP FUNCTION ifExists? fullId ; dropServer : DROP SERVER ifExists? uid ; dropTable : DROP TEMPORARY? TABLE ifExists? tables dropType = (RESTRICT | CASCADE)? ; dropTablespace : DROP TABLESPACE uid (ENGINE '='? engineName)? ; dropTrigger : DROP TRIGGER ifExists? fullId ; dropView : DROP VIEW ifExists? fullId (',' fullId)* dropType = (RESTRICT | CASCADE)? ; dropRole : DROP ROLE ifExists? roleName (',' roleName)* ; setRole : SET DEFAULT ROLE (NONE | ALL | roleName (',' roleName)*) TO (userName | uid) ( ',' (userName | uid) )* | SET ROLE roleOption ; // Other DDL statements renameTable : RENAME TABLE renameTableClause (',' renameTableClause)* ; renameTableClause : tableName TO tableName ; truncateTable : TRUNCATE TABLE? tableName ; // Data Manipulation Language // Primary DML Statements callStatement : CALL fullId ('(' (constants | expressions)? ')')? ; deleteStatement : singleDeleteStatement | multipleDeleteStatement ; doStatement : DO expressions ; handlerStatement : handlerOpenStatement | handlerReadIndexStatement | handlerReadStatement | handlerCloseStatement ; insertStatement : INSERT priority = (LOW_PRIORITY | DELAYED | HIGH_PRIORITY)? IGNORE? INTO? tableName ( PARTITION '(' partitions = uidList? ')' )? ( ('(' columns = fullColumnNameList? ')')? insertStatementValue (AS? uid)? | SET setFirst = updatedElement (',' setElements += updatedElement)* ) ( ON DUPLICATE KEY UPDATE duplicatedFirst = updatedElement ( ',' duplicatedElements += updatedElement )* )? ; loadDataStatement : LOAD DATA priority = (LOW_PRIORITY | CONCURRENT)? LOCAL? INFILE filename = STRING_LITERAL violation = ( REPLACE | IGNORE )? INTO TABLE tableName (PARTITION '(' uidList ')')? (CHARACTER SET charset = charsetName)? ( fieldsFormat = (FIELDS | COLUMNS) selectFieldsInto+ )? (LINES selectLinesInto+)? (IGNORE decimalLiteral linesFormat = (LINES | ROWS))? ( '(' assignmentField (',' assignmentField)* ')' )? (SET updatedElement (',' updatedElement)*)? ; loadXmlStatement : LOAD XML priority = (LOW_PRIORITY | CONCURRENT)? LOCAL? INFILE filename = STRING_LITERAL violation = ( REPLACE | IGNORE )? INTO TABLE tableName (CHARACTER SET charset = charsetName)? ( ROWS IDENTIFIED BY '<' tag = STRING_LITERAL '>' )? (IGNORE decimalLiteral linesFormat = (LINES | ROWS))? ( '(' assignmentField (',' assignmentField)* ')' )? (SET updatedElement (',' updatedElement)*)? ; replaceStatement : REPLACE priority = (LOW_PRIORITY | DELAYED)? INTO? tableName ( PARTITION '(' partitions = uidList ')' )? ( ('(' columns = uidList ')')? insertStatementValue | SET setFirst = updatedElement (',' setElements += updatedElement)* ) ; selectStatement : withStatement? querySpecification lockClause? | withStatement? queryExpression lockClause? | withStatement? (querySpecificationNointo | queryExpressionNointo) unionStatement+ ( UNION unionType = (ALL | DISTINCT)? (querySpecification | queryExpression) )? orderByClause? limitClause? lockClause? | withStatement? queryExpressionNointo unionParenthesis+ (UNION unionType = (ALL | DISTINCT)? queryExpression)? orderByClause? limitClause? lockClause? | withStatement? querySpecificationNointo (',' lateralStatement)+ ; updateStatement : singleUpdateStatement | multipleUpdateStatement ; // https://dev.mysql.com/doc/refman/8.0/en/values.html valuesStatement : VALUES '(' expressionsWithDefaults? ')' (',' '(' expressionsWithDefaults? ')')* ; // details insertStatementValue : selectStatement | insertFormat = (VALUES | VALUE) '(' expressionsWithDefaults? ')' ( ',' '(' expressionsWithDefaults? ')' )* ; updatedElement : fullColumnName '=' (expression | DEFAULT) ; assignmentField : uid | LOCAL_ID ; lockClause : FOR UPDATE | LOCK IN SHARE MODE ; // Detailed DML Statements singleDeleteStatement : DELETE priority = LOW_PRIORITY? QUICK? IGNORE? FROM tableName (AS? uid)? ( PARTITION '(' uidList ')' )? (WHERE expression)? orderByClause? (LIMIT limitClauseAtom)? ; multipleDeleteStatement : DELETE priority = LOW_PRIORITY? QUICK? IGNORE? ( tableName ('.' '*')? ( ',' tableName ('.' '*')?)* FROM tableSources | FROM tableName ('.' '*')? ( ',' tableName ('.' '*')?)* USING tableSources ) (WHERE expression)? ; handlerOpenStatement : HANDLER tableName OPEN (AS? uid)? ; handlerReadIndexStatement : HANDLER tableName READ index = uid ( comparisonOperator '(' constants ')' | moveOrder = (FIRST | NEXT | PREV | LAST) ) (WHERE expression)? (LIMIT limitClauseAtom)? ; handlerReadStatement : HANDLER tableName READ moveOrder = (FIRST | NEXT) (WHERE expression)? (LIMIT limitClauseAtom)? ; handlerCloseStatement : HANDLER tableName CLOSE ; singleUpdateStatement : UPDATE priority = LOW_PRIORITY? IGNORE? tableSources (AS? uid)? SET updatedElement ( ',' updatedElement )* (WHERE expression)? orderByClause? limitClause? ; multipleUpdateStatement : UPDATE priority = LOW_PRIORITY? IGNORE? tableSources SET updatedElement (',' updatedElement)* ( WHERE expression )? ; // details orderByClause : ORDER BY orderByExpression (',' orderByExpression)* ; orderByExpression : expression order = (ASC | DESC)? ; tableSources : tableSource (',' tableSource)* ; tableSource : tableSourceItem joinPart* # tableSourceBase | '(' tableSourceItem joinPart* ')' # tableSourceNested | jsonTable # tableJson ; tableSourceItem : tableName (PARTITION '(' uidList ')')? (AS? alias = uid)? (indexHint (',' indexHint)*)? # atomTableItem | sequenceFunctionName '(' DECIMAL_LITERAL ')' (AS? alias = uid)? # sequenceTableItem | (selectStatement | '(' parenthesisSubquery = selectStatement ')') AS? alias = uid # subqueryTableItem | '(' tableSources ')' # tableSourcesItem ; indexHint : indexHintAction = (USE | IGNORE | FORCE) keyFormat = (INDEX | KEY) (FOR indexHintType)? '(' uidList ')' ; indexHintType : JOIN | ORDER BY | GROUP BY ; joinPart : (INNER | CROSS)? JOIN LATERAL? tableSourceItem joinSpec* # innerJoin | STRAIGHT_JOIN tableSourceItem (ON expression)* # straightJoin | (LEFT | RIGHT) OUTER? JOIN LATERAL? tableSourceItem joinSpec* # outerJoin | NATURAL ((LEFT | RIGHT) OUTER?)? JOIN tableSourceItem # naturalJoin ; joinSpec : (ON expression) | USING '(' uidList ')' ; // Select Statement's Details queryExpression : '(' querySpecification ')' | '(' queryExpression ')' ; queryExpressionNointo : '(' querySpecificationNointo ')' | '(' queryExpressionNointo ')' ; querySpecification : SELECT selectSpec* selectElements selectIntoExpression? fromClause? groupByClause? havingClause? windowClause? orderByClause? limitClause? | SELECT selectSpec* selectElements fromClause? groupByClause? havingClause? windowClause? orderByClause? limitClause? selectIntoExpression? ; querySpecificationNointo : SELECT selectSpec* selectElements fromClause? groupByClause? havingClause? windowClause? orderByClause? limitClause? unionStatement? ; unionParenthesis : UNION unionType = (ALL | DISTINCT)? queryExpressionNointo ; unionStatement : UNION unionType = (ALL | DISTINCT)? (querySpecificationNointo | queryExpressionNointo) ; lateralStatement : LATERAL ( querySpecificationNointo | queryExpressionNointo | ('(' (querySpecificationNointo | queryExpressionNointo) ')' (AS? uid)?) ) ; // JSON // https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html jsonTable : JSON_TABLE '(' expression ',' STRING_LITERAL COLUMNS '(' jsonColumnList ')' ')' (AS? uid)? ; jsonColumnList : jsonColumn (',' jsonColumn)* ; jsonColumn : fullColumnName ( FOR ORDINALITY | dataType (PATH STRING_LITERAL jsonOnEmpty? jsonOnError? | EXISTS PATH STRING_LITERAL) ) | NESTED PATH? STRING_LITERAL COLUMNS '(' jsonColumnList ')' ; jsonOnEmpty : (NULL_LITERAL | ERROR | DEFAULT defaultValue) ON EMPTY ; jsonOnError : (NULL_LITERAL | ERROR | DEFAULT defaultValue) ON ERROR ; // details selectSpec : (ALL | DISTINCT | DISTINCTROW) | HIGH_PRIORITY | STRAIGHT_JOIN | SQL_SMALL_RESULT | SQL_BIG_RESULT | SQL_BUFFER_RESULT | (SQL_CACHE | SQL_NO_CACHE) | SQL_CALC_FOUND_ROWS ; selectElements : (star = '*' | selectElement) (',' selectElement)* ; selectElement : fullId '.' '*' # selectStarElement | fullColumnName (AS? uid)? # selectColumnElement | functionCall (AS? uid)? # selectFunctionElement | (LOCAL_ID VAR_ASSIGN)? expression (AS? uid)? # selectExpressionElement ; selectIntoExpression : INTO assignmentField (',' assignmentField)* # selectIntoVariables | INTO DUMPFILE STRING_LITERAL # selectIntoDumpFile | ( INTO OUTFILE filename = STRING_LITERAL (CHARACTER SET charset = charsetName)? ( fieldsFormat = (FIELDS | COLUMNS) selectFieldsInto+ )? (LINES selectLinesInto+)? ) # selectIntoTextFile ; selectFieldsInto : TERMINATED BY terminationField = STRING_LITERAL | OPTIONALLY? ENCLOSED BY enclosion = STRING_LITERAL | ESCAPED BY escaping = STRING_LITERAL ; selectLinesInto : STARTING BY starting = STRING_LITERAL | TERMINATED BY terminationLine = STRING_LITERAL ; fromClause : (FROM tableSources)? (WHERE whereExpr = expression)? ; groupByClause : GROUP BY groupByItem (',' groupByItem)* (WITH ROLLUP)? ; havingClause : HAVING havingExpr = expression ; windowClause : WINDOW windowName AS '(' windowSpec ')' (',' windowName AS '(' windowSpec ')')* ; groupByItem : expression order = (ASC | DESC)? ; limitClause : LIMIT ( (offset = limitClauseAtom ',')? limit = limitClauseAtom | limit = limitClauseAtom OFFSET offset = limitClauseAtom ) ; limitClauseAtom : decimalLiteral | mysqlVariable | simpleId ; // Transaction's Statements startTransaction : START TRANSACTION (transactionMode (',' transactionMode)*)? ; beginWork : BEGIN WORK? ; commitWork : COMMIT WORK? (AND nochain = NO? CHAIN)? (norelease = NO? RELEASE)? ; rollbackWork : ROLLBACK WORK? (AND nochain = NO? CHAIN)? (norelease = NO? RELEASE)? ; savepointStatement : SAVEPOINT uid ; rollbackStatement : ROLLBACK WORK? TO SAVEPOINT? uid ; releaseStatement : RELEASE SAVEPOINT uid ; lockTables : LOCK (TABLE | TABLES) lockTableElement (',' lockTableElement)* ; unlockTables : UNLOCK TABLES ; // details setAutocommitStatement : SET AUTOCOMMIT '=' autocommitValue = ('0' | '1') ; setTransactionStatement : SET transactionContext = (GLOBAL | SESSION)? TRANSACTION transactionOption ( ',' transactionOption )* ; transactionMode : WITH CONSISTENT SNAPSHOT | READ WRITE | READ ONLY ; lockTableElement : tableName (AS? uid)? lockAction ; lockAction : READ LOCAL? | LOW_PRIORITY? WRITE ; transactionOption : ISOLATION LEVEL transactionLevel | READ WRITE | READ ONLY ; transactionLevel : REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE ; // Replication's Statements // Base Replication changeMaster : CHANGE MASTER TO masterOption (',' masterOption)* channelOption? ; changeReplicationFilter : CHANGE REPLICATION FILTER replicationFilter (',' replicationFilter)* ; purgeBinaryLogs : PURGE purgeFormat = (BINARY | MASTER) LOGS ( TO fileName = STRING_LITERAL | BEFORE timeValue = STRING_LITERAL ) ; resetMaster : RESET MASTER ; resetSlave : RESET SLAVE ALL? channelOption? ; startSlave : START SLAVE (threadType (',' threadType)*)? (UNTIL untilOption)? connectionOption* channelOption? ; stopSlave : STOP SLAVE (threadType (',' threadType)*)? ; startGroupReplication : START GROUP_REPLICATION ; stopGroupReplication : STOP GROUP_REPLICATION ; // details masterOption : stringMasterOption '=' STRING_LITERAL # masterStringOption | decimalMasterOption '=' decimalLiteral # masterDecimalOption | boolMasterOption '=' boolVal = ('0' | '1') # masterBoolOption | MASTER_HEARTBEAT_PERIOD '=' REAL_LITERAL # masterRealOption | IGNORE_SERVER_IDS '=' '(' (uid (',' uid)*)? ')' # masterUidListOption ; stringMasterOption : MASTER_BIND | MASTER_HOST | MASTER_USER | MASTER_PASSWORD | MASTER_LOG_FILE | RELAY_LOG_FILE | MASTER_SSL_CA | MASTER_SSL_CAPATH | MASTER_SSL_CERT | MASTER_SSL_CRL | MASTER_SSL_CRLPATH | MASTER_SSL_KEY | MASTER_SSL_CIPHER | MASTER_TLS_VERSION ; decimalMasterOption : MASTER_PORT | MASTER_CONNECT_RETRY | MASTER_RETRY_COUNT | MASTER_DELAY | MASTER_LOG_POS | RELAY_LOG_POS ; boolMasterOption : MASTER_AUTO_POSITION | MASTER_SSL | MASTER_SSL_VERIFY_SERVER_CERT ; channelOption : FOR CHANNEL STRING_LITERAL ; replicationFilter : REPLICATE_DO_DB '=' '(' uidList ')' # doDbReplication | REPLICATE_IGNORE_DB '=' '(' uidList ')' # ignoreDbReplication | REPLICATE_DO_TABLE '=' '(' tables ')' # doTableReplication | REPLICATE_IGNORE_TABLE '=' '(' tables ')' # ignoreTableReplication | REPLICATE_WILD_DO_TABLE '=' '(' simpleStrings ')' # wildDoTableReplication | REPLICATE_WILD_IGNORE_TABLE '=' '(' simpleStrings ')' # wildIgnoreTableReplication | REPLICATE_REWRITE_DB '=' '(' tablePair (',' tablePair)* ')' # rewriteDbReplication ; tablePair : '(' firstTable = tableName ',' secondTable = tableName ')' ; threadType : IO_THREAD | SQL_THREAD ; untilOption : gtids = (SQL_BEFORE_GTIDS | SQL_AFTER_GTIDS) '=' gtuidSet # gtidsUntilOption | MASTER_LOG_FILE '=' STRING_LITERAL ',' MASTER_LOG_POS '=' decimalLiteral # masterLogUntilOption | RELAY_LOG_FILE '=' STRING_LITERAL ',' RELAY_LOG_POS '=' decimalLiteral # relayLogUntilOption | SQL_AFTER_MTS_GAPS # sqlGapsUntilOption ; connectionOption : USER '=' conOptUser = STRING_LITERAL # userConnectionOption | PASSWORD '=' conOptPassword = STRING_LITERAL # passwordConnectionOption | DEFAULT_AUTH '=' conOptDefAuth = STRING_LITERAL # defaultAuthConnectionOption | PLUGIN_DIR '=' conOptPluginDir = STRING_LITERAL # pluginDirConnectionOption ; gtuidSet : uuidSet (',' uuidSet)* | STRING_LITERAL ; // XA Transactions xaStartTransaction : XA xaStart = (START | BEGIN) xid xaAction = (JOIN | RESUME)? ; xaEndTransaction : XA END xid (SUSPEND (FOR MIGRATE)?)? ; xaPrepareStatement : XA PREPARE xid ; xaCommitWork : XA COMMIT xid (ONE PHASE)? ; xaRollbackWork : XA ROLLBACK xid ; xaRecoverWork : XA RECOVER (CONVERT xid)? ; // Prepared Statements prepareStatement : PREPARE uid FROM (query = STRING_LITERAL | variable = LOCAL_ID) ; executeStatement : EXECUTE uid (USING userVariables)? ; deallocatePrepare : dropFormat = (DEALLOCATE | DROP) PREPARE uid ; // Compound Statements routineBody : blockStatement | sqlStatement ; // details blockStatement : (uid ':')? BEGIN (declareVariable SEMI)* (declareCondition SEMI)* (declareCursor SEMI)* ( declareHandler SEMI )* procedureSqlStatement* END uid? ; caseStatement : CASE (uid | expression)? caseAlternative+ (ELSE procedureSqlStatement+)? END CASE ; ifStatement : IF expression THEN thenStatements += procedureSqlStatement+ elifAlternative* ( ELSE elseStatements += procedureSqlStatement+ )? END IF ; iterateStatement : ITERATE uid ; leaveStatement : LEAVE uid ; loopStatement : (uid ':')? LOOP procedureSqlStatement+ END LOOP uid? ; repeatStatement : (uid ':')? REPEAT procedureSqlStatement+ UNTIL expression END REPEAT uid? ; returnStatement : RETURN expression ; whileStatement : (uid ':')? WHILE expression DO procedureSqlStatement+ END WHILE uid? ; cursorStatement : CLOSE uid # CloseCursor | FETCH (NEXT? FROM)? uid INTO uidList # FetchCursor | OPEN uid # OpenCursor ; // details declareVariable : DECLARE uidList dataType (DEFAULT expression)? ; declareCondition : DECLARE uid CONDITION FOR (decimalLiteral | SQLSTATE VALUE? STRING_LITERAL) ; declareCursor : DECLARE uid CURSOR FOR selectStatement ; declareHandler : DECLARE handlerAction = (CONTINUE | EXIT | UNDO) HANDLER FOR handlerConditionValue ( ',' handlerConditionValue )* routineBody ; handlerConditionValue : decimalLiteral # handlerConditionCode | SQLSTATE VALUE? STRING_LITERAL # handlerConditionState | uid # handlerConditionName | SQLWARNING # handlerConditionWarning | NOT FOUND # handlerConditionNotfound | SQLEXCEPTION # handlerConditionException ; procedureSqlStatement : (compoundStatement | sqlStatement) SEMI ; caseAlternative : WHEN (constant | expression) THEN procedureSqlStatement+ ; elifAlternative : ELSEIF expression THEN procedureSqlStatement+ ; // Administration Statements // Account management statements alterUser : ALTER USER userSpecification (',' userSpecification)* # alterUserMysqlV56 | ALTER USER ifExists? userAuthOption (',' userAuthOption)* ( REQUIRE (tlsNone = NONE | tlsOption (AND? tlsOption)*) )? (WITH userResourceOption+)? (userPasswordOption | userLockOption)* ( COMMENT STRING_LITERAL | ATTRIBUTE STRING_LITERAL )? # alterUserMysqlV80 | ALTER USER ifExists? (userName | uid) DEFAULT ROLE roleOption # alterUserMysqlV80 ; createUser : CREATE USER userAuthOption (',' userAuthOption)* # createUserMysqlV56 | CREATE USER ifNotExists? userAuthOption (',' userAuthOption)* (DEFAULT ROLE roleOption)? ( REQUIRE (tlsNone = NONE | tlsOption (AND? tlsOption)*) )? (WITH userResourceOption+)? (userPasswordOption | userLockOption)* ( COMMENT STRING_LITERAL | ATTRIBUTE STRING_LITERAL )? # createUserMysqlV80 ; dropUser : DROP USER ifExists? userName (',' userName)* ; grantStatement : GRANT privelegeClause (',' privelegeClause)* ON privilegeObject = ( TABLE | FUNCTION | PROCEDURE )? privilegeLevel TO userAuthOption (',' userAuthOption)* ( REQUIRE (tlsNone = NONE | tlsOption (AND? tlsOption)*) )? (WITH (GRANT OPTION | userResourceOption)*)? (AS userName WITH ROLE roleOption)? | GRANT (userName | uid) (',' (userName | uid))* TO (userName | uid) (',' (userName | uid))* ( WITH ADMIN OPTION )? ; roleOption : DEFAULT | NONE | ALL (EXCEPT userName (',' userName)*)? | userName (',' userName)* ; grantProxy : GRANT PROXY ON fromFirst = userName TO toFirst = userName (',' toOther += userName)* ( WITH GRANT OPTION )? ; renameUser : RENAME USER renameUserClause (',' renameUserClause)* ; revokeStatement : REVOKE ifExists? (privelegeClause | uid) (',' privelegeClause | uid)* ON privilegeObject = ( TABLE | FUNCTION | PROCEDURE )? privilegeLevel FROM userName (',' userName)* (IGNORE UNKNOWN USER)? # detailRevoke | REVOKE ifExists? ALL PRIVILEGES? ',' GRANT OPTION FROM userName (',' userName)* ( IGNORE UNKNOWN USER )? # shortRevoke | REVOKE ifExists? (userName | uid) (',' (userName | uid))* FROM (userName | uid) ( ',' (userName | uid) )* (IGNORE UNKNOWN USER)? # roleRevoke ; revokeProxy : REVOKE PROXY ON onUser = userName FROM fromFirst = userName (',' fromOther += userName)* ; setPasswordStatement : SET PASSWORD (FOR userName)? '=' (passwordFunctionClause | STRING_LITERAL) ; // details userSpecification : userName userPasswordOption ; userAuthOption : userName IDENTIFIED BY PASSWORD hashed = STRING_LITERAL # hashAuthOption | userName IDENTIFIED BY RANDOM PASSWORD authOptionClause # randomAuthOption | userName IDENTIFIED BY STRING_LITERAL authOptionClause # stringAuthOption | userName IDENTIFIED WITH authenticationRule # moduleAuthOption | userName # simpleAuthOption ; authOptionClause : (REPLACE STRING_LITERAL)? (RETAIN CURRENT PASSWORD)? ; authenticationRule : authPlugin ((BY | USING | AS) (STRING_LITERAL | RANDOM PASSWORD) authOptionClause)? # module | authPlugin USING passwordFunctionClause # passwordModuleOption ; tlsOption : SSL | X509 | CIPHER STRING_LITERAL | ISSUER STRING_LITERAL | SUBJECT STRING_LITERAL ; userResourceOption : MAX_QUERIES_PER_HOUR decimalLiteral | MAX_UPDATES_PER_HOUR decimalLiteral | MAX_CONNECTIONS_PER_HOUR decimalLiteral | MAX_USER_CONNECTIONS decimalLiteral ; userPasswordOption : PASSWORD EXPIRE ( expireType = DEFAULT | expireType = NEVER | expireType = INTERVAL decimalLiteral DAY )? | PASSWORD HISTORY (DEFAULT | decimalLiteral) | PASSWORD REUSE INTERVAL (DEFAULT | decimalLiteral DAY) | PASSWORD REQUIRE CURRENT (OPTIONAL | DEFAULT)? | FAILED_LOGIN_ATTEMPTS decimalLiteral | PASSWORD_LOCK_TIME (decimalLiteral | UNBOUNDED) ; userLockOption : ACCOUNT lockType = (LOCK | UNLOCK) ; privelegeClause : privilege ('(' uidList ')')? ; privilege : ALL PRIVILEGES? | ALTER ROUTINE? | CREATE (TEMPORARY TABLES | ROUTINE | VIEW | USER | TABLESPACE | ROLE)? | DELETE | DROP (ROLE)? | EVENT | EXECUTE | FILE | GRANT OPTION | INDEX | INSERT | LOCK TABLES | PROCESS | PROXY | REFERENCES | RELOAD | REPLICATION (CLIENT | SLAVE) | SELECT | SHOW (VIEW | DATABASES) | SHUTDOWN | SUPER | TRIGGER | UPDATE | USAGE | APPLICATION_PASSWORD_ADMIN | AUDIT_ABORT_EXEMPT | AUDIT_ADMIN | AUTHENTICATION_POLICY_ADMIN | BACKUP_ADMIN | BINLOG_ADMIN | BINLOG_ENCRYPTION_ADMIN | CLONE_ADMIN | CONNECTION_ADMIN | ENCRYPTION_KEY_ADMIN | FIREWALL_ADMIN | FIREWALL_EXEMPT | FIREWALL_USER | FLUSH_OPTIMIZER_COSTS | FLUSH_STATUS | FLUSH_TABLES | FLUSH_USER_RESOURCES | GROUP_REPLICATION_ADMIN | INNODB_REDO_LOG_ARCHIVE | INNODB_REDO_LOG_ENABLE | NDB_STORED_USER | PASSWORDLESS_USER_ADMIN | PERSIST_RO_VARIABLES_ADMIN | REPLICATION_APPLIER | REPLICATION_SLAVE_ADMIN | RESOURCE_GROUP_ADMIN | RESOURCE_GROUP_USER | ROLE_ADMIN | SERVICE_CONNECTION_ADMIN | SESSION_VARIABLES_ADMIN | SET_USER_ID | SKIP_QUERY_REWRITE | SHOW_ROUTINE | SYSTEM_USER | SYSTEM_VARIABLES_ADMIN | TABLE_ENCRYPTION_ADMIN | TELEMETRY_LOG_ADMIN | TP_CONNECTION_ADMIN | VERSION_TOKEN_ADMIN | XA_RECOVER_ADMIN // MySQL on Amazon RDS | LOAD FROM S3 | SELECT INTO S3 | INVOKE LAMBDA ; privilegeLevel : '*' # currentSchemaPriviLevel | '*' '.' '*' # globalPrivLevel | uid '.' '*' # definiteSchemaPrivLevel | uid '.' uid # definiteFullTablePrivLevel | uid dottedId # definiteFullTablePrivLevel2 | uid # definiteTablePrivLevel ; renameUserClause : fromFirst = userName TO toFirst = userName ; // Table maintenance statements analyzeTable : ANALYZE actionOption = (NO_WRITE_TO_BINLOG | LOCAL)? (TABLE | TABLES) tables ( UPDATE HISTOGRAM ON fullColumnName (',' fullColumnName)* (WITH decimalLiteral BUCKETS)? )? (DROP HISTOGRAM ON fullColumnName (',' fullColumnName)*)? ; checkTable : CHECK TABLE tables checkTableOption* ; checksumTable : CHECKSUM TABLE tables actionOption = (QUICK | EXTENDED)? ; optimizeTable : OPTIMIZE actionOption = (NO_WRITE_TO_BINLOG | LOCAL)? (TABLE | TABLES) tables ; repairTable : REPAIR actionOption = (NO_WRITE_TO_BINLOG | LOCAL)? TABLE tables QUICK? EXTENDED? USE_FRM? ; // details checkTableOption : FOR UPGRADE | QUICK | FAST | MEDIUM | EXTENDED | CHANGED ; // Plugin and udf statements createUdfunction : CREATE AGGREGATE? FUNCTION ifNotExists? uid RETURNS returnType = ( STRING | INTEGER | REAL | DECIMAL ) SONAME STRING_LITERAL ; installPlugin : INSTALL PLUGIN uid SONAME STRING_LITERAL ; uninstallPlugin : UNINSTALL PLUGIN uid ; // Set and show statements setStatement : SET variableClause ('=' | ':=') (expression | ON) ( ',' variableClause ('=' | ':=') (expression | ON) )* # setVariable | SET charSet (charsetName | DEFAULT) # setCharset | SET NAMES (charsetName (COLLATE collationName)? | DEFAULT) # setNames | setPasswordStatement # setPassword | setTransactionStatement # setTransaction | setAutocommitStatement # setAutocommit | SET fullId ('=' | ':=') expression (',' fullId ('=' | ':=') expression)* # setNewValueInsideTrigger ; showStatement : SHOW logFormat = (BINARY | MASTER) LOGS # showMasterLogs | SHOW logFormat = (BINLOG | RELAYLOG) EVENTS (IN filename = STRING_LITERAL)? ( FROM fromPosition = decimalLiteral )? (LIMIT (offset = decimalLiteral ',')? rowCount = decimalLiteral)? # showLogEvents | SHOW showCommonEntity showFilter? # showObjectFilter | SHOW FULL? columnsFormat = (COLUMNS | FIELDS) tableFormat = (FROM | IN) tableName ( schemaFormat = (FROM | IN) uid )? showFilter? # showColumns | SHOW CREATE schemaFormat = (DATABASE | SCHEMA) ifNotExists? uid # showCreateDb | SHOW CREATE namedEntity = (EVENT | FUNCTION | PROCEDURE | TABLE | TRIGGER | VIEW) fullId # showCreateFullIdObject | SHOW CREATE USER userName # showCreateUser | SHOW ENGINE engineName engineOption = (STATUS | MUTEX) # showEngine | SHOW showGlobalInfoClause # showGlobalInfo | SHOW errorFormat = (ERRORS | WARNINGS) ( LIMIT (offset = decimalLiteral ',')? rowCount = decimalLiteral )? # showErrors | SHOW COUNT '(' '*' ')' errorFormat = (ERRORS | WARNINGS) # showCountErrors | SHOW showSchemaEntity (schemaFormat = (FROM | IN) uid)? showFilter? # showSchemaFilter | SHOW routine = (FUNCTION | PROCEDURE) CODE fullId # showRoutine | SHOW GRANTS (FOR userName)? # showGrants | SHOW indexFormat = (INDEX | INDEXES | KEYS) tableFormat = (FROM | IN) tableName ( schemaFormat = (FROM | IN) uid )? (WHERE expression)? # showIndexes | SHOW OPEN TABLES (schemaFormat = (FROM | IN) uid)? showFilter? # showOpenTables | SHOW PROFILE showProfileType (',' showProfileType)* (FOR QUERY queryCount = decimalLiteral)? ( LIMIT (offset = decimalLiteral ',')? rowCount = decimalLiteral ) # showProfile | SHOW SLAVE STATUS (FOR CHANNEL STRING_LITERAL)? # showSlaveStatus ; // details variableClause : LOCAL_ID | GLOBAL_ID | ( ('@' '@')? (GLOBAL | SESSION | LOCAL))? uid ; showCommonEntity : CHARACTER SET | COLLATION | DATABASES | SCHEMAS | FUNCTION STATUS | PROCEDURE STATUS | (GLOBAL | SESSION)? (STATUS | VARIABLES) ; showFilter : LIKE STRING_LITERAL | WHERE expression ; showGlobalInfoClause : STORAGE? ENGINES | MASTER STATUS | PLUGINS | PRIVILEGES | FULL? PROCESSLIST | PROFILES | SLAVE HOSTS | AUTHORS | CONTRIBUTORS ; showSchemaEntity : EVENTS | TABLE STATUS | FULL? TABLES | TRIGGERS ; showProfileType : ALL | BLOCK IO | CONTEXT SWITCHES | CPU | IPC | MEMORY | PAGE FAULTS | SOURCE | SWAPS ; // Other administrative statements binlogStatement : BINLOG STRING_LITERAL ; cacheIndexStatement : CACHE INDEX tableIndexes (',' tableIndexes)* (PARTITION '(' (uidList | ALL) ')')? IN schema = uid ; flushStatement : FLUSH flushFormat = (NO_WRITE_TO_BINLOG | LOCAL)? flushOption (',' flushOption)* // Specific for Azure Database for MySQL Single Server instance. | FLUSH FIREWALL_RULES ; killStatement : KILL connectionFormat = (CONNECTION | QUERY)? expression ; loadIndexIntoCache : LOAD INDEX INTO CACHE loadedTableIndexes (',' loadedTableIndexes)* ; // remark reset (maser | slave) describe in replication's // statements section resetStatement : RESET QUERY CACHE ; shutdownStatement : SHUTDOWN ; // details tableIndexes : tableName (indexFormat = (INDEX | KEY)? '(' uidList ')')? ; flushOption : ( DES_KEY_FILE | HOSTS | ( BINARY | ENGINE | ERROR | GENERAL | RELAY | SLOW)? LOGS | OPTIMIZER_COSTS | PRIVILEGES | QUERY CACHE | STATUS | USER_RESOURCES | TABLES (WITH READ LOCK)? ) # simpleFlushOption | RELAY LOGS channelOption? # channelFlushOption | (TABLE | TABLES) tables? flushTableOption? # tableFlushOption ; flushTableOption : WITH READ LOCK | FOR EXPORT ; loadedTableIndexes : tableName (PARTITION '(' (partitionList = uidList | ALL) ')')? ( indexFormat = (INDEX | KEY)? '(' indexList = uidList ')' )? (IGNORE LEAVES)? ; // Utility Statements simpleDescribeStatement : command = (EXPLAIN | DESCRIBE | DESC) tableName (column = uid | pattern = STRING_LITERAL)? ; fullDescribeStatement : command = (EXPLAIN | DESCRIBE | DESC) ( formatType = (EXTENDED | PARTITIONS | FORMAT) '=' formatValue = (TRADITIONAL | JSON) )? describeObjectClause ; helpStatement : HELP STRING_LITERAL ; useStatement : USE uid ; signalStatement : SIGNAL (( SQLSTATE VALUE? stringLiteral) | ID | REVERSE_QUOTE_ID) ( SET signalConditionInformation ( ',' signalConditionInformation)* )? ; resignalStatement : RESIGNAL (( SQLSTATE VALUE? stringLiteral) | ID | REVERSE_QUOTE_ID)? ( SET signalConditionInformation ( ',' signalConditionInformation)* )? ; signalConditionInformation : ( CLASS_ORIGIN | SUBCLASS_ORIGIN | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME ) '=' (stringLiteral | DECIMAL_LITERAL | mysqlVariable | simpleId) ; withStatement : WITH RECURSIVE? commonTableExpressions (',' commonTableExpressions)* ; tableStatement : TABLE tableName orderByClause? limitClause? ; diagnosticsStatement : GET (CURRENT | STACKED)? DIAGNOSTICS ( (variableClause '=' ( NUMBER | ROW_COUNT) ( ',' variableClause '=' ( NUMBER | ROW_COUNT))*) | ( CONDITION (decimalLiteral | variableClause) variableClause '=' diagnosticsConditionInformationName ( ',' variableClause '=' diagnosticsConditionInformationName )* ) ) ; diagnosticsConditionInformationName : CLASS_ORIGIN | SUBCLASS_ORIGIN | RETURNED_SQLSTATE | MESSAGE_TEXT | MYSQL_ERRNO | CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | CATALOG_NAME | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | CURSOR_NAME ; // details describeObjectClause : (selectStatement | deleteStatement | insertStatement | replaceStatement | updateStatement) # describeStatements | FOR CONNECTION uid # describeConnection ; // Common Clauses // DB Objects fullId : uid (DOT_ID | '.' uid)? ; tableName : fullId ; roleName : userName | uid ; fullColumnName : uid (dottedId dottedId?)? | .? dottedId dottedId? ; indexColumnName : ((uid | STRING_LITERAL) ('(' decimalLiteral ')')? | expression) sortType = (ASC | DESC)? ; simpleUserName : STRING_LITERAL | ID | ADMIN | keywordsCanBeId ; hostName : (LOCAL_ID | HOST_IP_ADDRESS | '@') ; userName : simpleUserName | simpleUserName hostName | currentUserExpression ; mysqlVariable : LOCAL_ID | GLOBAL_ID ; charsetName : BINARY | charsetNameBase | STRING_LITERAL | CHARSET_REVERSE_QOUTE_STRING ; collationName : uid | STRING_LITERAL ; engineName : engineNameBase | ID | STRING_LITERAL ; engineNameBase : ARCHIVE | BLACKHOLE | CONNECT | CSV | FEDERATED | INNODB | MEMORY | MRG_MYISAM | MYISAM | NDB | NDBCLUSTER | PERFORMANCE_SCHEMA | TOKUDB ; uuidSet : decimalLiteral '-' decimalLiteral '-' decimalLiteral '-' decimalLiteral '-' decimalLiteral ( ':' decimalLiteral '-' decimalLiteral )+ ; xid : globalTableUid = xuidStringId (',' qualifier = xuidStringId (',' idFormat = decimalLiteral)?)? ; xuidStringId : STRING_LITERAL | BIT_STRING | HEXADECIMAL_LITERAL+ ; authPlugin : uid | STRING_LITERAL ; uid : simpleId //| DOUBLE_QUOTE_ID //| REVERSE_QUOTE_ID | CHARSET_REVERSE_QOUTE_STRING | STRING_LITERAL ; simpleId : ID | charsetNameBase | transactionLevelBase | engineNameBase | privilegesBase | intervalTypeBase | dataTypeBase | keywordsCanBeId | scalarFunctionName ; dottedId : DOT_ID | '.' uid ; // Literals decimalLiteral : DECIMAL_LITERAL | ZERO_DECIMAL | ONE_DECIMAL | TWO_DECIMAL | REAL_LITERAL ; fileSizeLiteral : FILESIZE_LITERAL | decimalLiteral ; stringLiteral : (STRING_CHARSET_NAME? STRING_LITERAL | START_NATIONAL_STRING_LITERAL) STRING_LITERAL+ | (STRING_CHARSET_NAME? STRING_LITERAL | START_NATIONAL_STRING_LITERAL) (COLLATE collationName)? ; booleanLiteral : TRUE | FALSE ; hexadecimalLiteral : STRING_CHARSET_NAME? HEXADECIMAL_LITERAL ; nullNotnull : NOT? (NULL_LITERAL | NULL_SPEC_LITERAL) ; constant : stringLiteral | decimalLiteral | '-' decimalLiteral | hexadecimalLiteral | booleanLiteral | REAL_LITERAL | BIT_STRING | NOT? nullLiteral = (NULL_LITERAL | NULL_SPEC_LITERAL) ; // Data Types dataType : typeName = ( CHAR | CHARACTER | VARCHAR | TINYTEXT | TEXT | MEDIUMTEXT | LONGTEXT | NCHAR | NVARCHAR | LONG ) VARYING? lengthOneDimension? BINARY? (charSet charsetName)? (COLLATE collationName | BINARY)? # stringDataType | NATIONAL typeName = (CHAR | CHARACTER) VARYING lengthOneDimension? BINARY? # nationalVaryingStringDataType | NATIONAL typeName = (VARCHAR | CHARACTER | CHAR) lengthOneDimension? BINARY? # nationalStringDataType | NCHAR typeName = VARCHAR lengthOneDimension? BINARY? # nationalStringDataType | typeName = ( TINYINT | SMALLINT | MEDIUMINT | INT | INTEGER | BIGINT | MIDDLEINT | INT1 | INT2 | INT3 | INT4 | INT8 ) lengthOneDimension? (SIGNED | UNSIGNED | ZEROFILL)* # dimensionDataType | typeName = REAL lengthTwoDimension? (SIGNED | UNSIGNED | ZEROFILL)* # dimensionDataType | typeName = DOUBLE PRECISION? lengthTwoDimension? (SIGNED | UNSIGNED | ZEROFILL)* # dimensionDataType | typeName = (DECIMAL | DEC | FIXED | NUMERIC | FLOAT | FLOAT4 | FLOAT8) lengthTwoOptionalDimension? ( SIGNED | UNSIGNED | ZEROFILL )* # dimensionDataType | typeName = (DATE | TINYBLOB | MEDIUMBLOB | LONGBLOB | BOOL | BOOLEAN | SERIAL) # simpleDataType | typeName = (BIT | TIME | TIMESTAMP | DATETIME | BINARY | VARBINARY | BLOB | YEAR | VECTOR) lengthOneDimension? # dimensionDataType | typeName = (ENUM | SET) collectionOptions BINARY? (charSet charsetName)? # collectionDataType | typeName = ( GEOMETRYCOLLECTION | GEOMCOLLECTION | LINESTRING | MULTILINESTRING | MULTIPOINT | MULTIPOLYGON | POINT | POLYGON | JSON | GEOMETRY ) (SRID decimalLiteral)? # spatialDataType | typeName = LONG VARCHAR? BINARY? (charSet charsetName)? (COLLATE collationName)? # longVarcharDataType // LONG VARCHAR is the same as LONG | LONG VARBINARY # longVarbinaryDataType ; collectionOptions : '(' collectionOption (',' collectionOption)* ')' ; collectionOption : STRING_LITERAL ; convertedDataType : ( typeName = (BINARY | NCHAR | FLOAT) lengthOneDimension? | typeName = CHAR lengthOneDimension? (charSet charsetName)? | typeName = (DATE | DATETIME | TIME | YEAR | JSON | INT | INTEGER | DOUBLE) | typeName = (DECIMAL | DEC) lengthTwoOptionalDimension? | (SIGNED | UNSIGNED) (INTEGER | INT)? ) ARRAY? ; lengthOneDimension : '(' decimalLiteral ')' ; lengthTwoDimension : '(' decimalLiteral ',' decimalLiteral ')' ; lengthTwoOptionalDimension : '(' decimalLiteral (',' decimalLiteral)? ')' ; // Common Lists uidList : uid (',' uid)* ; fullColumnNameList : fullColumnName (',' fullColumnName)* ; tables : tableName (',' tableName)* ; indexColumnNames : '(' indexColumnName (',' indexColumnName)* ')' ; expressions : expression (',' expression)* ; expressionsWithDefaults : expressionOrDefault (',' expressionOrDefault)* ; constants : constant (',' constant)* ; simpleStrings : STRING_LITERAL (',' STRING_LITERAL)* ; userVariables : LOCAL_ID (',' LOCAL_ID)* ; // Common Expressons defaultValue : NULL_LITERAL | CAST '(' expression AS convertedDataType ')' | unaryOperator? constant | currentTimestamp (ON UPDATE currentTimestamp)? | '(' expression ')' | '(' fullId ')' ; currentTimestamp : ( (CURRENT_TIMESTAMP | LOCALTIME | LOCALTIMESTAMP) ('(' decimalLiteral? ')')? | NOW '(' decimalLiteral? ')' ) ; expressionOrDefault : expression | DEFAULT ; ifExists : IF EXISTS ; ifNotExists : IF NOT EXISTS ; orReplace : OR REPLACE ; // Functions functionCall : specificFunction # specificFunctionCall | aggregateWindowedFunction # aggregateFunctionCall | nonAggregateWindowedFunction # nonAggregateFunctionCall | scalarFunctionName '(' functionArgs? ')' # scalarFunctionCall | fullId '(' functionArgs? ')' # udfFunctionCall | passwordFunctionClause # passwordFunctionCall ; specificFunction : (CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP | LOCALTIME | UTC_TIMESTAMP | SCHEMA) ( '(' ')' )? # simpleFunctionCall | currentUserExpression # currentUser | CONVERT '(' expression separator = ',' convertedDataType ')' # dataTypeFunctionCall | CONVERT '(' expression USING charsetName ')' # dataTypeFunctionCall | CAST '(' expression AS convertedDataType ')' # dataTypeFunctionCall | VALUES '(' fullColumnName ')' # valuesFunctionCall | CASE expression caseFuncAlternative+ (ELSE elseArg = functionArg)? END # caseExpressionFunctionCall | CASE caseFuncAlternative+ (ELSE elseArg = functionArg)? END # caseFunctionCall | CHAR '(' functionArgs (USING charsetName)? ')' # charFunctionCall | POSITION '(' (positionString = stringLiteral | positionExpression = expression) IN ( inString = stringLiteral | inExpression = expression ) ')' # positionFunctionCall | (SUBSTR | SUBSTRING) '(' (sourceString = stringLiteral | sourceExpression = expression) FROM ( fromDecimal = decimalLiteral | fromExpression = expression ) (FOR ( forDecimal = decimalLiteral | forExpression = expression))? ')' # substrFunctionCall | TRIM '(' positioinForm = (BOTH | LEADING | TRAILING) ( sourceString = stringLiteral | sourceExpression = expression )? FROM (fromString = stringLiteral | fromExpression = expression) ')' # trimFunctionCall | TRIM '(' (sourceString = stringLiteral | sourceExpression = expression) FROM ( fromString = stringLiteral | fromExpression = expression ) ')' # trimFunctionCall | WEIGHT_STRING '(' (stringLiteral | expression) ( AS stringFormat = (CHAR | BINARY) '(' decimalLiteral ')' )? levelsInWeightString? ')' # weightFunctionCall | EXTRACT '(' intervalType FROM (sourceString = stringLiteral | sourceExpression = expression) ')' # extractFunctionCall | GET_FORMAT '(' datetimeFormat = (DATE | TIME | DATETIME) ',' stringLiteral ')' # getFormatFunctionCall | JSON_VALUE '(' expression ',' expression (RETURNING convertedDataType)? jsonOnEmpty? jsonOnError? ')' # jsonValueFunctionCall ; caseFuncAlternative : WHEN condition = functionArg THEN consequent = functionArg ; levelsInWeightString : LEVEL levelInWeightListElement (',' levelInWeightListElement)* # levelWeightList | LEVEL firstLevel = decimalLiteral '-' lastLevel = decimalLiteral # levelWeightRange ; levelInWeightListElement : decimalLiteral orderType = (ASC | DESC | REVERSE)? ; aggregateWindowedFunction : (AVG | MAX | MIN | SUM) '(' aggregator = (ALL | DISTINCT)? functionArg ')' overClause? | COUNT '(' ( starArg = '*' | aggregator = ALL? functionArg | aggregator = DISTINCT functionArgs ) ')' overClause? | ( BIT_AND | BIT_OR | BIT_XOR | STD | STDDEV | STDDEV_POP | STDDEV_SAMP | VAR_POP | VAR_SAMP | VARIANCE ) '(' aggregator = ALL? functionArg ')' overClause? | GROUP_CONCAT '(' aggregator = DISTINCT? functionArgs ( ORDER BY orderByExpression (',' orderByExpression)* )? (SEPARATOR separator = STRING_LITERAL)? ')' ; nonAggregateWindowedFunction : (LAG | LEAD) '(' expression (',' decimalLiteral)? (',' (decimalLiteral | NULL_LITERAL))? ')' overClause | (FIRST_VALUE | LAST_VALUE) '(' expression ')' overClause | (CUME_DIST | DENSE_RANK | PERCENT_RANK | RANK | ROW_NUMBER) '(' ')' overClause | NTH_VALUE '(' expression ',' decimalLiteral ')' overClause | NTILE '(' decimalLiteral ')' overClause ; overClause : OVER ('(' windowSpec? ')' | windowName) ; windowSpec : windowName? partitionClause? orderByClause? frameClause? ; windowName : uid ; frameClause : frameUnits frameExtent ; frameUnits : ROWS | RANGE ; frameExtent : frameRange | frameBetween ; frameBetween : BETWEEN frameRange AND frameRange ; frameRange : CURRENT ROW | UNBOUNDED (PRECEDING | FOLLOWING) | expression (PRECEDING | FOLLOWING) ; partitionClause : PARTITION BY expression (',' expression)* ; sequenceFunctionName : SEQUENCE_TABLE | PERCONA_SEQUENCE_TABLE ; scalarFunctionName : functionNameBase | ASCII | CURDATE | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP | CURTIME | DATE_ADD | DATE_SUB | IF | INSERT | LOCALTIME | LOCALTIMESTAMP | MID | NOW | REPEAT | REPLACE | SUBSTR | SUBSTRING | SYSDATE | TRIM | UTC_DATE | UTC_TIME | UTC_TIMESTAMP ; passwordFunctionClause : functionName = (PASSWORD | OLD_PASSWORD) '(' functionArg ')' ; functionArgs : (constant | fullColumnName | functionCall | expression) ( ',' (constant | fullColumnName | functionCall | expression) )* ; functionArg : constant | fullColumnName | functionCall | expression ; // Expressions, predicates // Simplified approach for expression expression : notOperator = (NOT | '!') expression # notExpression | expression logicalOperator expression # logicalExpression | predicate IS NOT? testValue = (TRUE | FALSE | UNKNOWN) # isExpression | predicate # predicateExpression ; predicate : predicate NOT? IN '(' (selectStatement | expressions) ')' # inPredicate | predicate IS nullNotnull # isNullPredicate | left = predicate comparisonOperator right = predicate # binaryComparisonPredicate | predicate comparisonOperator quantifier = (ALL | ANY | SOME) '(' selectStatement ')' # subqueryComparisonPredicate | predicate NOT? BETWEEN predicate AND predicate # betweenPredicate | predicate SOUNDS LIKE predicate # soundsLikePredicate | predicate NOT? LIKE predicate (ESCAPE STRING_LITERAL)? # likePredicate | predicate NOT? regex = (REGEXP | RLIKE) predicate # regexpPredicate | predicate MEMBER OF '(' predicate ')' # jsonMemberOfPredicate | expressionAtom # expressionAtomPredicate ; // Add in ASTVisitor nullNotnull in constant expressionAtom : constant # constantExpressionAtom | fullColumnName # fullColumnNameExpressionAtom | functionCall # functionCallExpressionAtom | expressionAtom COLLATE collationName # collateExpressionAtom | mysqlVariable # mysqlVariableExpressionAtom | unaryOperator expressionAtom # unaryExpressionAtom | BINARY expressionAtom # binaryExpressionAtom | LOCAL_ID VAR_ASSIGN expressionAtom # variableAssignExpressionAtom | '(' expression (',' expression)* ')' # nestedExpressionAtom | ROW '(' expression (',' expression)+ ')' # nestedRowExpressionAtom | EXISTS '(' selectStatement ')' # existsExpressionAtom | '(' selectStatement ')' # subqueryExpressionAtom | INTERVAL expression intervalType # intervalExpressionAtom | left = expressionAtom bitOperator right = expressionAtom # bitExpressionAtom | left = expressionAtom multOperator right = expressionAtom # mathExpressionAtom | left = expressionAtom addOperator right = expressionAtom # mathExpressionAtom | left = expressionAtom jsonOperator right = expressionAtom # jsonExpressionAtom ; unaryOperator : '!' | '~' | '+' | '-' | NOT ; comparisonOperator : '=' | '>' | '<' | '<' '=' | '>' '=' | '<' '>' | '!' '=' | '<' '=' '>' ; logicalOperator : AND | '&' '&' | XOR | OR | '|' '|' ; bitOperator : '<' '<' | '>' '>' | '&' | '^' | '|' ; multOperator : '*' | '/' | '%' | DIV | MOD ; addOperator : '+' | '-' ; jsonOperator : '-' '>' | '-' '>' '>' ; // Simple id sets // (that keyword, which can be id) charsetNameBase : ARMSCII8 | ASCII | BIG5 | BINARY | CP1250 | CP1251 | CP1256 | CP1257 | CP850 | CP852 | CP866 | CP932 | DEC8 | EUCJPMS | EUCKR | GB18030 | GB2312 | GBK | GEOSTD8 | GREEK | HEBREW | HP8 | KEYBCS2 | KOI8R | KOI8U | LATIN1 | LATIN2 | LATIN5 | LATIN7 | MACCE | MACROMAN | SJIS | SWE7 | TIS620 | UCS2 | UJIS | UTF16 | UTF16LE | UTF32 | UTF8 | UTF8MB3 | UTF8MB4 ; transactionLevelBase : REPEATABLE | COMMITTED | UNCOMMITTED | SERIALIZABLE ; privilegesBase : TABLES | ROUTINE | EXECUTE | FILE | PROCESS | RELOAD | SHUTDOWN | SUPER | PRIVILEGES ; intervalTypeBase : QUARTER | MONTH | DAY | HOUR | MINUTE | WEEK | SECOND | MICROSECOND ; dataTypeBase : DATE | TIME | TIMESTAMP | DATETIME | YEAR | ENUM | TEXT ; keywordsCanBeId : ACCOUNT | ACTION | ADMIN | AFTER | AGGREGATE | ALGORITHM | ANY | APPLICATION_PASSWORD_ADMIN | ARRAY | AT | AUDIT_ADMIN | AUDIT_ABORT_EXEMPT | AUTHORS | AUTOCOMMIT | AUTOEXTEND_SIZE | AUTO_INCREMENT | AUTHENTICATION_POLICY_ADMIN | AVG | AVG_ROW_LENGTH | ATTRIBUTE | BACKUP_ADMIN | BEGIN | BINLOG | BINLOG_ADMIN | BINLOG_ENCRYPTION_ADMIN | BIT | BIT_AND | BIT_OR | BIT_XOR | BLOCK | BOOL | BOOLEAN | BTREE | BUCKETS | CACHE | CASCADED | CHAIN | CHANGED | CHANNEL | CHECKSUM | PAGE_CHECKSUM | CATALOG_NAME | CIPHER | CLASS_ORIGIN | CLIENT | CLONE_ADMIN | CLOSE | CLUSTERING | COALESCE | CODE | COLUMNS | COLUMN_FORMAT | COLUMN_NAME | COMMENT | COMMIT | COMPACT | COMPLETION | COMPRESSED | COMPRESSION | CONCURRENT | CONDITION | CONNECT | CONNECTION | CONNECTION_ADMIN | CONSISTENT | CONSTRAINT_CATALOG | CONSTRAINT_NAME | CONSTRAINT_SCHEMA | CONTAINS | CONTEXT | CONTRIBUTORS | COPY | COUNT | CPU | CURRENT | CURRENT_USER | CURSOR_NAME | DATA | DATAFILE | DEALLOCATE | DEFAULT | DEFAULT_AUTH | DEFINER | DELAY_KEY_WRITE | DES_KEY_FILE | DIAGNOSTICS | DIRECTORY | DISABLE | DISCARD | DISK | DO | DUMPFILE | DUPLICATE | DYNAMIC | EMPTY | ENABLE | ENCRYPTION | ENCRYPTION_KEY_ADMIN | END | ENDS | ENGINE | ENGINE_ATTRIBUTE | ENGINES | ENFORCED | ERROR | ERRORS | ESCAPE | EUR | EVEN | EVENT | EVENTS | EVERY | EXCEPT | EXCHANGE | EXCLUSIVE | EXPIRE | EXPORT | EXTENDED | EXTENT_SIZE | FAILED_LOGIN_ATTEMPTS | FAST | FAULTS | FIELDS | FILE_BLOCK_SIZE | FILTER | FIREWALL_ADMIN | FIREWALL_EXEMPT | FIREWALL_USER | FIRST | FIXED | FLUSH | FLUSH_OPTIMIZER_COSTS | FLUSH_STATUS | FLUSH_TABLES | FLUSH_USER_RESOURCES | FOLLOWS | FOUND | FULL | FUNCTION | GENERAL | GEOMETRY | GLOBAL | GRANTS | GROUP | GROUP_CONCAT | GROUP_REPLICATION | GROUP_REPLICATION_ADMIN | HANDLER | HASH | HELP | HISTORY | HOST | HOSTS | IDENTIFIED | IGNORED | IGNORE_SERVER_IDS | IMPORT | INDEXES | INITIAL_SIZE | INNODB_REDO_LOG_ARCHIVE | INNODB_REDO_LOG_ENABLE | INPLACE | INSERT_METHOD | INSTALL | INSTANCE | INSTANT | INTERNAL | INVOKE | INVOKER | IO | IO_THREAD | IPC | ISO | ISOLATION | ISSUER | JIS | JSON | KEY_BLOCK_SIZE | LAMBDA | LANGUAGE | LAST | LATERAL | LEAVES | LESS | LEVEL | LIST | LOCAL | LOGFILE | LOGS | MASTER | MASTER_AUTO_POSITION | MASTER_CONNECT_RETRY | MASTER_DELAY | MASTER_HEARTBEAT_PERIOD | MASTER_HOST | MASTER_LOG_FILE | MASTER_LOG_POS | MASTER_PASSWORD | MASTER_PORT | MASTER_RETRY_COUNT | MASTER_SSL | MASTER_SSL_CA | MASTER_SSL_CAPATH | MASTER_SSL_CERT | MASTER_SSL_CIPHER | MASTER_SSL_CRL | MASTER_SSL_CRLPATH | MASTER_SSL_KEY | MASTER_TLS_VERSION | MASTER_USER | MAX_CONNECTIONS_PER_HOUR | MAX_QUERIES_PER_HOUR | MAX | MAX_ROWS | MAX_SIZE | MAX_UPDATES_PER_HOUR | MAX_USER_CONNECTIONS | MEDIUM | MEMBER | MEMORY | MERGE | MESSAGE_TEXT | MID | MIGRATE | MIN | MIN_ROWS | MODE | MODIFY | MUTEX | MYSQL | MYSQL_ERRNO | NAME | NAMES | NATIONAL | NCHAR | NDB_STORED_USER | NESTED | NEVER | NEXT | NO | NOCOPY | NODEGROUP | NONE | NOWAIT | NUMBER | ODBC | OFFLINE | OFFSET | OF | OJ | OLD_PASSWORD | ONE | ONLINE | ONLY | OPEN | OPTIMIZER_COSTS | OPTIONAL | OPTIONS | ORDER | ORDINALITY | OWNER | PACK_KEYS | PAGE | PARSER | PARTIAL | PARTITIONING | PARTITIONS | PASSWORD | PASSWORDLESS_USER_ADMIN | PASSWORD_LOCK_TIME | PATH | PERCONA_SEQUENCE_TABLE | PERSIST_RO_VARIABLES_ADMIN | PHASE | PLUGINS | PLUGIN_DIR | PLUGIN | PORT | PRECEDES | PREPARE | PRESERVE | PREV | PRIMARY | PROCESSLIST | PROFILE | PROFILES | PROXY | QUERY | QUICK | REBUILD | RECOVER | RECURSIVE | REDO_BUFFER_SIZE | REDUNDANT | RELAY | RELAYLOG | RELAY_LOG_FILE | RELAY_LOG_POS | REMOVE | REORGANIZE | REPAIR | REPLICATE_DO_DB | REPLICATE_DO_TABLE | REPLICATE_IGNORE_DB | REPLICATE_IGNORE_TABLE | REPLICATE_REWRITE_DB | REPLICATE_WILD_DO_TABLE | REPLICATE_WILD_IGNORE_TABLE | REPLICATION | REPLICATION_APPLIER | REPLICATION_SLAVE_ADMIN | RESET | RESOURCE_GROUP_ADMIN | RESOURCE_GROUP_USER | RESUME | RETURNED_SQLSTATE | RETURNING | RETURNS | REUSE | ROLE | ROLE_ADMIN | ROLLBACK | ROLLUP | ROTATE | ROW | ROWS | ROW_FORMAT | RTREE | S3 | SAVEPOINT | SCHEDULE | SCHEMA_NAME | SECURITY | SECONDARY_ENGINE_ATTRIBUTE | SEQUENCE_TABLE | SERIAL | SERVER | SESSION | SESSION_VARIABLES_ADMIN | SET_USER_ID | SHARE | SHARED | SHOW_ROUTINE | SIGNED | SIMPLE | SLAVE | SLOW | SKIP_QUERY_REWRITE | SNAPSHOT | SOCKET | SOME | SONAME | SOUNDS | SOURCE | SQL_AFTER_GTIDS | SQL_AFTER_MTS_GAPS | SQL_BEFORE_GTIDS | SQL_BUFFER_RESULT | SQL_CACHE | SQL_NO_CACHE | SQL_THREAD | STACKED | START | STARTS | STATS_AUTO_RECALC | STATS_PERSISTENT | STATS_SAMPLE_PAGES | STATUS | STD | STDDEV | STDDEV_POP | STDDEV_SAMP | STOP | STORAGE | STRING | SUBCLASS_ORIGIN | SUBJECT | SUBPARTITION | SUBPARTITIONS | SUM | SUSPEND | SWAPS | SWITCHES | SYSTEM_VARIABLES_ADMIN | SYSTEM_USER | TABLE_NAME | TABLESPACE | TABLE_ENCRYPTION_ADMIN | TABLE_TYPE | TELEMETRY_LOG_ADMIN | TEMPORARY | TEMPTABLE | THAN | TP_CONNECTION_ADMIN | TRADITIONAL | TRANSACTION | TRANSACTIONAL | TRIGGERS | TRUNCATE | UNBOUNDED | UNDEFINED | UNDOFILE | UNDO_BUFFER_SIZE | UNINSTALL | UNKNOWN | UNTIL | UPGRADE | USA | USER | USE_FRM | USER_RESOURCES | VALIDATION | VALUE | VAR_POP | VAR_SAMP | VARIABLES | VARIANCE | VERSION_TOKEN_ADMIN | VIEW | VIRTUAL | WAIT | WARNINGS | WITHOUT | WORK | WRAPPER | X509 | XA | XA_RECOVER_ADMIN | XML | YES ; functionNameBase : ABS | ACOS | ADDDATE | ADDTIME | AES_DECRYPT | AES_ENCRYPT | AREA | ASBINARY | ASIN | ASTEXT | ASWKB | ASWKT | ASYMMETRIC_DECRYPT | ASYMMETRIC_DERIVE | ASYMMETRIC_ENCRYPT | ASYMMETRIC_SIGN | ASYMMETRIC_VERIFY | ATAN | ATAN2 | BENCHMARK | BIN | BIT_COUNT | BIT_LENGTH | BUFFER | CEIL | CEILING | CENTROID | CHARACTER_LENGTH | CHARSET | CHAR_LENGTH | COERCIBILITY | COLLATION | COMPRESS | CONCAT | CONCAT_WS | CONNECTION_ID | CONV | CONVERT_TZ | COS | COT | COUNT | CRC32 | CREATE_ASYMMETRIC_PRIV_KEY | CREATE_ASYMMETRIC_PUB_KEY | CREATE_DH_PARAMETERS | CREATE_DIGEST | CROSSES | CUME_DIST | DATABASE | DATE | DATEDIFF | DATE_FORMAT | DAY | DAYNAME | DAYOFMONTH | DAYOFWEEK | DAYOFYEAR | DECODE | DEGREES | DENSE_RANK | DES_DECRYPT | DES_ENCRYPT | DIMENSION | DISJOINT | DISTANCE | ELT | ENCODE | ENCRYPT | ENDPOINT | ENVELOPE | EQUALS | EXP | EXPORT_SET | EXTERIORRING | EXTRACTVALUE | FIELD | FIND_IN_SET | FIRST_VALUE | FLOOR | FORMAT | FOUND_ROWS | FROM_BASE64 | FROM_DAYS | FROM_UNIXTIME | GEOMCOLLFROMTEXT | GEOMCOLLFROMWKB | GEOMETRYCOLLECTION | GEOMETRYCOLLECTIONFROMTEXT | GEOMETRYCOLLECTIONFROMWKB | GEOMETRYFROMTEXT | GEOMETRYFROMWKB | GEOMETRYN | GEOMETRYTYPE | GEOMFROMTEXT | GEOMFROMWKB | GET_FORMAT | GET_LOCK | GLENGTH | GREATEST | GTID_SUBSET | GTID_SUBTRACT | HEX | HOUR | IFNULL | INET6_ATON | INET6_NTOA | INET_ATON | INET_NTOA | INSTR | INTERIORRINGN | INTERSECTS | INVISIBLE | ISCLOSED | ISEMPTY | ISNULL | ISSIMPLE | IS_FREE_LOCK | IS_IPV4 | IS_IPV4_COMPAT | IS_IPV4_MAPPED | IS_IPV6 | IS_USED_LOCK | LAG | LAST_INSERT_ID | LAST_VALUE | LCASE | LEAD | LEAST | LEFT | LENGTH | LINEFROMTEXT | LINEFROMWKB | LINESTRING | LINESTRINGFROMTEXT | LINESTRINGFROMWKB | LN | LOAD_FILE | LOCATE | LOG | LOG10 | LOG2 | LOWER | LPAD | LTRIM | MAKEDATE | MAKETIME | MAKE_SET | MASTER_POS_WAIT | MBRCONTAINS | MBRDISJOINT | MBREQUAL | MBRINTERSECTS | MBROVERLAPS | MBRTOUCHES | MBRWITHIN | MD5 | MICROSECOND | MINUTE | MLINEFROMTEXT | MLINEFROMWKB | MOD | MONTH | MONTHNAME | MPOINTFROMTEXT | MPOINTFROMWKB | MPOLYFROMTEXT | MPOLYFROMWKB | MULTILINESTRING | MULTILINESTRINGFROMTEXT | MULTILINESTRINGFROMWKB | MULTIPOINT | MULTIPOINTFROMTEXT | MULTIPOINTFROMWKB | MULTIPOLYGON | MULTIPOLYGONFROMTEXT | MULTIPOLYGONFROMWKB | NAME_CONST | NTH_VALUE | NTILE | NULLIF | NUMGEOMETRIES | NUMINTERIORRINGS | NUMPOINTS | OCT | OCTET_LENGTH | ORD | OVERLAPS | PERCENT_RANK | PERIOD_ADD | PERIOD_DIFF | PI | POINT | POINTFROMTEXT | POINTFROMWKB | POINTN | POLYFROMTEXT | POLYFROMWKB | POLYGON | POLYGONFROMTEXT | POLYGONFROMWKB | POSITION | POW | POWER | QUARTER | QUOTE | RADIANS | RAND | RANDOM | RANK | RANDOM_BYTES | RELEASE_LOCK | REVERSE | RIGHT | ROUND | ROW_COUNT | ROW_NUMBER | RPAD | RTRIM | SCHEMA | SECOND | SEC_TO_TIME | SESSION_USER | SESSION_VARIABLES_ADMIN | SHA | SHA1 | SHA2 | SIGN | SIN | SLEEP | SOUNDEX | SQL_THREAD_WAIT_AFTER_GTIDS | SQRT | SRID | STARTPOINT | STRCMP | STR_TO_DATE | ST_AREA | ST_ASBINARY | ST_ASTEXT | ST_ASWKB | ST_ASWKT | ST_BUFFER | ST_CENTROID | ST_CONTAINS | ST_CROSSES | ST_DIFFERENCE | ST_DIMENSION | ST_DISJOINT | ST_DISTANCE | ST_ENDPOINT | ST_ENVELOPE | ST_EQUALS | ST_EXTERIORRING | ST_GEOMCOLLFROMTEXT | ST_GEOMCOLLFROMTXT | ST_GEOMCOLLFROMWKB | ST_GEOMETRYCOLLECTIONFROMTEXT | ST_GEOMETRYCOLLECTIONFROMWKB | ST_GEOMETRYFROMTEXT | ST_GEOMETRYFROMWKB | ST_GEOMETRYN | ST_GEOMETRYTYPE | ST_GEOMFROMTEXT | ST_GEOMFROMWKB | ST_INTERIORRINGN | ST_INTERSECTION | ST_INTERSECTS | ST_ISCLOSED | ST_ISEMPTY | ST_ISSIMPLE | ST_LINEFROMTEXT | ST_LINEFROMWKB | ST_LINESTRINGFROMTEXT | ST_LINESTRINGFROMWKB | ST_NUMGEOMETRIES | ST_NUMINTERIORRING | ST_NUMINTERIORRINGS | ST_NUMPOINTS | ST_OVERLAPS | ST_POINTFROMTEXT | ST_POINTFROMWKB | ST_POINTN | ST_POLYFROMTEXT | ST_POLYFROMWKB | ST_POLYGONFROMTEXT | ST_POLYGONFROMWKB | ST_SRID | ST_STARTPOINT | ST_SYMDIFFERENCE | ST_TOUCHES | ST_UNION | ST_WITHIN | ST_X | ST_Y | STRING_TO_VECTOR | SUBDATE | SUBSTRING_INDEX | SUBTIME | SYSTEM_USER | TAN | TIME | TIMEDIFF | TIMESTAMP | TIMESTAMPADD | TIMESTAMPDIFF | TIME_FORMAT | TIME_TO_SEC | TOUCHES | TO_BASE64 | TO_DAYS | TO_SECONDS | UCASE | UNCOMPRESS | UNCOMPRESSED_LENGTH | UNHEX | UNIX_TIMESTAMP | UPDATEXML | UPPER | UUID | UUID_SHORT | VALIDATE_PASSWORD_STRENGTH | VECTOR_DIM | VECTOR_TO_STRING | VERSION | VISIBLE | WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS | WEEK | WEEKDAY | WEEKOFYEAR | WEIGHT_STRING | WITHIN | YEAR | YEARWEEK | Y_FUNCTION | X_FUNCTION | JSON_ARRAY | JSON_OBJECT | JSON_QUOTE | JSON_CONTAINS | JSON_CONTAINS_PATH | JSON_EXTRACT | JSON_KEYS | JSON_OVERLAPS | JSON_SEARCH | JSON_VALUE | JSON_ARRAY_APPEND | JSON_ARRAY_INSERT | JSON_INSERT | JSON_MERGE | JSON_MERGE_PATCH | JSON_MERGE_PRESERVE | JSON_REMOVE | JSON_REPLACE | JSON_SET | JSON_UNQUOTE | JSON_DEPTH | JSON_LENGTH | JSON_TYPE | JSON_VALID | JSON_TABLE | JSON_SCHEMA_VALID | JSON_SCHEMA_VALIDATION_REPORT | JSON_PRETTY | JSON_STORAGE_FREE | JSON_STORAGE_SIZE | JSON_ARRAYAGG | JSON_OBJECTAGG | STATEMENT ; ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.mysql import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.mysql.antlr4.MySqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(MySqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: MySqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(MySqlParser._ATN)) } } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/MySqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.mysql import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.AlterActionType.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.common.UseDatabase import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.common.relational.table.TruncateTable import io.github.melin.superior.parser.mysql.antlr4.MySqlParser import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.AlterByAddIndexContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.AlterByAddPrimaryKeyContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.AlterByDropPrimaryKeyContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.AlterByTruncatePartitionContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.PartitionFunctionHashContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.PartitionFunctionKeyContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.PartitionFunctionListContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParser.PartitionFunctionRangeContext import io.github.melin.superior.parser.mysql.antlr4.MySqlParserBaseVisitor import org.antlr.v4.runtime.tree.TerminalNodeImpl import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/2/8. */ class MySqlAntlr4Visitor(val splitSql: Boolean = false) : MySqlParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private val primaryKeys = ArrayList() private var inputTables: ArrayList = arrayListOf() private var inCte = false private var cteTempTables: ArrayList = arrayListOf() // 多语句解析结果 private var statements: ArrayList = arrayListOf() // 存储过程和函数中包含的子语句 private var childStatements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun visitSqlStatements(ctx: MySqlParser.SqlStatementsContext): Statement? { ctx.sqlStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSqlStatement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } override fun visitSqlStatement(ctx: MySqlParser.SqlStatementContext): Statement? { val statement = super.visitSqlStatement(ctx) if ( statement != null && statement.statementType != StatementType.CREATE_FUNCTION && statement.statementType != StatementType.CREATE_PROCEDURE ) { childStatements.add(statement) } return statement } override fun visitDeclareCursor(ctx: MySqlParser.DeclareCursorContext): Statement? { val statement = super.visitDeclareCursor(ctx) if ( statement != null && statement.statementType != StatementType.CREATE_FUNCTION && statement.statementType != StatementType.CREATE_PROCEDURE ) { childStatements.add(statement) } return statement } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() inCte = false cteTempTables = arrayListOf() } // -----------------------------------database------------------------------------------------- override fun visitCreateDatabase(ctx: MySqlParser.CreateDatabaseContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.uid().text) return CreateDatabase(databaseName) } override fun visitDropDatabase(ctx: MySqlParser.DropDatabaseContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.uid().text) return DropDatabase(databaseName) } // -----------------------------------table------------------------------------------------- override fun visitColumnCreateTable(ctx: MySqlParser.ColumnCreateTableContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) var comment: String? = null ctx.tableOption().forEach { when (it) { is MySqlParser.TableOptionCommentContext -> { comment = CommonUtils.cleanQuote(it.STRING_LITERAL().text) } } } val columnRels = ArrayList() ctx.createDefinitions().children.forEach { column -> if (column is MySqlParser.ColumnDeclarationContext) { val name = CommonUtils.cleanQuote(column.fullColumnName().text) var dataType = column.columnDefinition().dataType().getChild(0).text.lowercase() val count = column.columnDefinition().dataType().childCount if (count > 1) { val item = column.columnDefinition().dataType().getChild(1) if ( item is MySqlParser.LengthOneDimensionContext || item is MySqlParser.LengthTwoDimensionContext || item is MySqlParser.LengthTwoOptionalDimensionContext ) { dataType = dataType + item.text } } var colComment: String? = null column.columnDefinition().columnConstraint().forEach { if (it is MySqlParser.CommentColumnConstraintContext) { colComment = CommonUtils.cleanQuote(it.STRING_LITERAL().text) } } columnRels.add(ColumnRel(name, dataType, colComment)) } } super.visitColumnCreateTable(ctx) val ifNotExists: Boolean = if (ctx.ifNotExists() != null) true else false columnRels.forEach { columnRel: ColumnRel -> if (primaryKeys.contains(columnRel.columnName)) { columnRel.primaryKey = true } } val createTable = CreateTable(tableId, TableType.MYSQL, comment, null, null, columnRels, null, null, ifNotExists) if (ctx.partitionDefinitions() != null) { val def = ctx.partitionDefinitions().partitionFunctionDefinition() if (def is PartitionFunctionHashContext) { createTable.partitionType = PartitionType.HASH } else if (def is PartitionFunctionKeyContext) { createTable.partitionType = PartitionType.KEY } else if (def is PartitionFunctionRangeContext) { createTable.partitionType = PartitionType.RANGE } else if (def is PartitionFunctionListContext) { createTable.partitionType = PartitionType.LIST } } return createTable } override fun visitQueryCreateTable(ctx: MySqlParser.QueryCreateTableContext): Statement { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val tableId = parseFullId(ctx.tableName().fullId()) var comment: String? = null ctx.tableOption().forEach { when (it) { is MySqlParser.TableOptionCommentContext -> { comment = CommonUtils.cleanQuote(it.STRING_LITERAL().text) } } } val ifNotExists: Boolean = if (ctx.ifNotExists() != null) true else false val queryStmt = this.visitSelectStatement(ctx.selectStatement()) as QueryStmt val createTable = CreateTableAsSelect(tableId, queryStmt, comment, null, null, null, null, null, ifNotExists) return createTable } override fun visitCopyCreateTable(ctx: MySqlParser.CopyCreateTableContext): Statement? { currentOptType = StatementType.CREATE_TABLE_AS_LIKE val tableId = parseFullId(ctx.tableName().get(0).fullId()) var likeTableId = parseFullId(ctx.tableName().get(1).fullId()) var createTableLike = CreateTableLike(likeTableId, tableId, false, false, false); return createTableLike; } override fun visitPrimaryKeyTableConstraint(ctx: MySqlParser.PrimaryKeyTableConstraintContext): Statement? { val count = ctx.indexColumnNames().childCount for (i in 1..(count - 2)) { var column = ctx.indexColumnNames().getChild(i).text column = CommonUtils.cleanQuote(column) primaryKeys.add(column) } return null } override fun visitDropTable(ctx: MySqlParser.DropTableContext): Statement { if (ctx.tables().tableName().size > 1) { throw SQLParserException("不支持drop多个表") } val tableId = parseFullId(ctx.tables().tableName(0).fullId()) val dropTable = DropTable(tableId) dropTable.ifExists = if (ctx.ifExists() != null) true else false return dropTable } override fun visitTruncateTable(ctx: MySqlParser.TruncateTableContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) return TruncateTable(tableId) } override fun visitRenameTable(ctx: MySqlParser.RenameTableContext): Statement { val tableId = parseFullId(ctx.renameTableClause().get(0).tableName(0).fullId()) val newTableId = parseFullId(ctx.renameTableClause().get(0).tableName(1).fullId()) val action = RenameAction(newTableId) return AlterTable(tableId, action) } override fun visitUseStatement(ctx: MySqlParser.UseStatementContext): Statement { val databaseName = ctx.uid().text return UseDatabase(databaseName) } // -----------------------------------Alter----------------------------------------------- override fun visitAlterTable(ctx: MySqlParser.AlterTableContext): Statement? { val tableId = parseFullId(ctx.tableName().fullId()) val alterTable = AlterTable(tableId) ctx.alterSpecification().forEach { statement -> if (statement is MySqlParser.AlterByChangeColumnContext) { val columnName = CommonUtils.cleanQuote(statement.oldColumn.text) val newColumnName = CommonUtils.cleanQuote(statement.newColumn.text) val dataType = source(statement.columnDefinition().dataType()) var comment: String? = null var nullable: Boolean = true var defaultExpr: String? = null statement.columnDefinition().children.forEach { if (it is MySqlParser.CommentColumnConstraintContext) { comment = CommonUtils.cleanQuote(it.STRING_LITERAL().text) } else if (it is MySqlParser.NullColumnConstraintContext) { nullable = it.nullNotnull().NOT() == null } else if (it is MySqlParser.DefaultColumnConstraintContext) { defaultExpr = source(it.defaultValue()) } } val action = AlterColumnAction(ALTER_COLUMN, columnName, dataType, comment) action.newColumName = newColumnName action.nullable = nullable action.defaultExpression = defaultExpr alterTable.addAction(action) } else if (statement is MySqlParser.AlterByAddColumnContext) { val columnName = CommonUtils.cleanQuote(statement.uid().get(0).text) val dataType = statement.columnDefinition().dataType().text var comment: String? = null var nullable: Boolean = true var defaultExpr: String? = null statement.columnDefinition().children.forEach { if (it is MySqlParser.CommentColumnConstraintContext) { comment = CommonUtils.cleanQuote(it.STRING_LITERAL().text) } else if (it is MySqlParser.NullColumnConstraintContext) { nullable = it.nullNotnull().NOT() == null } else if (it is MySqlParser.DefaultColumnConstraintContext) { defaultExpr = source(it.defaultValue()) } } val action = AlterColumnAction(ADD_COLUMN, columnName, dataType, comment) action.nullable = nullable action.defaultExpression = defaultExpr alterTable.addAction(action) } else if (statement is MySqlParser.AlterByDropColumnContext) { val columnName = CommonUtils.cleanQuote(statement.uid().text) val action = DropColumnAction(columnName) return AlterTable(tableId, action) } else if (statement is MySqlParser.AlterByModifyColumnContext) { val columnName = CommonUtils.cleanQuote(statement.uid().get(0).text) val dataType = statement.columnDefinition().dataType().text val action = AlterColumnAction(ALTER_COLUMN, columnName, dataType) alterTable.addAction(action) } else if (statement is AlterByAddIndexContext) { val createIndex = CreateIndex(statement.uid().text) alterTable.addAction(createIndex) } else if (statement is MySqlParser.AlterByDropIndexContext) { val dropIndex = DropIndex(statement.uid().text) alterTable.addAction(dropIndex) } else if (statement is AlterByAddPrimaryKeyContext) { val action = AlterTableAction(ADD_PRIMARY_KEY) alterTable.addAction(action) } else if (statement is AlterByDropPrimaryKeyContext) { val action = AlterTableAction(DROP_PRIMARY_KEY) alterTable.addAction(action) } else if (statement is MySqlParser.AlterByAddUniqueKeyContext) { val action = AlterTableAction(ADD_UNIQUE_KEY) alterTable.addAction(action) } else if (statement is MySqlParser.AlterPartitionContext) { val alterPartition = statement.alterPartitionSpecification() if (alterPartition is AlterByTruncatePartitionContext) { val action = AlterTableAction(TRUNCATE_PARTITION) alterTable.addAction(action) } else if (alterPartition is MySqlParser.AlterByDropPartitionContext) { val action = AlterTableAction(DROP_PARTITION) alterTable.addAction(action) } else if (alterPartition is MySqlParser.AlterByAddPartitionContext) { val action = AlterTableAction(ADD_PARTITION) alterTable.addAction(action) } } } if (alterTable.actions.size > 0) { return alterTable } else { return super.visitAlterTable(ctx) } } override fun visitAnalyzeTable(ctx: MySqlParser.AnalyzeTableContext): Statement { val tables = ArrayList() ctx.tables().tableName().forEach { context -> val tableId = parseFullId(context.fullId()) tables.add(tableId) } return AnalyzeTable(tables) } // -----------------------------------DML------------------------------------------------- override fun visitSelectStatement(ctx: MySqlParser.SelectStatementContext): Statement { if (currentOptType == StatementType.UNKOWN) { currentOptType = StatementType.SELECT } super.visitSelectStatement(ctx) return QueryStmt(inputTables, limit, offset) } override fun visitInsertStatement(ctx: MySqlParser.InsertStatementContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) currentOptType = StatementType.INSERT if (ctx.insertStatementValue().selectStatement() != null) { val queryStmt = this.visitSelectStatement(ctx.insertStatementValue().selectStatement()) as QueryStmt val insertTable = InsertTable(InsertMode.INTO, queryStmt, tableId) insertTable?.setSql(source(ctx)) return insertTable } else { val insertTable = InsertTable(InsertMode.INTO, QueryStmt(), tableId) insertTable?.setSql(source(ctx)) return insertTable } } override fun visitReplaceStatement(ctx: MySqlParser.ReplaceStatementContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) currentOptType = StatementType.INSERT if (ctx.insertStatementValue().selectStatement() != null) { val queryStmt = this.visitSelectStatement(ctx.insertStatementValue().selectStatement()) as QueryStmt val insertTable = InsertTable(InsertMode.INTO, queryStmt, tableId) insertTable.mysqlReplace = true return insertTable } else { return InsertTable(InsertMode.INTO, QueryStmt(), tableId) } } override fun visitDeleteStatement(ctx: MySqlParser.DeleteStatementContext): Statement { currentOptType = StatementType.DELETE val deleteTable = if (ctx.multipleDeleteStatement() != null) { this.visit(ctx.multipleDeleteStatement().expression()) val outputTables = ctx.multipleDeleteStatement().tableName().map { parseFullId(it.fullId()) } val deleteTable = DeleteTable(outputTables.first(), inputTables) super.visitTableSources(ctx.multipleDeleteStatement().tableSources()) deleteTable.outputTables.addAll(outputTables.subList(1, outputTables.size)) deleteTable } else { if (ctx.singleDeleteStatement().expression() != null) { this.visit(ctx.singleDeleteStatement().expression()) } val tableId = parseFullId(ctx.singleDeleteStatement().tableName().fullId()) DeleteTable(tableId, inputTables) } return deleteTable } override fun visitUpdateStatement(ctx: MySqlParser.UpdateStatementContext): Statement { currentOptType = StatementType.UPDATE val updateTable = if (ctx.multipleUpdateStatement() != null) { super.visitTableSources(ctx.multipleUpdateStatement().tableSources()) val expression = ctx.singleUpdateStatement().expression() if (expression != null) { this.visit(expression) } val updateTable = UpdateTable(inputTables.first(), inputTables.toMutableList()) updateTable } else { super.visitTableSources(ctx.singleUpdateStatement().tableSources()) val expression = ctx.singleUpdateStatement().expression() if (expression != null) { this.visit(expression) } val updateTable = UpdateTable(inputTables.first(), inputTables.toMutableList()) updateTable } return updateTable } override fun visitCreateIndex(ctx: MySqlParser.CreateIndexContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) val createIndex = CreateIndex(ctx.uid().text) return AlterTable(tableId, createIndex) } override fun visitDropIndex(ctx: MySqlParser.DropIndexContext): Statement { val tableId = parseFullId(ctx.tableName().fullId()) val dropIndex = DropIndex(ctx.uid().text) return AlterTable(tableId, dropIndex) } override fun visitCreateProcedure(ctx: MySqlParser.CreateProcedureContext): Statement { super.visitCreateProcedure(ctx) val tableId = parseFullId(ctx.fullId()) val procedureId = ProcedureId(tableId.schemaName, tableId.tableName) return CreateProcedure(procedureId, childStatements, false) } override fun visitCreateFunction(ctx: MySqlParser.CreateFunctionContext): Statement { super.visitCreateFunction(ctx) val tableId = parseFullId(ctx.fullId()) val functionId = FunctionId(tableId.schemaName, tableId.tableName) return CreateFunction(functionId, childStatements, false) } // -----------------------------------private // method------------------------------------------------- override fun visitWithStatement(ctx: MySqlParser.WithStatementContext): Statement? { inCte = true ctx.commonTableExpressions().forEach { val tableId = TableId(it.cteName().text) cteTempTables.add(tableId) super.visitDmlStatement(it.dmlStatement()) } inCte = false return null } override fun visitTableName(ctx: MySqlParser.TableNameContext): Statement? { if ( StatementType.SELECT == currentOptType || StatementType.INSERT == currentOptType || StatementType.UPDATE == currentOptType || StatementType.DELETE == currentOptType || StatementType.CREATE_TABLE_AS_SELECT == currentOptType ) { val tableId = parseFullId(ctx.fullId()) // 别名和表名一样的场景 if (inCte && cteTempTables.last() == tableId) { cteTempTables.remove(tableId) } if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } override fun visitLimitClause(ctx: MySqlParser.LimitClauseContext): Statement? { if (ctx.limit != null && ctx.limit.decimalLiteral() != null) { limit = ctx.limit.text.toInt() } if (ctx.offset != null && ctx.offset.decimalLiteral() != null) { offset = ctx.offset.text.toInt() } return super.visitLimitClause(ctx) } private fun parseFullId(fullId: MySqlParser.FullIdContext): TableId { var databaseName: String? = null var tableName: String = "" if (fullId.childCount == 2) { databaseName = fullId.uid().get(0).text tableName = (fullId.getChild(1) as TerminalNodeImpl).text.substring(1) } else if (fullId.childCount == 3) { databaseName = CommonUtils.cleanQuote(fullId.uid().get(0).text) tableName = CommonUtils.cleanQuote((fullId.getChild(2) as MySqlParser.UidContext).text) } else { tableName = fullId.uid().get(0).text } if (databaseName != null) { databaseName = CommonUtils.cleanQuote(databaseName) } tableName = CommonUtils.cleanQuote(tableName) return TableId(databaseName, tableName) } } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/MySqlHelper.kt ================================================ package com.github.melin.superior.sql.parser.mysql import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.mysql.AbstractSqlParser import io.github.melin.superior.parser.mysql.MySqlAntlr4Visitor import io.github.melin.superior.parser.mysql.antlr4.MySqlLexer import io.github.melin.superior.parser.mysql.antlr4.MySqlParser import io.github.melin.superior.parser.mysql.antlr4.MySqlParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object MySqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until MySqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = MySqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = MySqlAntlr4Visitor(false) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = MySqlAntlr4Visitor(true) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = MySqlParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: MySqlParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = MySqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = MySqlParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visitSqlStatements(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visitSqlStatements(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/type/JsonType.kt ================================================ package io.github.melin.superior.parser.mysql.type import io.github.melin.superior.common.type.AbsType class JsonType : AbsType() { override val name: String = "json" } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/type/datetime.kt ================================================ package io.github.melin.superior.parser.mysql.type import io.github.melin.superior.common.type.AbsDataTimeType class DateType : AbsDataTimeType() { override val name: String = "date" } data class TimeType(val precision: Int = 0) : AbsDataTimeType() { override val name: String = "time" } data class TimeStampType(val precision: Int = 0) : AbsDataTimeType() { override val name: String = "timestamp" } data class DateTimeType(val precision: Int = 0) : AbsDataTimeType() { override val name: String = "datetime" } class YearType : AbsDataTimeType() { override val name: String = "year" } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/type/numeric.kt ================================================ package io.github.melin.superior.parser.mysql.type import io.github.melin.superior.common.type.AbsNumericType data class TinyintType(val length: Int, val unsigned: Boolean = false, val zerofill: Boolean = false) : AbsNumericType() { override val name: String = "tinyint" override val alias: String = "int1" companion object { const val MIN_VALUE: Short = -128 const val MAX_VALUE: Short = 127 } } data class SmallIntType(val length: Int, val unsigned: Boolean = false, val zerofill: Boolean = false) : AbsNumericType() { override val name: String = "smallint" override val alias: String = "int2" companion object { const val MIN_VALUE: Int = -32768 const val MAX_VALUE: Int = 32767 } } data class MediumIntType(val length: Int, val unsigned: Boolean = false, val zerofill: Boolean = false) : AbsNumericType() { override val name: String = "mediumint" override val alias: String = "int3" companion object { const val MIN_VALUE: Int = -8388608 const val MAX_VALUE: Int = 8388607 } } data class IntegerType(val length: Int) : AbsNumericType() { override val name: String = "integer" override val alias: String = "int" override val alias2: String = "int4" companion object { const val MIN_VALUE: Long = -2147483648L const val MAX_VALUE: Long = 2147483647L } } data class BigIntType(val length: Int, val unsigned: Boolean = false, val zerofill: Boolean = false) : AbsNumericType() { override val name: String = "bigint" override val alias: String = "int8" } data class DecimalType(val precision: Int = 10, val scale: Int = 0) : AbsNumericType() { override val name: String = "decimal" } data class FloatType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "float" } data class DoubleType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "double" override val alias: String = "float8" } data class RealType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "real" override val alias: String = "float4" } data class BitType(val length: Int) : AbsNumericType() { override val name: String = "bit" } ================================================ FILE: superior-mysql-parser/src/main/kotlin/io/github/melin/superior/parser/mysql/type/string.kt ================================================ package io.github.melin.superior.parser.mysql.type import io.github.melin.superior.common.type.AbsStringType data class CharType(val length: Int) : AbsStringType() { override val name: String = "char" companion object { const val MAX_LENGTH: Int = 255 } } data class VarcharType(val length: Int) : AbsStringType() { override val name: String = "varchar" companion object { const val MAX_LENGTH: Int = 65535 } } data class BinaryType(val length: Int) : AbsStringType() { override val name: String = "binary" companion object { const val MAX_LENGTH: Int = 255 } } data class VarbinaryType(val length: Int) : AbsStringType() { override val name: String = "varbinary" companion object { const val MAX_LENGTH: Int = 65535 } } class TinyblobType : AbsStringType() { override val name: String = "tinyblob" } class BlobType : AbsStringType() { override val name: String = "blob" } class MediumblobType : AbsStringType() { override val name: String = "mediumblob" } class LongblobType : AbsStringType() { override val name: String = "longblob" } class TinytextType : AbsStringType() { override val name: String = "tinytext" } class TextType : AbsStringType() { override val name: String = "text" } class MediumtextType : AbsStringType() { override val name: String = "mediumtext" } class LongtextType : AbsStringType() { override val name: String = "longtext" } data class EnumType(val values: List) : AbsStringType() { override val name: String = "enum" } data class SetType(val values: List) : AbsStringType() { override val name: String = "set" } ================================================ FILE: superior-mysql-parser/src/test/kotlin/io/github/melin/superior/parser/mysql/MySqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.mysql import com.github.melin.superior.sql.parser.mysql.MySqlHelper import io.github.melin.superior.common.* import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.UseDatabase import io.github.melin.superior.common.relational.create.CreateDatabase import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.table.TruncateTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class MySqlParserDdlTest { @Test fun splitSqlTest() { val sql = """ CREATE DATABASE IF NOT EXISTS bigdata1; drop DATABASE IF EXISTS bigdata2 """ .trimIndent() val statements = MySqlHelper.splitSql(sql) Assert.assertEquals(2, statements.size) Assert.assertEquals("CREATE DATABASE IF NOT EXISTS bigdata1", statements.get(0)) } @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE IF NOT EXISTS "bigdata1"; drop DATABASE IF EXISTS bigdata2 """ .trimIndent() val statements = MySqlHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("bigdata1", createDatabse.databaseName) } if (dropDatabase is CreateDatabase) { Assert.assertEquals("bigdata2", dropDatabase.databaseName) } } @Test fun dropDatabaseTest() { val sql = "DROP DATABASE IF EXISTS bigdata" val statement = MySqlHelper.parseStatement(sql) if (statement is DropDatabase) { val name = statement.databaseName Assert.assertEquals(StatementType.DROP_DATABASE, statement.statementType) Assert.assertEquals("bigdata", name) } else { Assert.fail() } } @Test fun createTableTest() { val sql = "CREATE TABLE bigdata.dc_config (\n" + " `id` int(11) NOT NULL AUTO_INCREMENT comment 'id',\n" + " `appname` varchar(64) NOT NULL,\n" + " `profile` varchar(64) NOT NULL,\n" + " `width` DECIMAL(5, 2) NOT NULL,\n" + " `config_text` longtext,\n" + " `content` json,\n" + " `content1` text COLLATE utf8mb4_unicode_ci comment 'test',\n" + " `creater` varchar(45) NOT NULL,\n" + " `modifier` varchar(45) DEFAULT NULL,\n" + " `gmt_created` datetime NOT NULL,\n" + " `gmt_modified` datetime DEFAULT NULL,\n" + " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `appname_UNIQUE` (`appname`,`profile`)\n" + ") ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='系统参数配置';" val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("bigdata", statement.tableId.schemaName) Assert.assertEquals("dc_config", statement.tableId.tableName) Assert.assertEquals("系统参数配置", statement.comment) statement.columnRels?.get(0)?.let { Assert.assertTrue(it.primaryKey) } } else { Assert.fail() } } @Test fun createTableTest1() { val sql = "CREATE TABLE `box_partner` (\n" + " `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n" + " `code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户编码',\n" + " `name` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '客户名称',\n" + " `role` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户角色',\n" + " `key` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户key',\n" + " `logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户logo',\n" + " `info` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户简介',\n" + " `contacts` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系方式',\n" + " `token` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户唯一标识',\n" + " `callback_url` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '客户提供的回调地址',\n" + " `attachment` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '扩展字段',\n" + " `create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" + " `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n" + " `callback_url_status` int(11) DEFAULT NULL COMMENT '回调地址状态:成功0,失败1,通讯中断2',\n" + " `callback_url_detail` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '回调事件',\n" + " PRIMARY KEY (`id`),\n" + " UNIQUE KEY `token` (`token`)\n" + " ) ENGINE=InnoDB AUTO_INCREMENT=7564 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("box_partner", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createTableTest2() { val sql = " CREATE TABLE `decision_flow_model` (\n" + " `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',\n" + " `model_uuid` char(32) NOT NULL COMMENT '关联holmes_model表的uuid',\n" + " `partner_code` varchar(128) NOT NULL COMMENT '合作方',\n" + " `decision_flow_uuid` char(32) NOT NULL COMMENT '关联decision_flow表的uuid',\n" + " `gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',\n" + " `gmt_modify` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',\n" + " PRIMARY KEY (`id`)\n" + ") ENGINE=InnoDB AUTO_INCREMENT=4475 DEFAULT CHARSET=utf8 COMMENT='决策流与模型关系表'" val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("decision_flow_model", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createTableTest3() { val sql = "CREATE TABLE `app_channel_daily_report` (\n" + " `id` bigint(20) NOT NULL AUTO_INCREMENT,\n" + " `normal_counting` bigint(20) NOT NULL DEFAULT '0' COMMENT '正常用户',\n" + " `abnormal_counting` bigint(20) NOT NULL DEFAULT '0' COMMENT '异常用户',\n" + " `emulator_counting` bigint(20) NOT NULL DEFAULT '0' COMMENT '模拟器用户',\n" + " `gmt_create` datetime NOT NULL COMMENT '创建时间',\n" + " `gmt_modified` datetime DEFAULT NULL COMMENT '更新时间',\n" + " `create_by` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '创建者',\n" + " `update_by` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '更新者',\n" + " `event_type` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '事件类型',\n" + " `partner_code` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '合作方编码',\n" + " `app_channel` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '渠道',\n" + " `app_name` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'app名称',\n" + " `app_version` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'default',\n" + " PRIMARY KEY (`id`,`gmt_create`),\n" + " KEY `channel_report_index` (`gmt_create`,`partner_code`,`app_channel`,`app_name`,`app_version`,`event_type`)\n" + ") ENGINE=InnoDB AUTO_INCREMENT=33703438 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='渠道反作弊日统计表'\n" + " PARTITION BY RANGE (month(gmt_create)-1)\n" + "(PARTITION part0 VALUES LESS THAN (1) COMMENT = '1月份' ENGINE = InnoDB,\n" + " PARTITION part1 VALUES LESS THAN (2) COMMENT = '2月份' ENGINE = InnoDB,\n" + " PARTITION part2 VALUES LESS THAN (3) COMMENT = '3月份' ENGINE = InnoDB,\n" + " PARTITION part3 VALUES LESS THAN (4) COMMENT = '4月份' ENGINE = InnoDB,\n" + " PARTITION part4 VALUES LESS THAN (5) COMMENT = '5月份' ENGINE = InnoDB,\n" + " PARTITION part5 VALUES LESS THAN (6) COMMENT = '6月份' ENGINE = InnoDB,\n" + " PARTITION part6 VALUES LESS THAN (7) COMMENT = '7月份' ENGINE = InnoDB,\n" + " PARTITION part7 VALUES LESS THAN (8) COMMENT = '8月份' ENGINE = InnoDB,\n" + " PARTITION part8 VALUES LESS THAN (9) COMMENT = '9月份' ENGINE = InnoDB,\n" + " PARTITION part9 VALUES LESS THAN (10) COMMENT = '10月份' ENGINE = InnoDB,\n" + " PARTITION part10 VALUES LESS THAN (11) COMMENT = '11月份' ENGINE = InnoDB,\n" + " PARTITION part11 VALUES LESS THAN (12) COMMENT = '12月份' ENGINE = InnoDB)" val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("app_channel_daily_report", statement.tableId.tableName) Assert.assertEquals(PartitionType.RANGE, statement.partitionType) } else { Assert.fail() } } @Test fun createTableTest4() { val sql = """ CREATE TABLE IF NOT EXISTS `decision_flow_model` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `model_uuid` char(32) NOT NULL COMMENT '关联holmes_model表的uuid', `partner_code` varchar(128) NOT NULL COMMENT '合作方', `decision_flow_uuid` char(32) NOT NULL COMMENT '关联decision_flow表的uuid', `gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gmt_modify` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=77 DEFAULT CHARSET=utf8 """ val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("decision_flow_model", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createTableTest5() { val sql = """ CREATE TABLE `dw_job_analysis_detail` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(255) DEFAULT NULL, `job_id` int(11) DEFAULT NULL, `job_type` varchar(255) DEFAULT NULL, `job_status` int(255) DEFAULT NULL, `create_time` timestamp(6) NULL DEFAULT NULL, `creater` varchar(255) DEFAULT NULL, `modifier` varchar(255) DEFAULT NULL, `gmt_created` timestamp(6) NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6), `gmt_modified` datetime(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6), PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=75306 DEFAULT CHARSET=utf8 """ val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("dw_job_analysis_detail", statement.tableId.tableName) } else { Assert.fail() } } @Test fun dropTableTest() { val sql = "DROP table IF EXISTS bigdata.users" val statement = MySqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals("bigdata", statement.tableId.schemaName) Assert.assertEquals("users", statement.tableId.tableName) } else { Assert.fail() } } @Test fun renameTableTest() { val sql = "RENAME TABLE `datacompute`.`users_quan` TO `datacompute`.`dc_users`\n" val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("datacompute", statement.tableId.schemaName) Assert.assertEquals("users_quan", statement.tableId.tableName) val action = statement.firstAction() as RenameAction Assert.assertEquals(AlterActionType.RENAME, action.alterType) Assert.assertEquals("dc_users", action.newTableId.tableName) } else { Assert.fail() } } @Test fun analyzeTableTest() { val sql = "analyze table bigdata.users" val statement = MySqlHelper.parseStatement(sql) if (statement is AnalyzeTable) { val table = statement.tableIds.get(0) Assert.assertEquals(StatementType.ANALYZE_TABLE, statement.statementType) Assert.assertEquals("bigdata", table.schemaName) Assert.assertEquals("users", table.tableName) } else { Assert.fail() } } @Test fun truncateTableTest() { val sql = "TRUNCATE TABLE test.user" val statement = MySqlHelper.parseStatement(sql) if (statement is TruncateTable) { Assert.assertEquals(StatementType.TRUNCATE_TABLE, statement.statementType) Assert.assertEquals("test", statement.tableId.schemaName) Assert.assertEquals("user", statement.tableId.tableName) } else { Assert.fail() } } @Test fun changeColumnTest() { val sql = "ALTER TABLE `datacompute`.`log_collect_config` \n" + "CHANGE COLUMN `partition_type` `partition_type1` VARCHAR(45) NULL DEFAULT 'day' COMMENT '分区类型:day, hour, minute' ;" val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("datacompute", statement.tableId.schemaName) Assert.assertEquals("log_collect_config", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("partition_type", action.columName) Assert.assertEquals("partition_type1", action.newColumName) Assert.assertEquals("分区类型:day, hour, minute", action.comment) } else { Assert.fail() } } @Test fun modifyColumnTest() { val sql = "ALTER TABLE t1 MODIFY age BIGINT NOT NULL;" val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("t1", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals(AlterActionType.ALTER_COLUMN, action.alterType) Assert.assertEquals("age", action.columName) Assert.assertEquals("BIGINT", action.dataType) } else { Assert.fail() } } @Test fun addColumnTest() { val sql = "ALTER TABLE `datacompute`.`users_quan` ADD COLUMN `age` VARCHAR(45) NOT NULL DEFAULT 18 COMMENT '年龄' AFTER `username`" val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("datacompute", statement.tableId.schemaName) Assert.assertEquals("users_quan", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals(AlterActionType.ADD_COLUMN, action.alterType) Assert.assertEquals("age", action.columName) Assert.assertFalse(action.nullable) Assert.assertEquals("18", action.defaultExpression) Assert.assertEquals("年龄", action.comment) } else { Assert.fail() } } @Test fun addColumnTest1() { val sql = """ ALTER TABLE `mxy`.`cyj` ADD COLUMN new_column1 VARCHAR(255) default null, ADD COLUMN new_column2 INT not null default 0, ADD COLUMN new_column3 TIMESTAMP DEFAULT CURRENT_TIMESTAMP; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("mxy", statement.tableId.schemaName) Assert.assertEquals("cyj", statement.tableId.tableName) Assert.assertEquals(3, statement.actions.size) } else { Assert.fail() } } @Test fun dropColumnTest() { val sql = "ALTER TABLE `datacompute`.`users_quan` DROP COLUMN `age`;" val statement = MySqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("datacompute", statement.tableId.schemaName) Assert.assertEquals("users_quan", statement.tableId.tableName) val action = statement.firstAction() as DropColumnAction Assert.assertEquals(AlterActionType.DROP_COLUMN, action.alterType) Assert.assertEquals("age", action.columNames.get(0)) } else { Assert.fail() } } @Test fun addUNIQUETest() { val sql = "ALTER TABLE `datacompute`.`dc_project_member`\n" + " ADD UNIQUE INDEX `uk_prj_user` (`project_code` ASC, `user_id` ASC);" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) } @Test fun addUNIQUETest1() { val sql = "ALTER TABLE amount_all ADD UNIQUE uk_type_time(etype, time)" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) } @Test fun addIndexTest() { val sql = "ALTER TABLE sj_resource_charges add index index_test (name);" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals("index_test", createIndex.indexName) } } @Test fun addIndexTest1() { val sql = "ALTER TABLE tablename ADD INDEX INDEX_NAME (school_id, settlement_time)" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) } @Test fun dropIndexTest1() { val sql = "ALTER TABLE table_name DROP INDEX index_name" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals("ALTER TABLE table_name DROP INDEX index_name", sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) } @Test fun useTest() { var sql = "use bigdata" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.USE, statement.statementType) if (statement is UseDatabase) { Assert.assertEquals("bigdata", statement.databaseName) } else { Assert.fail() } } @Test fun createIndexTest() { val sql = "CREATE INDEX test_index ON demo.orders (column_name)" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("demo", "orders"), statement.tableId) val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals("test_index", createIndex.indexName) } } @Test fun dropIndexTest() { val sql = "DROP INDEX test_index ON demo.orders" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("demo", "orders"), statement.tableId) val dropIndex = statement.firstAction() as DropIndex Assert.assertEquals(AlterActionType.DROP_INDEX, dropIndex.alterType) Assert.assertEquals("test_index", dropIndex.indexName) } } @Test fun truncatePartitionTest() { val sql = "ALTER TABLE demo.orders TRUNCATE PARTITION p1998\n" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(AlterActionType.TRUNCATE_PARTITION, statement.firstAction().alterType) Assert.assertEquals(TableId("demo", "orders"), statement.tableId) } } @Test fun dropPrimarykeyTest() { val sql = "alter table rd_orders drop primary key" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(AlterActionType.DROP_PRIMARY_KEY, statement.firstAction().alterType) Assert.assertEquals(TableId("rd_orders"), statement.tableId) } } @Test fun addPrimarykeyTest() { val sql = "alter table rd_orders add primary key (name)" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(AlterActionType.ADD_PRIMARY_KEY, statement.firstAction().alterType) Assert.assertEquals(TableId("rd_orders"), statement.tableId) } } } ================================================ FILE: superior-mysql-parser/src/test/kotlin/io/github/melin/superior/parser/mysql/MySqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.mysql import com.github.melin.superior.sql.parser.mysql.MySqlHelper import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.DeleteTable import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.dml.UpdateTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class MySqlParserDmlTest { @Test fun selectTest0() { val sql = "select * from users limit 5, 10" val statement = MySqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(5, statement.offset) Assert.assertEquals(10, statement.limit) } else { Assert.fail() } } @Test fun selectTest1() { val sql = "select * from users a left outer join address b on a.address_id = b.id limit 10 offset 100" val statement = MySqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(10, statement.limit) Assert.assertEquals(100, statement.offset) } else { Assert.fail() } } @Test fun deleteTest0() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest1() { val sql = """ DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("t1", statement.tableId.tableName) Assert.assertEquals(2, statement.outputTables.size) Assert.assertEquals(3, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest2() { val sql = """ DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("t1", statement.tableId.tableName) Assert.assertEquals(2, statement.outputTables.size) Assert.assertEquals(3, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest3() { val sql = """ DELETE FROM users """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("users", statement.tableId.tableName) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId?.tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest1() { val sql = """ UPDATE product p LEFT JOIN product_price pp ON p.productid= pp.productid SET p.isdelete = 1 WHERE pp.productid IS NULL; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("product", statement.tableId.tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest2() { val sql = """ update resource_screen_node b join ( select concat(region_name,'区域测点') name ,sum(access_station_num) as snum ,sum(access_point_num) as pnum from ads_dmap_datasource_indicator group by region_name ) as a on a.name=b.name set b.access_station=a.snum,b.access_point=pnum; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("resource_screen_node", statement.tableId.tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest3() { val sql = """ UPDATE items,month SET items.price=month.price WHERE items.id=month.id; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("items", statement.tableId.tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun insertValuesTest() { val sql = """ insert into bigdata."user" select * from users a left outer join address b on a.address_id = b.id """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("bigdata", statement.tableId?.schemaName) Assert.assertEquals("user", statement.tableId?.tableName) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun replaceValuesTest() { // val sql = "insert into user values('name')" val sql = "REPLACE into bigdata.user select * from users a left outer join address b on a.address_id = b.id" val statement = MySqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("bigdata", statement.tableId?.schemaName) Assert.assertEquals("user", statement.tableId?.tableName) Assert.assertTrue(statement.mysqlReplace) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun countCondTest() { val sql = "select count(type='mac' or null) From test_table where a=2 limit 50" val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) if (statement is QueryStmt) { Assert.assertEquals("test_table", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun cteTest0() { val sql = """ WITH CTE1 AS (SELECT A, B FROM TABLE1), CTE2 AS (SELECT C, D FROM TABLE2) SELECT B, D FROM CTE1 JOIN CTE2 WHERE CTE1.A = CTE2.C; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) if (statement is QueryStmt) { Assert.assertEquals("TABLE1", statement.inputTables.get(0).tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun cteTest1() { val sql = """ INSERT INTO DATES (DATE) SELECT DATE FROM ( WITH RECURSIVE DATE_RANGE AS ( SELECT DATE('2023-01-01') AS DATE UNION ALL SELECT DATE + INTERVAL 1 DAY FROM DATE_RANGE WHERE DATE < '2024-12-31' ), DATE_RANGE2 AS ( SELECT DATE('2025-01-01') AS DATE UNION ALL SELECT DATE + INTERVAL 1 DAY FROM DATE_RANGE2 WHERE DATE < '2025-12-31' ) SELECT DATE FROM DATE_RANGE UNION ALL SELECT DATE FROM DATE_RANGE2 ) AS DERIVED_TABLE ON DUPLICATE KEY UPDATE DATE = VALUES(DATE); """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.INSERT, statement.statementType) if (statement is InsertTable) { Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals(TableId("DATES"), statement.tableId) } else { Assert.fail() } } @Test fun cteTest2() { val sql = """ WITH cte1 AS (SELECT 1) SELECT * FROM (WITH cte2 AS (SELECT 2) SELECT * FROM cte2 JOIN cte1) AS dt; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) if (statement is QueryStmt) { Assert.assertEquals(0, statement.inputTables.size) } else { Assert.fail() } } @Test fun ctasTest0() { val sql = "create table demo1 as select * from demo" val statement = MySqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("demo1", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-mysql-parser/src/test/kotlin/io/github/melin/superior/parser/mysql/MySqlProcedureParserTest.kt ================================================ package io.github.melin.superior.parser.mysql import com.github.melin.superior.sql.parser.mysql.MySqlHelper import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.create.CreateProcedure import org.junit.Assert import org.junit.Test class MySqlProcedureParserTest { @Test fun procedureTest0() { val sql = """ CREATE PROCEDURE UpdateEmployeeSalary(IN employeeId INT, IN newSalary DECIMAL(10, 2)) BEGIN -- Update the salary of an employee with the given ID UPDATE employees SET salary = newSalary WHERE id = employeeId; select * from demos; END; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals("UpdateEmployeeSalary", statement.procedureId?.procedureName) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun procedureTest1() { val sql = """ create procedure my_procedure() begin declare my_id varchar(32); declare my_name varchar(50); DECLARE done INT DEFAULT FALSE; DECLARE My_Cursor CURSOR FOR ( SELECT id, name FROM t_people ); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN My_Cursor; myLoop: LOOP FETCH My_Cursor into my_id, my_name; IF done THEN LEAVE myLoop; END IF; UPDATE t_user SET c_name = my_name WHERE id = my_id and rtrim(ltrim(c_name)) = ''; COMMIT; END LOOP myLoop; CLOSE My_Cursor; END; """ .trimIndent() val statement = MySqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals("my_procedure", statement.procedureId?.procedureName) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } } ================================================ FILE: superior-mysql-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-oracle-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-oracle-parser superior-oracle-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-oracle-parser/src/main/antlr4/io/github/melin/superior/parser/oracle/antlr4/OracleLexer.g4 ================================================ /** * Oracle(c) PL/SQL 11g Parser * * Copyright (c) 2009-2011 Alexandre Porcelli * Copyright (c) 2015-2019 Ivan Kochurkin (KvanTTT, kvanttt@gmail.com, Positive Technologies). * Copyright (c) 2017 Mark Adams * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ lexer grammar OracleLexer; options { superClass=OracleLexerBase; } ABORT : 'ABORT'; ABS : 'ABS'; ABSENT : 'ABSENT'; ACCESS : 'ACCESS'; ACCESSED : 'ACCESSED'; ACCESSIBLE : 'ACCESSIBLE'; ACCOUNT : 'ACCOUNT'; ACL : 'ACL'; ACOS : 'ACOS'; ACROSS : 'ACROSS'; ACTION : 'ACTION'; ACTIONS : 'ACTIONS'; ACTIVATE : 'ACTIVATE'; ACTIVE : 'ACTIVE'; ACTIVE_COMPONENT : 'ACTIVE_COMPONENT'; ACTIVE_DATA : 'ACTIVE_DATA'; ACTIVE_FUNCTION : 'ACTIVE_FUNCTION'; ACTIVE_TAG : 'ACTIVE_TAG'; ACTIVITY : 'ACTIVITY'; ADAPTIVE_PLAN : 'ADAPTIVE_PLAN'; ADD : 'ADD'; ADD_COLUMN : 'ADD_COLUMN'; ADD_GROUP : 'ADD_GROUP'; ADD_MONTHS : 'ADD_MONTHS'; ADJ_DATE : 'ADJ_DATE'; ADMIN : 'ADMIN'; ADMINISTER : 'ADMINISTER'; ADMINISTRATOR : 'ADMINISTRATOR'; ADVANCED : 'ADVANCED'; ADVISE : 'ADVISE'; ADVISOR : 'ADVISOR'; AFD_DISKSTRING : 'AFD_DISKSTRING'; AFTER : 'AFTER'; AGENT : 'AGENT'; AGGREGATE : 'AGGREGATE'; A_LETTER : 'A'; ALIAS : 'ALIAS'; ALL : 'ALL'; ALLOCATE : 'ALLOCATE'; ALLOW : 'ALLOW'; ALL_ROWS : 'ALL_ROWS'; ALTER : 'ALTER'; ALTERNATE : 'ALTERNATE'; ALWAYS : 'ALWAYS'; ANALYTIC : 'ANALYTIC'; ANALYZE : 'ANALYZE'; ANCESTOR : 'ANCESTOR'; ANCILLARY : 'ANCILLARY'; AND : 'AND'; AND_EQUAL : 'AND_EQUAL'; ANNOTATIONS : 'ANNOTATIONS'; ANOMALY : 'ANOMALY'; ANSI_REARCH : 'ANSI_REARCH'; ANTIJOIN : 'ANTIJOIN'; ANY : 'ANY'; ANYSCHEMA : 'ANYSCHEMA'; APPEND : 'APPEND'; APPENDCHILDXML : 'APPENDCHILDXML'; APPEND_VALUES : 'APPEND_VALUES'; APPLICATION : 'APPLICATION'; APPLY : 'APPLY'; APPROX_COUNT_DISTINCT : 'APPROX_COUNT_DISTINCT'; ARCHIVAL : 'ARCHIVAL'; ARCHIVE : 'ARCHIVE'; ARCHIVED : 'ARCHIVED'; ARCHIVELOG : 'ARCHIVELOG'; ARE : 'ARE'; ARRAY : 'ARRAY'; AS : 'AS'; ASC : 'ASC'; ASCII : 'ASCII'; ASCIISTR : 'ASCIISTR'; ASIN : 'ASIN'; ASIS : 'ASIS'; ASSEMBLY : 'ASSEMBLY'; ASSIGN : 'ASSIGN'; ASSOCIATE : 'ASSOCIATE'; ASYNC : 'ASYNC'; ASYNCHRONOUS : 'ASYNCHRONOUS'; ATAN2 : 'ATAN2'; ATAN : 'ATAN'; AT : 'AT'; ATTRIBUTE : 'ATTRIBUTE'; ATTRIBUTES : 'ATTRIBUTES'; AUDIT : 'AUDIT'; AUTHENTICATED : 'AUTHENTICATED'; AUTHENTICATION : 'AUTHENTICATION'; AUTHID : 'AUTHID'; AUTHORIZATION : 'AUTHORIZATION'; AUTOALLOCATE : 'AUTOALLOCATE'; AUTO : 'AUTO'; AUTOBACKUP : 'AUTOBACKUP'; AUTOEXTEND : 'AUTOEXTEND'; AUTO_LOGIN : 'AUTO_LOGIN'; AUTOMATIC : 'AUTOMATIC'; AUTONOMOUS_TRANSACTION : 'AUTONOMOUS_TRANSACTION'; AUTO_REOPTIMIZE : 'AUTO_REOPTIMIZE'; AVAILABILITY : 'AVAILABILITY'; AVRO : 'AVRO'; BACKGROUND : 'BACKGROUND'; BACKINGFILE : 'BACKINGFILE'; BACKUP : 'BACKUP'; BACKUPS : 'BACKUPS'; BACKUPSET : 'BACKUPSET'; BADFILE : 'BADFILE'; BASIC : 'BASIC'; BASICFILE : 'BASICFILE'; BATCH : 'BATCH'; BATCHSIZE : 'BATCHSIZE'; BATCH_TABLE_ACCESS_BY_ROWID : 'BATCH_TABLE_ACCESS_BY_ROWID'; BECOME : 'BECOME'; BEFORE : 'BEFORE'; BEGIN : 'BEGIN'; BEGINNING : 'BEGINNING'; BEGIN_OUTLINE_DATA : 'BEGIN_OUTLINE_DATA'; BEHALF : 'BEHALF'; BEQUEATH : 'BEQUEATH'; BETWEEN : 'BETWEEN'; BFILE : 'BFILE'; BFILENAME : 'BFILENAME'; BIG : 'BIG'; BIGFILE : 'BIGFILE'; BIGINT : 'BIGINT'; BINARY : 'BINARY'; BINARY_DOUBLE : 'BINARY_DOUBLE'; BINARY_DOUBLE_INFINITY : 'BINARY_DOUBLE_INFINITY'; BINARY_DOUBLE_NAN : 'BINARY_DOUBLE_NAN'; BINARY_FLOAT : 'BINARY_FLOAT'; BINARY_FLOAT_INFINITY : 'BINARY_FLOAT_INFINITY'; BINARY_FLOAT_NAN : 'BINARY_FLOAT_NAN'; BINARY_INTEGER : 'BINARY_INTEGER'; BIND_AWARE : 'BIND_AWARE'; BINDING : 'BINDING'; BIN_TO_NUM : 'BIN_TO_NUM'; BITAND : 'BITAND'; BITMAP_AND : 'BITMAP_AND'; BITMAP : 'BITMAP'; BITMAPS : 'BITMAPS'; BITMAP_TREE : 'BITMAP_TREE'; BITS : 'BITS'; BLANKS : 'BLANKS'; BLOB : 'BLOB'; BLOCK : 'BLOCK'; BLOCK_RANGE : 'BLOCK_RANGE'; BLOCKS : 'BLOCKS'; BLOCKSIZE : 'BLOCKSIZE'; BODY : 'BODY'; BOOLEAN : 'BOOLEAN'; BOTH : 'BOTH'; BOUND : 'BOUND'; BRANCH : 'BRANCH'; BREADTH : 'BREADTH'; BROADCAST : 'BROADCAST'; BSON : 'BSON'; BUFFER : 'BUFFER'; BUFFER_CACHE : 'BUFFER_CACHE'; BUFFER_POOL : 'BUFFER_POOL'; BUILD : 'BUILD'; BULK : 'BULK'; BY : 'BY'; BYPASS_RECURSIVE_CHECK : 'BYPASS_RECURSIVE_CHECK'; BYPASS_UJVC : 'BYPASS_UJVC'; BYTE : 'BYTE'; BYTES : 'BYTES'; BYTEORDERMARK : 'BYTEORDERMARK'; CACHE : 'CACHE'; CACHE_CB : 'CACHE_CB'; CACHE_INSTANCES : 'CACHE_INSTANCES'; CACHE_TEMP_TABLE : 'CACHE_TEMP_TABLE'; CACHING : 'CACHING'; CALCULATED : 'CALCULATED'; CALLBACK : 'CALLBACK'; CALL : 'CALL'; CANCEL : 'CANCEL'; CANONICAL : 'CANONICAL'; CAPACITY : 'CAPACITY'; CAPTION : 'CAPTION'; CARDINALITY : 'CARDINALITY'; CASCADE : 'CASCADE'; CASE : 'CASE'; CAST : 'CAST'; CASESENSITIVE : 'CASE-SENSITIVE'; CATEGORY : 'CATEGORY'; CDBDEFAULT : 'CDB$DEFAULT'; CEIL : 'CEIL'; CELL_FLASH_CACHE : 'CELL_FLASH_CACHE'; CERTIFICATE : 'CERTIFICATE'; CFILE : 'CFILE'; CHAINED : 'CHAINED'; CHANGE : 'CHANGE'; CHANGETRACKING : 'CHANGETRACKING'; CHANGE_DUPKEY_ERROR_INDEX : 'CHANGE_DUPKEY_ERROR_INDEX'; CHARACTER : 'CHARACTER'; CHARACTERS : 'CHARACTERS'; CHARACTERSET : 'CHARACTERSET'; CHAR : 'CHAR'; CHAR_CS : 'CHAR_CS'; CHARTOROWID : 'CHARTOROWID'; CHECK_ACL_REWRITE : 'CHECK_ACL_REWRITE'; CHECK : 'CHECK'; CHECKPOINT : 'CHECKPOINT'; CHILD : 'CHILD'; CHOOSE : 'CHOOSE'; CHR : 'CHR'; CHUNK : 'CHUNK'; CLASS : 'CLASS'; CLASSIFICATION : 'CLASSIFICATION'; CLASSIFIER : 'CLASSIFIER'; CLAUSE : 'CLAUSE'; CLEAN : 'CLEAN'; CLEANUP : 'CLEANUP'; CLEAR : 'CLEAR'; C_LETTER : 'C'; CLIENT : 'CLIENT'; CLOB : 'CLOB'; CLONE : 'CLONE'; CLOSE_CACHED_OPEN_CURSORS : 'CLOSE_CACHED_OPEN_CURSORS'; CLOSE : 'CLOSE'; CLUSTER_BY_ROWID : 'CLUSTER_BY_ROWID'; CLUSTER : 'CLUSTER'; CLUSTER_DETAILS : 'CLUSTER_DETAILS'; CLUSTER_DISTANCE : 'CLUSTER_DISTANCE'; CLUSTER_ID : 'CLUSTER_ID'; CLUSTERING : 'CLUSTERING'; CLUSTERING_FACTOR : 'CLUSTERING_FACTOR'; CLUSTER_PROBABILITY : 'CLUSTER_PROBABILITY'; CLUSTER_SET : 'CLUSTER_SET'; COALESCE : 'COALESCE'; COALESCE_SQ : 'COALESCE_SQ'; COARSE : 'COARSE'; CO_AUTH_IND : 'CO_AUTH_IND'; COLD : 'COLD'; COLLECT : 'COLLECT'; COLLECTION : 'COLLECTION'; COLUMNAR : 'COLUMNAR'; COLUMN_AUTH_INDICATOR : 'COLUMN_AUTH_INDICATOR'; COLUMN : 'COLUMN'; COLUMNS : 'COLUMNS'; COLUMN_STATS : 'COLUMN_STATS'; COLUMN_VALUE : 'COLUMN_VALUE'; COMMENT : 'COMMENT'; COMMIT : 'COMMIT'; COMMITTED : 'COMMITTED'; COMMON : 'COMMON'; COMMON_DATA : 'COMMON_DATA'; COMPACT : 'COMPACT'; COMPATIBLE : 'COMPATIBLE'; COMPATIBILITY : 'COMPATIBILITY'; COMPILE : 'COMPILE'; COMPLETE : 'COMPLETE'; COMPLIANCE : 'COMPLIANCE'; COMPONENT : 'COMPONENT'; COMPONENTS : 'COMPONENTS'; COMPOSE : 'COMPOSE'; COMPOSITE : 'COMPOSITE'; COMPOSITE_LIMIT : 'COMPOSITE_LIMIT'; COMPOUND : 'COMPOUND'; COMPRESS : 'COMPRESS'; COMPRESSION : 'COMPRESSION'; COMPUTE : 'COMPUTE'; CONCAT : 'CONCAT'; CON_DBID_TO_ID : 'CON_DBID_TO_ID'; CONDITIONAL : 'CONDITIONAL'; CONDITION : 'CONDITION'; CONFIRM : 'CONFIRM'; CONFORMING : 'CONFORMING'; CON_GUID_TO_ID : 'CON_GUID_TO_ID'; CON_ID : 'CON_ID'; CON_NAME_TO_ID : 'CON_NAME_TO_ID'; CONNECT_BY_CB_WHR_ONLY : 'CONNECT_BY_CB_WHR_ONLY'; CONNECT_BY_COMBINE_SW : 'CONNECT_BY_COMBINE_SW'; CONNECT_BY_COST_BASED : 'CONNECT_BY_COST_BASED'; CONNECT_BY_ELIM_DUPS : 'CONNECT_BY_ELIM_DUPS'; CONNECT_BY_FILTERING : 'CONNECT_BY_FILTERING'; CONNECT_BY_ISCYCLE : 'CONNECT_BY_ISCYCLE'; CONNECT_BY_ISLEAF : 'CONNECT_BY_ISLEAF'; CONNECT_BY_ROOT : 'CONNECT_BY_ROOT'; CONNECT : 'CONNECT'; CONNECT_TIME : 'CONNECT_TIME'; CONSIDER : 'CONSIDER'; CONSISTENT : 'CONSISTENT'; CONSTANT : 'CONSTANT'; CONST : 'CONST'; CONSTRAINT : 'CONSTRAINT'; CONSTRAINTS : 'CONSTRAINTS'; CONSTRUCTOR : 'CONSTRUCTOR'; CONTAINER : 'CONTAINER'; CONTAINERS : 'CONTAINERS'; CONTAINERS_DEFAULT : 'CONTAINERS_DEFAULT'; CONTAINER_DATA : 'CONTAINER_DATA'; CONTAINER_MAP : 'CONTAINER_MAP'; CONTENT : 'CONTENT'; CONTENTS : 'CONTENTS'; CONTEXT : 'CONTEXT'; CONTINUE : 'CONTINUE'; CONTROLFILE : 'CONTROLFILE'; CON_UID_TO_ID : 'CON_UID_TO_ID'; CONVERT : 'CONVERT'; CONVERSION : 'CONVERSION'; COOKIE : 'COOKIE'; COPY : 'COPY'; CORR_K : 'CORR_K'; CORR_S : 'CORR_S'; CORRUPTION : 'CORRUPTION'; CORRUPT_XID_ALL : 'CORRUPT_XID_ALL'; CORRUPT_XID : 'CORRUPT_XID'; COS : 'COS'; COSH : 'COSH'; COST : 'COST'; COST_XML_QUERY_REWRITE : 'COST_XML_QUERY_REWRITE'; COUNT : 'COUNT'; COUNTED : 'COUNTED'; COVAR_POP : 'COVAR_POP'; COVAR_SAMP : 'COVAR_SAMP'; CPU_COSTING : 'CPU_COSTING'; CPU_PER_CALL : 'CPU_PER_CALL'; CPU_PER_SESSION : 'CPU_PER_SESSION'; CRASH : 'CRASH'; CREATE : 'CREATE'; CREATE_FILE_DEST : 'CREATE_FILE_DEST'; CREATE_STORED_OUTLINES : 'CREATE_STORED_OUTLINES'; CREATION : 'CREATION'; CREDENTIAL : 'CREDENTIAL'; CRITICAL : 'CRITICAL'; CROSS : 'CROSS'; CROSSEDITION : 'CROSSEDITION'; CSCONVERT : 'CSCONVERT'; CSV : 'CSV'; CUBE_AJ : 'CUBE_AJ'; CUBE : 'CUBE'; CUBE_GB : 'CUBE_GB'; CUBE_SJ : 'CUBE_SJ'; CUME_DISTM : 'CUME_DISTM'; CURRENT : 'CURRENT'; CURRENT_DATE : 'CURRENT_DATE'; CURRENT_SCHEMA : 'CURRENT_SCHEMA'; CURRENT_TIME : 'CURRENT_TIME'; CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP'; CURRENT_USER : 'CURRENT_USER'; CURRENTV : 'CURRENTV'; CURSOR : 'CURSOR'; CURSOR_SHARING_EXACT : 'CURSOR_SHARING_EXACT'; CURSOR_SPECIFIC_SEGMENT : 'CURSOR_SPECIFIC_SEGMENT'; CUSTOMDATUM : 'CUSTOMDATUM'; CV : 'CV'; CYCLE : 'CYCLE'; DANGLING : 'DANGLING'; DATABASE : 'DATABASE'; DATA : 'DATA'; DATAFILE : 'DATAFILE'; DATAFILES : 'DATAFILES'; DATAGUARDCONFIG : 'DATAGUARDCONFIG'; DATAMOVEMENT : 'DATAMOVEMENT'; DATAOBJNO : 'DATAOBJNO'; DATAOBJ_TO_MAT_PARTITION : 'DATAOBJ_TO_MAT_PARTITION'; DATAOBJ_TO_PARTITION : 'DATAOBJ_TO_PARTITION'; DATAPUMP : 'DATAPUMP'; DATA_SECURITY_REWRITE_LIMIT : 'DATA_SECURITY_REWRITE_LIMIT'; DATE : 'DATE'; DATE_CACHE : 'DATE_CACHE'; DATE_FORMAT : 'DATE_FORMAT'; DATE_MODE : 'DATE_MODE'; DAY : 'DAY'; DAYS : 'DAYS'; DAY_TO_SECOND : 'DAY_TO_SECOND'; DBA : 'DBA'; DBA_RECYCLEBIN : 'DBA_RECYCLEBIN'; DBLINK : 'DBLINK'; DBMS_STATS : 'DBMS_STATS'; DB_ROLE_CHANGE : 'DB_ROLE_CHANGE'; DBTIMEZONE : 'DBTIMEZONE'; DB_UNIQUE_NAME : 'DB_UNIQUE_NAME'; DB_VERSION : 'DB_VERSION'; DDL : 'DDL'; DEALLOCATE : 'DEALLOCATE'; DEBUG : 'DEBUG'; DEBUGGER : 'DEBUGGER'; DEC : 'DEC'; DECIMAL : 'DECIMAL'; DECLARE : 'DECLARE'; DECOMPOSE : 'DECOMPOSE'; DECORRELATE : 'DECORRELATE'; DECR : 'DECR'; DECREMENT : 'DECREMENT'; DECRYPT : 'DECRYPT'; DEDUPLICATE : 'DEDUPLICATE'; DEFAULT : 'DEFAULT'; DEFAULTIF : 'DEFAULTIF'; DEFAULTS : 'DEFAULTS'; DEFAULT_COLLATION : 'DEFAULT_COLLATION'; DEFAULT_CREDENTIAL : 'DEFAULT_CREDENTIAL'; DEFERRABLE : 'DEFERRABLE'; DEFERRED : 'DEFERRED'; DEFINED : 'DEFINED'; DEFINE : 'DEFINE'; DEFINER : 'DEFINER'; DEGREE : 'DEGREE'; DELAY : 'DELAY'; DELEGATE : 'DELEGATE'; DELETE_ALL : 'DELETE_ALL'; DELETE : 'DELETE'; DELETEXML : 'DELETEXML'; DELIMITED : 'DELIMITED'; DEMAND : 'DEMAND'; DENSE_RANKM : 'DENSE_RANKM'; DEPENDENT : 'DEPENDENT'; DEPRECATE : 'DEPRECATE'; DEPTH : 'DEPTH'; DEQUEUE : 'DEQUEUE'; DEREF : 'DEREF'; DEREF_NO_REWRITE : 'DEREF_NO_REWRITE'; DESC : 'DESC'; DESCRIPTION : 'DESCRIPTION'; DESTROY : 'DESTROY'; DETACHED : 'DETACHED'; DETECTED : 'DETECTED'; DETERMINES : 'DETERMINES'; DETERMINISTIC : 'DETERMINISTIC'; DICTIONARY : 'DICTIONARY'; DIMENSION : 'DIMENSION'; DIMENSIONS : 'DIMENSIONS'; DIRECTIO : 'DIRECTIO'; DIRECT_LOAD : 'DIRECT_LOAD'; DIRECTORY : 'DIRECTORY'; DIRECT_PATH : 'DIRECT_PATH'; DISABLE_ALL : 'DISABLE_ALL'; DISABLE : 'DISABLE'; DISABLED : 'DISABLED'; DISABLE_DIRECTORY_LINK_CHECK : 'DISABLE_DIRECTORY_LINK_CHECK'; DISABLE_PARALLEL_DML : 'DISABLE_PARALLEL_DML'; DISABLE_PRESET : 'DISABLE_PRESET'; DISABLE_RPKE : 'DISABLE_RPKE'; DISALLOW : 'DISALLOW'; DISASSOCIATE : 'DISASSOCIATE'; DISCARD : 'DISCARD'; DISCARDFILE : 'DISCARDFILE'; DISCONNECT : 'DISCONNECT'; DISK : 'DISK'; DISKGROUP : 'DISKGROUP'; DISKGROUP_PLUS : '\'+ DISKGROUP'; DISKS : 'DISKS'; DISMOUNT : 'DISMOUNT'; DISTINCT : 'DISTINCT'; DISTINGUISHED : 'DISTINGUISHED'; DISTRIBUTED : 'DISTRIBUTED'; DISTRIBUTE : 'DISTRIBUTE'; DML : 'DML'; DML_UPDATE : 'DML_UPDATE'; DNFS_DISABLE : 'DNFS_DISABLE'; DNFS_ENABLE : 'DNFS_ENABLE'; DNFS_READBUFFERS : 'DNFS_READBUFFERS'; DOCFIDELITY : 'DOCFIDELITY'; DOCUMENT : 'DOCUMENT'; DOLLAR_ELSE : '$ELSE'; DOLLAR_ELSIF : '$ELSIF'; DOLLAR_END : '$END'; DOLLAR_ERROR : '$ERROR'; DOLLAR_IF : '$IF'; DOLLAR_THEN : '$THEN'; DOMAIN_INDEX_FILTER : 'DOMAIN_INDEX_FILTER'; DOMAIN_INDEX_NO_SORT : 'DOMAIN_INDEX_NO_SORT'; DOMAIN_INDEX_SORT : 'DOMAIN_INDEX_SORT'; DOUBLE : 'DOUBLE'; DOWNGRADE : 'DOWNGRADE'; DRIVING_SITE : 'DRIVING_SITE'; DROP_COLUMN : 'DROP_COLUMN'; DROP : 'DROP'; DROP_GROUP : 'DROP_GROUP'; DSINTERVAL_UNCONSTRAINED : 'DSINTERVAL_UNCONSTRAINED'; DST_UPGRADE_INSERT_CONV : 'DST_UPGRADE_INSERT_CONV'; DUMP : 'DUMP'; DUMPSET : 'DUMPSET'; DUPLICATE : 'DUPLICATE'; DV : 'DV'; DYNAMIC : 'DYNAMIC'; DYNAMIC_SAMPLING : 'DYNAMIC_SAMPLING'; DYNAMIC_SAMPLING_EST_CDN : 'DYNAMIC_SAMPLING_EST_CDN'; E_LETTER : 'E'; EACH : 'EACH'; EDITIONABLE : 'EDITIONABLE'; EDITION : 'EDITION'; EDITIONING : 'EDITIONING'; EDITIONS : 'EDITIONS'; ELEMENT : 'ELEMENT'; ELIM_GROUPBY : 'ELIM_GROUPBY'; ELIMINATE_JOIN : 'ELIMINATE_JOIN'; ELIMINATE_OBY : 'ELIMINATE_OBY'; ELIMINATE_OUTER_JOIN : 'ELIMINATE_OUTER_JOIN'; ELSE : 'ELSE'; ELSIF : 'ELSIF'; EM : 'EM'; EMBEDDED : 'EMBEDDED'; EMPTY_BLOB : 'EMPTY_BLOB'; EMPTY_CLOB : 'EMPTY_CLOB'; EMPTY_ : 'EMPTY'; ENABLE_ALL : 'ENABLE_ALL'; ENABLE : 'ENABLE'; ENABLED : 'ENABLED'; ENABLE_PARALLEL_DML : 'ENABLE_PARALLEL_DML'; ENABLE_PRESET : 'ENABLE_PRESET'; ENCLOSED : 'ENCLOSED'; ENCODING : 'ENCODING'; ENCRYPT : 'ENCRYPT'; ENCRYPTION : 'ENCRYPTION'; ENCRYPTPASSWORDISNULL : 'ENCRYPTPASSWORDISNULL'; END : 'END'; END_OUTLINE_DATA : 'END_OUTLINE_DATA'; ENDIAN : 'ENDIAN'; ENFORCED : 'ENFORCED'; ENFORCE : 'ENFORCE'; ENQUEUE : 'ENQUEUE'; ENTERPRISE : 'ENTERPRISE'; ENTITYESCAPING : 'ENTITYESCAPING'; ENTRY : 'ENTRY'; EQUIPART : 'EQUIPART'; ERR : 'ERR'; ERROR_ARGUMENT : 'ERROR_ARGUMENT'; ERROR : 'ERROR'; ERROR_ON_OVERLAP_TIME : 'ERROR_ON_OVERLAP_TIME'; ERRORS : 'ERRORS'; ERROR_INDEX : 'ERROR_INDEX'; ERROR_CODE : 'ERROR_CODE'; ESCAPE : 'ESCAPE'; ESCAPED : 'ESCAPED'; ESTIMATE : 'ESTIMATE'; EVAL : 'EVAL'; EVALNAME : 'EVALNAME'; EVALUATE : 'EVALUATE'; EVALUATION : 'EVALUATION'; EVENTS : 'EVENTS'; EVERY : 'EVERY'; EXCEPT : 'EXCEPT'; EXCEPTION : 'EXCEPTION'; EXCEPTION_INIT : 'EXCEPTION_INIT'; EXCEPTIONS : 'EXCEPTIONS'; EXCHANGE : 'EXCHANGE'; EXCLUDE : 'EXCLUDE'; EXCLUDING : 'EXCLUDING'; EXCLUSIVE : 'EXCLUSIVE'; EXECUTE : 'EXECUTE'; EXEMPT : 'EXEMPT'; EXISTING : 'EXISTING'; EXISTS : 'EXISTS'; EXISTSNODE : 'EXISTSNODE'; EXIT : 'EXIT'; EXPAND_GSET_TO_UNION : 'EXPAND_GSET_TO_UNION'; EXPAND_TABLE : 'EXPAND_TABLE'; EXP : 'EXP'; EXPIRE : 'EXPIRE'; EXPLAIN : 'EXPLAIN'; EXPLOSION : 'EXPLOSION'; EXPORT : 'EXPORT'; EXPR_CORR_CHECK : 'EXPR_CORR_CHECK'; EXPRESS : 'EXPRESS'; EXTENDS : 'EXTENDS'; EXTENT : 'EXTENT'; EXTENTS : 'EXTENTS'; EXTERNAL : 'EXTERNAL'; EXTERNALLY : 'EXTERNALLY'; EXTRACTCLOBXML : 'EXTRACTCLOBXML'; EXTRACT : 'EXTRACT'; EXTRACTVALUE : 'EXTRACTVALUE'; EXTRA : 'EXTRA'; FACILITY : 'FACILITY'; FACT : 'FACT'; FACTOR : 'FACTOR'; FACTORIZE_JOIN : 'FACTORIZE_JOIN'; FAILED : 'FAILED'; FAILED_LOGIN_ATTEMPTS : 'FAILED_LOGIN_ATTEMPTS'; FAILGROUP : 'FAILGROUP'; FAILOVER : 'FAILOVER'; FAILURE : 'FAILURE'; FALSE : 'FALSE'; FAMILY : 'FAMILY'; FAR : 'FAR'; FAST : 'FAST'; FASTSTART : 'FASTSTART'; FBTSCAN : 'FBTSCAN'; FEATURE : 'FEATURE'; FEATURE_DETAILS : 'FEATURE_DETAILS'; FEATURE_ID : 'FEATURE_ID'; FEATURE_SET : 'FEATURE_SET'; FEATURE_VALUE : 'FEATURE_VALUE'; FETCH : 'FETCH'; FIELD : 'FIELD'; FIELDS : 'FIELDS'; FILE : 'FILE'; FILE_NAME_CONVERT : 'FILE_NAME_CONVERT'; FILEGROUP : 'FILEGROUP'; FILESTORE : 'FILESTORE'; FILESYSTEM_LIKE_LOGGING : 'FILESYSTEM_LIKE_LOGGING'; FILTER : 'FILTER'; FINAL : 'FINAL'; FINE : 'FINE'; FINISH : 'FINISH'; FIRST : 'FIRST'; FIRSTM : 'FIRSTM'; FIRST_ROWS : 'FIRST_ROWS'; FIRST_VALUE : 'FIRST_VALUE'; FIXED : 'FIXED'; FIXED_VIEW_DATA : 'FIXED_VIEW_DATA'; FLAGGER : 'FLAGGER'; FLASHBACK : 'FLASHBACK'; FLASH_CACHE : 'FLASH_CACHE'; FLOAT : 'FLOAT'; FLOB : 'FLOB'; FLEX : 'FLEX'; FLOOR : 'FLOOR'; FLUSH : 'FLUSH'; FOLDER : 'FOLDER'; FOLLOWING : 'FOLLOWING'; FOLLOWS : 'FOLLOWS'; FORALL : 'FORALL'; FORCE : 'FORCE'; FORCE_XML_QUERY_REWRITE : 'FORCE_XML_QUERY_REWRITE'; FOREIGN : 'FOREIGN'; FOREVER : 'FOREVER'; FOR : 'FOR'; FORMAT : 'FORMAT'; FORWARD : 'FORWARD'; FRAGMENT_NUMBER : 'FRAGMENT_NUMBER'; FREELIST : 'FREELIST'; FREELISTS : 'FREELISTS'; FREEPOOLS : 'FREEPOOLS'; FRESH : 'FRESH'; FROM : 'FROM'; FROM_TZ : 'FROM_TZ'; FULL : 'FULL'; FULL_OUTER_JOIN_TO_OUTER : 'FULL_OUTER_JOIN_TO_OUTER'; FUNCTION : 'FUNCTION'; FUNCTIONS : 'FUNCTIONS'; FTP : 'FTP'; G_LETTER : 'G'; GATHER_OPTIMIZER_STATISTICS : 'GATHER_OPTIMIZER_STATISTICS'; GATHER_PLAN_STATISTICS : 'GATHER_PLAN_STATISTICS'; GBY_CONC_ROLLUP : 'GBY_CONC_ROLLUP'; GBY_PUSHDOWN : 'GBY_PUSHDOWN'; GENERATED : 'GENERATED'; GET : 'GET'; GLOBAL : 'GLOBAL'; GLOBALLY : 'GLOBALLY'; GLOBAL_NAME : 'GLOBAL_NAME'; GLOBAL_TOPIC_ENABLED : 'GLOBAL_TOPIC_ENABLED'; GOTO : 'GOTO'; GRANT : 'GRANT'; GROUP_BY : 'GROUP_BY'; GROUP : 'GROUP'; GROUP_ID : 'GROUP_ID'; GROUPING : 'GROUPING'; GROUPING_ID : 'GROUPING_ID'; GROUPS : 'GROUPS'; GUARANTEED : 'GUARANTEED'; GUARANTEE : 'GUARANTEE'; GUARD : 'GUARD'; HADOOP_TRAILERS : 'HADOOP_TRAILERS'; HALF_YEARS : 'HALF_YEARS'; HASH_AJ : 'HASH_AJ'; HASH : 'HASH'; HASHKEYS : 'HASHKEYS'; HASH_SJ : 'HASH_SJ'; HAVING : 'HAVING'; HEADER : 'HEADER'; HEAP : 'HEAP'; HELP : 'HELP'; HEXTORAW : 'HEXTORAW'; HEXTOREF : 'HEXTOREF'; HIDDEN_KEYWORD : 'HIDDEN'; HIDE : 'HIDE'; HIER_ORDER : 'HIER_ORDER'; HIERARCHICAL : 'HIERARCHICAL'; HIERARCHIES : 'HIERARCHIES'; HIERARCHY : 'HIERARCHY'; HIGH : 'HIGH'; HINTSET_BEGIN : 'HINTSET_BEGIN'; HINTSET_END : 'HINTSET_END'; HOT : 'HOT'; HOUR : 'HOUR'; HOURS : 'HOURS'; HTTP : 'HTTP'; HWM_BROKERED : 'HWM_BROKERED'; HYBRID : 'HYBRID'; H_LETTER : 'H'; IDENTIFIED : 'IDENTIFIED'; IDENTIFIER : 'IDENTIFIER'; IDENTITY : 'IDENTITY'; IDGENERATORS : 'IDGENERATORS'; ID : 'ID'; IDLE_TIME : 'IDLE_TIME'; IF : 'IF'; IGNORE : 'IGNORE'; IGNORE_CHARS_AFTER_EOR : 'IGNORE_CHARS_AFTER_EOR'; IGNORE_OPTIM_EMBEDDED_HINTS : 'IGNORE_OPTIM_EMBEDDED_HINTS'; IGNORE_ROW_ON_DUPKEY_INDEX : 'IGNORE_ROW_ON_DUPKEY_INDEX'; IGNORE_WHERE_CLAUSE : 'IGNORE_WHERE_CLAUSE'; ILM : 'ILM'; IMMEDIATE : 'IMMEDIATE'; IMPACT : 'IMPACT'; IMPORT : 'IMPORT'; INACTIVE : 'INACTIVE'; INACTIVE_ACCOUNT_TIME : 'INACTIVE_ACCOUNT_TIME'; INCLUDE : 'INCLUDE'; INCLUDE_VERSION : 'INCLUDE_VERSION'; INCLUDING : 'INCLUDING'; INCREMENTAL : 'INCREMENTAL'; INCREMENT : 'INCREMENT'; INCR : 'INCR'; INDENT : 'INDENT'; INDEX_ASC : 'INDEX_ASC'; INDEX_COMBINE : 'INDEX_COMBINE'; INDEX_DESC : 'INDEX_DESC'; INDEXED : 'INDEXED'; INDEXES : 'INDEXES'; INDEX_FFS : 'INDEX_FFS'; INDEX_FILTER : 'INDEX_FILTER'; INDEX : 'INDEX'; INDEXING : 'INDEXING'; INDEX_JOIN : 'INDEX_JOIN'; INDEX_ROWS : 'INDEX_ROWS'; INDEX_RRS : 'INDEX_RRS'; INDEX_RS_ASC : 'INDEX_RS_ASC'; INDEX_RS_DESC : 'INDEX_RS_DESC'; INDEX_RS : 'INDEX_RS'; INDEX_SCAN : 'INDEX_SCAN'; INDEX_SKIP_SCAN : 'INDEX_SKIP_SCAN'; INDEX_SS_ASC : 'INDEX_SS_ASC'; INDEX_SS_DESC : 'INDEX_SS_DESC'; INDEX_SS : 'INDEX_SS'; INDEX_STATS : 'INDEX_STATS'; INDEXTYPE : 'INDEXTYPE'; INDEXTYPES : 'INDEXTYPES'; INDICATOR : 'INDICATOR'; INDICES : 'INDICES'; INFINITE : 'INFINITE'; INFORMATIONAL : 'INFORMATIONAL'; INHERIT : 'INHERIT'; IN : 'IN'; INITCAP : 'INITCAP'; INITIAL : 'INITIAL'; INITIALIZED : 'INITIALIZED'; INITIALLY : 'INITIALLY'; INITRANS : 'INITRANS'; INLINE : 'INLINE'; INLINE_XMLTYPE_NT : 'INLINE_XMLTYPE_NT'; INMEMORY : 'INMEMORY'; IN_MEMORY_METADATA : 'IN_MEMORY_METADATA'; INMEMORY_PRUNING : 'INMEMORY_PRUNING'; INNER : 'INNER'; INOUT : 'INOUT'; INPLACE : 'INPLACE'; INPUTFORMAT : 'INPUTFORMAT'; INSERTCHILDXMLAFTER : 'INSERTCHILDXMLAFTER'; INSERTCHILDXMLBEFORE : 'INSERTCHILDXMLBEFORE'; INSERTCHILDXML : 'INSERTCHILDXML'; INSERT : 'INSERT'; INSERTXMLAFTER : 'INSERTXMLAFTER'; INSERTXMLBEFORE : 'INSERTXMLBEFORE'; INSTANCE : 'INSTANCE'; INSTANCES : 'INSTANCES'; INSTANTIABLE : 'INSTANTIABLE'; INSTANTLY : 'INSTANTLY'; INSTEAD : 'INSTEAD'; INSTR2 : 'INSTR2'; INSTR4 : 'INSTR4'; INSTRB : 'INSTRB'; INSTRC : 'INSTRC'; INSTR : 'INSTR'; INTEGER : 'INTEGER'; INTERLEAVED : 'INTERLEAVED'; INTERMEDIATE : 'INTERMEDIATE'; INTERNAL_CONVERT : 'INTERNAL_CONVERT'; INTERNAL_USE : 'INTERNAL_USE'; INTERPRETED : 'INTERPRETED'; INTERSECT : 'INTERSECT'; INTERVAL : 'INTERVAL'; INT : 'INT'; INTERNAL : 'INTERNAL'; INTO : 'INTO'; INVALIDATE : 'INVALIDATE'; INVALIDATION : 'INVALIDATION'; INVISIBLE : 'INVISIBLE'; IN_XQUERY : 'IN_XQUERY'; IO_OPTIONS : 'IO_OPTIONS'; IS : 'IS'; IS_LEAF : 'IS_LEAF'; ISOLATION : 'ISOLATION'; ISOLATION_LEVEL : 'ISOLATION_LEVEL'; ITEMS : 'ITEMS'; ITERATE : 'ITERATE'; ITERATION_NUMBER : 'ITERATION_NUMBER'; JAVA : 'JAVA'; JOB : 'JOB'; JOIN : 'JOIN'; JSON_ARRAYAGG : 'JSON_ARRAYAGG'; JSON_ARRAY : 'JSON_ARRAY'; JSON_EQUAL : 'JSON_EQUAL'; JSON_EXISTS2 : 'JSON_EXISTS2'; JSON_EXISTS : 'JSON_EXISTS'; JSONGET : 'JSONGET'; JSON : 'JSON'; JSON_OBJECTAGG : 'JSON_OBJECTAGG'; JSON_OBJECT : 'JSON_OBJECT'; JSONPARSE : 'JSONPARSE'; JSON_QUERY : 'JSON_QUERY'; JSON_SERIALIZE : 'JSON_SERIALIZE'; JSON_TABLE : 'JSON_TABLE'; JSON_TEXTCONTAINS2 : 'JSON_TEXTCONTAINS2'; JSON_TEXTCONTAINS : 'JSON_TEXTCONTAINS'; JSON_TRANSFORM : 'JSON_TRANSFORM'; JSON_VALUE : 'JSON_VALUE'; K_LETTER : 'K'; KEEP_DUPLICATES : 'KEEP_DUPLICATES'; KEEP : 'KEEP'; KERBEROS : 'KERBEROS'; KEY : 'KEY'; KEY_LENGTH : 'KEY_LENGTH'; KEYSIZE : 'KEYSIZE'; KEYS : 'KEYS'; KEYSTORE : 'KEYSTORE'; KILL : 'KILL'; LABEL : 'LABEL'; LANGUAGE : 'LANGUAGE'; LAST_DAY : 'LAST_DAY'; LAST : 'LAST'; LAST_VALUE : 'LAST_VALUE'; LATERAL : 'LATERAL'; LATEST : 'LATEST'; LAX : 'LAX'; LAYER : 'LAYER'; LDAP_REGISTRATION_ENABLED : 'LDAP_REGISTRATION_ENABLED'; LDAP_REGISTRATION : 'LDAP_REGISTRATION'; LDAP_REG_SYNC_INTERVAL : 'LDAP_REG_SYNC_INTERVAL'; LDRTRIM : 'LDRTRIM'; LEAF : 'LEAF'; LEAD_CDB : 'LEAD_CDB'; LEAD_CDB_URI : 'LEAD_CDB_URI'; LEADING : 'LEADING'; LEFT : 'LEFT'; LENGTH2 : 'LENGTH2'; LENGTH4 : 'LENGTH4'; LENGTHB : 'LENGTHB'; LENGTHC : 'LENGTHC'; LENGTH : 'LENGTH'; LESS : 'LESS'; LEVEL : 'LEVEL'; LEVEL_NAME : 'LEVEL_NAME'; LEVELS : 'LEVELS'; LIBRARY : 'LIBRARY'; LIFECYCLE : 'LIFECYCLE'; LIFE : 'LIFE'; LIFETIME : 'LIFETIME'; LIKE2 : 'LIKE2'; LIKE4 : 'LIKE4'; LIKEC : 'LIKEC'; LIKE_EXPAND : 'LIKE_EXPAND'; LIKE : 'LIKE'; LIMIT : 'LIMIT'; LINEAR : 'LINEAR'; LINES : 'LINES'; LINK : 'LINK'; LIST : 'LIST'; LITTLE : 'LITTLE'; LLS : 'LLS'; LN : 'LN'; LNNVL : 'LNNVL'; LOAD : 'LOAD'; LOB : 'LOB'; LOBFILE : 'LOBFILE'; LOBNVL : 'LOBNVL'; LOBS : 'LOBS'; LOCAL_INDEXES : 'LOCAL_INDEXES'; LOCAL : 'LOCAL'; LOCALTIME : 'LOCALTIME'; LOCALTIMESTAMP : 'LOCALTIMESTAMP'; LOCATION : 'LOCATION'; LOCATOR : 'LOCATOR'; LOCKDOWN : 'LOCKDOWN'; LOCKED : 'LOCKED'; LOCKING : 'LOCKING'; LOCK : 'LOCK'; LOGFILE : 'LOGFILE'; LOGFILES : 'LOGFILES'; LOGGING : 'LOGGING'; LOGICAL : 'LOGICAL'; LOGICAL_READS_PER_CALL : 'LOGICAL_READS_PER_CALL'; LOGICAL_READS_PER_SESSION : 'LOGICAL_READS_PER_SESSION'; LOG : 'LOG'; LOGMINING : 'LOGMINING'; LOGOFF : 'LOGOFF'; LOGON : 'LOGON'; LOG_READ_ONLY_VIOLATIONS : 'LOG_READ_ONLY_VIOLATIONS'; LONG : 'LONG'; LOOP : 'LOOP'; LOST : 'LOST'; LOWER : 'LOWER'; LOW : 'LOW'; LPAD : 'LPAD'; LRTRIM : 'LRTRIM'; LTRIM : 'LTRIM'; M_LETTER : 'M'; MAIN : 'MAIN'; MAKE_REF : 'MAKE_REF'; MANAGED : 'MANAGED'; MANAGE : 'MANAGE'; MANAGEMENT : 'MANAGEMENT'; MANAGER : 'MANAGER'; MANDATORY : 'MANDATORY'; MANUAL : 'MANUAL'; MAP : 'MAP'; MAPPING : 'MAPPING'; MASK : 'MASK'; MASTER : 'MASTER'; MATCHED : 'MATCHED'; MATCHES : 'MATCHES'; MATCH : 'MATCH'; MATCH_NUMBER : 'MATCH_NUMBER'; MATCH_RECOGNIZE : 'MATCH_RECOGNIZE'; MATERIALIZED : 'MATERIALIZED'; MATERIALIZE : 'MATERIALIZE'; MAXARCHLOGS : 'MAXARCHLOGS'; MAXDATAFILES : 'MAXDATAFILES'; MAXEXTENTS : 'MAXEXTENTS'; MAXIMIZE : 'MAXIMIZE'; MAXINSTANCES : 'MAXINSTANCES'; MAXLOGFILES : 'MAXLOGFILES'; MAXLOGHISTORY : 'MAXLOGHISTORY'; MAXLOGMEMBERS : 'MAXLOGMEMBERS'; MAX_SHARED_TEMP_SIZE : 'MAX_SHARED_TEMP_SIZE'; MAXSIZE : 'MAXSIZE'; MAXTRANS : 'MAXTRANS'; MAXVALUE : 'MAXVALUE'; MEASURE : 'MEASURE'; MEASURES : 'MEASURES'; MEDIUM : 'MEDIUM'; MEMBER : 'MEMBER'; MEMBER_CAPTION : 'MEMBER_CAPTION'; MEMBER_DESCRIPTION : 'MEMBER_DESCRIPTION'; MEMBER_NAME : 'MEMBER_NAME'; MEMBER_UNIQUE_NAME : 'MEMBER_UNIQUE_NAME'; MEMCOMPRESS : 'MEMCOMPRESS'; MEMORY : 'MEMORY'; MERGEACTIONS : 'MERGE$ACTIONS'; MERGE_AJ : 'MERGE_AJ'; MERGE_CONST_ON : 'MERGE_CONST_ON'; MERGE : 'MERGE'; MERGE_SJ : 'MERGE_SJ'; METADATA : 'METADATA'; METHOD : 'METHOD'; MIGRATE : 'MIGRATE'; MIGRATION : 'MIGRATION'; MINEXTENTS : 'MINEXTENTS'; MINIMIZE : 'MINIMIZE'; MINIMUM : 'MINIMUM'; MINING : 'MINING'; MINUS : 'MINUS'; MINUS_NULL : 'MINUS_NULL'; MINUTE : 'MINUTE'; MINUTES : 'MINUTES'; MINVALUE : 'MINVALUE'; MIRRORCOLD : 'MIRRORCOLD'; MIRRORHOT : 'MIRRORHOT'; MIRROR : 'MIRROR'; MISSING : 'MISSING'; MISMATCH : 'MISMATCH'; MLSLABEL : 'MLSLABEL'; MODEL_COMPILE_SUBQUERY : 'MODEL_COMPILE_SUBQUERY'; MODEL_DONTVERIFY_UNIQUENESS : 'MODEL_DONTVERIFY_UNIQUENESS'; MODEL_DYNAMIC_SUBQUERY : 'MODEL_DYNAMIC_SUBQUERY'; MODEL_MIN_ANALYSIS : 'MODEL_MIN_ANALYSIS'; MODEL : 'MODEL'; MODEL_NB : 'MODEL_NB'; MODEL_NO_ANALYSIS : 'MODEL_NO_ANALYSIS'; MODEL_PBY : 'MODEL_PBY'; MODEL_PUSH_REF : 'MODEL_PUSH_REF'; MODEL_SV : 'MODEL_SV'; MODE : 'MODE'; MODIFICATION : 'MODIFICATION'; MODIFY_COLUMN_TYPE : 'MODIFY_COLUMN_TYPE'; MODIFY : 'MODIFY'; MOD : 'MOD'; MODULE : 'MODULE'; MONITORING : 'MONITORING'; MONITOR : 'MONITOR'; MONTH : 'MONTH'; MONTHS_BETWEEN : 'MONTHS_BETWEEN'; MONTHS : 'MONTHS'; MOUNT : 'MOUNT'; MOUNTPATH : 'MOUNTPATH'; MOUNTPOINT : 'MOUNTPOINT'; MOVEMENT : 'MOVEMENT'; MOVE : 'MOVE'; MULTIDIMENSIONAL : 'MULTIDIMENSIONAL'; MULTISET : 'MULTISET'; MV_MERGE : 'MV_MERGE'; NAMED : 'NAMED'; NAME : 'NAME'; NAMESPACE : 'NAMESPACE'; NAN_ : 'NAN'; NANVL : 'NANVL'; NATIONAL : 'NATIONAL'; NATIVE_FULL_OUTER_JOIN : 'NATIVE_FULL_OUTER_JOIN'; NATIVE : 'NATIVE'; NATURAL : 'NATURAL'; NATURALN : 'NATURALN'; NAV : 'NAV'; NCHAR_CS : 'NCHAR_CS'; NCHAR : 'NCHAR'; NCHR : 'NCHR'; NCLOB : 'NCLOB'; NEEDED : 'NEEDED'; NEG : 'NEG'; NESTED : 'NESTED'; NESTED_TABLE_FAST_INSERT : 'NESTED_TABLE_FAST_INSERT'; NESTED_TABLE_GET_REFS : 'NESTED_TABLE_GET_REFS'; NESTED_TABLE_ID : 'NESTED_TABLE_ID'; NESTED_TABLE_SET_REFS : 'NESTED_TABLE_SET_REFS'; NESTED_TABLE_SET_SETID : 'NESTED_TABLE_SET_SETID'; NETWORK : 'NETWORK'; NEVER : 'NEVER'; NEW : 'NEW'; NEWLINE_ : 'NEWLINE'; NEW_TIME : 'NEW_TIME'; NEXT_DAY : 'NEXT_DAY'; NEXT : 'NEXT'; NL_AJ : 'NL_AJ'; NLJ_BATCHING : 'NLJ_BATCHING'; NLJ_INDEX_FILTER : 'NLJ_INDEX_FILTER'; NLJ_INDEX_SCAN : 'NLJ_INDEX_SCAN'; NLJ_PREFETCH : 'NLJ_PREFETCH'; NLS_CALENDAR : 'NLS_CALENDAR'; NLS_CHARACTERSET : 'NLS_CHARACTERSET'; NLS_CHARSET_DECL_LEN : 'NLS_CHARSET_DECL_LEN'; NLS_CHARSET_ID : 'NLS_CHARSET_ID'; NLS_CHARSET_NAME : 'NLS_CHARSET_NAME'; NLS_COMP : 'NLS_COMP'; NLS_CURRENCY : 'NLS_CURRENCY'; NLS_DATE_FORMAT : 'NLS_DATE_FORMAT'; NLS_DATE_LANGUAGE : 'NLS_DATE_LANGUAGE'; NLS_INITCAP : 'NLS_INITCAP'; NLS_ISO_CURRENCY : 'NLS_ISO_CURRENCY'; NL_SJ : 'NL_SJ'; NLS_LANG : 'NLS_LANG'; NLS_LANGUAGE : 'NLS_LANGUAGE'; NLS_LENGTH_SEMANTICS : 'NLS_LENGTH_SEMANTICS'; NLS_LOWER : 'NLS_LOWER'; NLS_NCHAR_CONV_EXCP : 'NLS_NCHAR_CONV_EXCP'; NLS_NUMERIC_CHARACTERS : 'NLS_NUMERIC_CHARACTERS'; NLS_SORT : 'NLS_SORT'; NLSSORT : 'NLSSORT'; NLS_SPECIAL_CHARS : 'NLS_SPECIAL_CHARS'; NLS_TERRITORY : 'NLS_TERRITORY'; NLS_UPPER : 'NLS_UPPER'; NO_ACCESS : 'NO_ACCESS'; NO_ADAPTIVE_PLAN : 'NO_ADAPTIVE_PLAN'; NO_ANSI_REARCH : 'NO_ANSI_REARCH'; NOAPPEND : 'NOAPPEND'; NOARCHIVELOG : 'NOARCHIVELOG'; NOAUDIT : 'NOAUDIT'; NOBADFILE : 'NOBADFILE'; NO_AUTO_REOPTIMIZE : 'NO_AUTO_REOPTIMIZE'; NO_BASETABLE_MULTIMV_REWRITE : 'NO_BASETABLE_MULTIMV_REWRITE'; NO_BATCH_TABLE_ACCESS_BY_ROWID : 'NO_BATCH_TABLE_ACCESS_BY_ROWID'; NO_BIND_AWARE : 'NO_BIND_AWARE'; NO_BUFFER : 'NO_BUFFER'; NOCACHE : 'NOCACHE'; NOCHECK : 'NOCHECK'; NO_CARTESIAN : 'NO_CARTESIAN'; NO_CHECK_ACL_REWRITE : 'NO_CHECK_ACL_REWRITE'; NO_CLUSTER_BY_ROWID : 'NO_CLUSTER_BY_ROWID'; NO_CLUSTERING : 'NO_CLUSTERING'; NO_COALESCE_SQ : 'NO_COALESCE_SQ'; NO_COMMON_DATA : 'NO_COMMON_DATA'; NOCOMPRESS : 'NOCOMPRESS'; NO_CONNECT_BY_CB_WHR_ONLY : 'NO_CONNECT_BY_CB_WHR_ONLY'; NO_CONNECT_BY_COMBINE_SW : 'NO_CONNECT_BY_COMBINE_SW'; NO_CONNECT_BY_COST_BASED : 'NO_CONNECT_BY_COST_BASED'; NO_CONNECT_BY_ELIM_DUPS : 'NO_CONNECT_BY_ELIM_DUPS'; NO_CONNECT_BY_FILTERING : 'NO_CONNECT_BY_FILTERING'; NOCOPY : 'NOCOPY'; NO_COST_XML_QUERY_REWRITE : 'NO_COST_XML_QUERY_REWRITE'; NO_CPU_COSTING : 'NO_CPU_COSTING'; NOCPU_COSTING : 'NOCPU_COSTING'; NOCYCLE : 'NOCYCLE'; NO_DATA_SECURITY_REWRITE : 'NO_DATA_SECURITY_REWRITE'; NO_DECORRELATE : 'NO_DECORRELATE'; NODELAY : 'NODELAY'; NODIRECTIO : 'NODIRECTIO'; NODISCARDFILE : 'NODISCARDFILE'; NO_DOMAIN_INDEX_FILTER : 'NO_DOMAIN_INDEX_FILTER'; NO_DST_UPGRADE_INSERT_CONV : 'NO_DST_UPGRADE_INSERT_CONV'; NO_ELIM_GROUPBY : 'NO_ELIM_GROUPBY'; NO_ELIMINATE_JOIN : 'NO_ELIMINATE_JOIN'; NO_ELIMINATE_OBY : 'NO_ELIMINATE_OBY'; NO_ELIMINATE_OUTER_JOIN : 'NO_ELIMINATE_OUTER_JOIN'; NOENTITYESCAPING : 'NOENTITYESCAPING'; NO_EXPAND_GSET_TO_UNION : 'NO_EXPAND_GSET_TO_UNION'; NO_EXPAND : 'NO_EXPAND'; NO_EXPAND_TABLE : 'NO_EXPAND_TABLE'; NOEXTEND : 'NOEXTEND'; NO_FACT : 'NO_FACT'; NO_FACTORIZE_JOIN : 'NO_FACTORIZE_JOIN'; NO_FILTERING : 'NO_FILTERING'; NOFORCE : 'NOFORCE'; NO_FULL_OUTER_JOIN_TO_OUTER : 'NO_FULL_OUTER_JOIN_TO_OUTER'; NO_GATHER_OPTIMIZER_STATISTICS : 'NO_GATHER_OPTIMIZER_STATISTICS'; NO_GBY_PUSHDOWN : 'NO_GBY_PUSHDOWN'; NOGUARANTEE : 'NOGUARANTEE'; NO_INDEX_FFS : 'NO_INDEX_FFS'; NO_INDEX : 'NO_INDEX'; NO_INDEX_SS : 'NO_INDEX_SS'; NO_INMEMORY : 'NO_INMEMORY'; NO_INMEMORY_PRUNING : 'NO_INMEMORY_PRUNING'; NOKEEP : 'NOKEEP'; NO_LOAD : 'NO_LOAD'; NOLOCAL : 'NOLOCAL'; NOLOG : 'NOLOG'; NOLOGFILE : 'NOLOGFILE'; NOLOGGING : 'NOLOGGING'; NOMAPPING : 'NOMAPPING'; NOMAXVALUE : 'NOMAXVALUE'; NO_MERGE : 'NO_MERGE'; NOMINIMIZE : 'NOMINIMIZE'; NOMINVALUE : 'NOMINVALUE'; NO_MODEL_PUSH_REF : 'NO_MODEL_PUSH_REF'; NO_MONITORING : 'NO_MONITORING'; NOMONITORING : 'NOMONITORING'; NO_MONITOR : 'NO_MONITOR'; NO_MULTIMV_REWRITE : 'NO_MULTIMV_REWRITE'; NO_NATIVE_FULL_OUTER_JOIN : 'NO_NATIVE_FULL_OUTER_JOIN'; NONBLOCKING : 'NONBLOCKING'; NONEDITIONABLE : 'NONEDITIONABLE'; NONE : 'NONE'; NONULLIF : 'NONULLIF'; NO_NLJ_BATCHING : 'NO_NLJ_BATCHING'; NO_NLJ_PREFETCH : 'NO_NLJ_PREFETCH'; NO : 'NO'; NONSCHEMA : 'NONSCHEMA'; NO_OBJECT_LINK : 'NO_OBJECT_LINK'; NOORDER : 'NOORDER'; NO_ORDER_ROLLUPS : 'NO_ORDER_ROLLUPS'; NO_OUTER_JOIN_TO_ANTI : 'NO_OUTER_JOIN_TO_ANTI'; NO_OUTER_JOIN_TO_INNER : 'NO_OUTER_JOIN_TO_INNER'; NOOVERRIDE : 'NOOVERRIDE'; NO_PARALLEL_INDEX : 'NO_PARALLEL_INDEX'; NOPARALLEL_INDEX : 'NOPARALLEL_INDEX'; NO_PARALLEL : 'NO_PARALLEL'; NOPARALLEL : 'NOPARALLEL'; NO_PARTIAL_COMMIT : 'NO_PARTIAL_COMMIT'; NO_PARTIAL_JOIN : 'NO_PARTIAL_JOIN'; NO_PARTIAL_ROLLUP_PUSHDOWN : 'NO_PARTIAL_ROLLUP_PUSHDOWN'; NOPARTITION : 'NOPARTITION'; NO_PLACE_DISTINCT : 'NO_PLACE_DISTINCT'; NO_PLACE_GROUP_BY : 'NO_PLACE_GROUP_BY'; NO_PQ_CONCURRENT_UNION : 'NO_PQ_CONCURRENT_UNION'; NO_PQ_MAP : 'NO_PQ_MAP'; NOPROMPT : 'NOPROMPT'; NO_PQ_REPLICATE : 'NO_PQ_REPLICATE'; NO_PQ_SKEW : 'NO_PQ_SKEW'; NO_PRUNE_GSETS : 'NO_PRUNE_GSETS'; NO_PULL_PRED : 'NO_PULL_PRED'; NO_PUSH_PRED : 'NO_PUSH_PRED'; NO_PUSH_SUBQ : 'NO_PUSH_SUBQ'; NO_PX_FAULT_TOLERANCE : 'NO_PX_FAULT_TOLERANCE'; NO_PX_JOIN_FILTER : 'NO_PX_JOIN_FILTER'; NO_QKN_BUFF : 'NO_QKN_BUFF'; NO_QUERY_TRANSFORMATION : 'NO_QUERY_TRANSFORMATION'; NO_REF_CASCADE : 'NO_REF_CASCADE'; NORELOCATE : 'NORELOCATE'; NORELY : 'NORELY'; NOREPAIR : 'NOREPAIR'; NOREPLAY : 'NOREPLAY'; NORESETLOGS : 'NORESETLOGS'; NO_RESULT_CACHE : 'NO_RESULT_CACHE'; NOREVERSE : 'NOREVERSE'; NO_REWRITE : 'NO_REWRITE'; NOREWRITE : 'NOREWRITE'; NORMAL : 'NORMAL'; NO_ROOT_SW_FOR_LOCAL : 'NO_ROOT_SW_FOR_LOCAL'; NOROWDEPENDENCIES : 'NOROWDEPENDENCIES'; NOSCALE : 'NOSCALE'; NOSCHEMACHECK : 'NOSCHEMACHECK'; NOSEGMENT : 'NOSEGMENT'; NO_SEMIJOIN : 'NO_SEMIJOIN'; NO_SEMI_TO_INNER : 'NO_SEMI_TO_INNER'; NO_SET_TO_JOIN : 'NO_SET_TO_JOIN'; NOSHARD : 'NOSHARD'; NOSORT : 'NOSORT'; NO_SQL_TRANSLATION : 'NO_SQL_TRANSLATION'; NO_SQL_TUNE : 'NO_SQL_TUNE'; NO_STAR_TRANSFORMATION : 'NO_STAR_TRANSFORMATION'; NO_STATEMENT_QUEUING : 'NO_STATEMENT_QUEUING'; NO_STATS_GSETS : 'NO_STATS_GSETS'; NOSTRICT : 'NOSTRICT'; NO_SUBQUERY_PRUNING : 'NO_SUBQUERY_PRUNING'; NO_SUBSTRB_PAD : 'NO_SUBSTRB_PAD'; NO_SWAP_JOIN_INPUTS : 'NO_SWAP_JOIN_INPUTS'; NOSWITCH : 'NOSWITCH'; NO_TABLE_LOOKUP_BY_NL : 'NO_TABLE_LOOKUP_BY_NL'; NO_TEMP_TABLE : 'NO_TEMP_TABLE'; NOTHING : 'NOTHING'; NOTIFICATION : 'NOTIFICATION'; NOTRIM : 'NOTRIM'; NOT : 'NOT'; NO_TRANSFORM_DISTINCT_AGG : 'NO_TRANSFORM_DISTINCT_AGG'; NO_UNNEST : 'NO_UNNEST'; NO_USE_CUBE : 'NO_USE_CUBE'; NO_USE_HASH_AGGREGATION : 'NO_USE_HASH_AGGREGATION'; NO_USE_HASH_GBY_FOR_PUSHDOWN : 'NO_USE_HASH_GBY_FOR_PUSHDOWN'; NO_USE_HASH : 'NO_USE_HASH'; NO_USE_INVISIBLE_INDEXES : 'NO_USE_INVISIBLE_INDEXES'; NO_USE_MERGE : 'NO_USE_MERGE'; NO_USE_NL : 'NO_USE_NL'; NO_USE_VECTOR_AGGREGATION : 'NO_USE_VECTOR_AGGREGATION'; NOVALIDATE : 'NOVALIDATE'; NO_VECTOR_TRANSFORM_DIMS : 'NO_VECTOR_TRANSFORM_DIMS'; NO_VECTOR_TRANSFORM_FACT : 'NO_VECTOR_TRANSFORM_FACT'; NO_VECTOR_TRANSFORM : 'NO_VECTOR_TRANSFORM'; NOWAIT : 'NOWAIT'; NO_XDB_FASTPATH_INSERT : 'NO_XDB_FASTPATH_INSERT'; NO_XML_DML_REWRITE : 'NO_XML_DML_REWRITE'; NO_XMLINDEX_REWRITE_IN_SELECT : 'NO_XMLINDEX_REWRITE_IN_SELECT'; NO_XMLINDEX_REWRITE : 'NO_XMLINDEX_REWRITE'; NO_XML_QUERY_REWRITE : 'NO_XML_QUERY_REWRITE'; NO_ZONEMAP : 'NO_ZONEMAP'; NTH_VALUE : 'NTH_VALUE'; NULLIF : 'NULLIF'; NULL_ : 'NULL'; NULLS : 'NULLS'; NUMBER : 'NUMBER'; NUMERIC : 'NUMERIC'; NUM_INDEX_KEYS : 'NUM_INDEX_KEYS'; NUMTODSINTERVAL : 'NUMTODSINTERVAL'; NUMTOYMINTERVAL : 'NUMTOYMINTERVAL'; NVARCHAR2 : 'NVARCHAR2'; NVL2 : 'NVL2'; OBJECT2XML : 'OBJECT2XML'; OBJECT : 'OBJECT'; OBJ_ID : 'OBJ_ID'; OBJNO : 'OBJNO'; OBJNO_REUSE : 'OBJNO_REUSE'; OCCURENCES : 'OCCURENCES'; OFFLINE : 'OFFLINE'; OFF : 'OFF'; OFFSET : 'OFFSET'; OF : 'OF'; OIDINDEX : 'OIDINDEX'; OID : 'OID'; OLAP : 'OLAP'; OLD : 'OLD'; OLD_PUSH_PRED : 'OLD_PUSH_PRED'; OLS : 'OLS'; OLTP : 'OLTP'; OMIT : 'OMIT'; ONE : 'ONE'; ONLINE : 'ONLINE'; ONLINELOG : 'ONLINELOG'; ONLY : 'ONLY'; ON : 'ON'; OPAQUE : 'OPAQUE'; OPAQUE_TRANSFORM : 'OPAQUE_TRANSFORM'; OPAQUE_XCANONICAL : 'OPAQUE_XCANONICAL'; OPCODE : 'OPCODE'; OPEN : 'OPEN'; OPERATIONS : 'OPERATIONS'; OPERATOR : 'OPERATOR'; OPT_ESTIMATE : 'OPT_ESTIMATE'; OPTIMAL : 'OPTIMAL'; OPTIMIZE : 'OPTIMIZE'; OPTIMIZER_FEATURES_ENABLE : 'OPTIMIZER_FEATURES_ENABLE'; OPTIMIZER_GOAL : 'OPTIMIZER_GOAL'; OPTION : 'OPTION'; OPTIONALLY : 'OPTIONALLY'; OPT_PARAM : 'OPT_PARAM'; ORA_BRANCH : 'ORA_BRANCH'; ORA_CHECK_ACL : 'ORA_CHECK_ACL'; ORA_CHECK_PRIVILEGE : 'ORA_CHECK_PRIVILEGE'; ORA_CLUSTERING : 'ORA_CLUSTERING'; ORADATA : 'ORADATA'; ORC : 'ORC'; ORACLE_DATE : 'ORACLE_DATE'; ORACLE_NUMBER : 'ORACLE_NUMBER'; ORADEBUG : 'ORADEBUG'; ORA_DST_AFFECTED : 'ORA_DST_AFFECTED'; ORA_DST_CONVERT : 'ORA_DST_CONVERT'; ORA_DST_ERROR : 'ORA_DST_ERROR'; ORA_GET_ACLIDS : 'ORA_GET_ACLIDS'; ORA_GET_PRIVILEGES : 'ORA_GET_PRIVILEGES'; ORA_HASH : 'ORA_HASH'; ORA_INVOKING_USERID : 'ORA_INVOKING_USERID'; ORA_INVOKING_USER : 'ORA_INVOKING_USER'; ORA_INVOKING_XS_USER_GUID : 'ORA_INVOKING_XS_USER_GUID'; ORA_INVOKING_XS_USER : 'ORA_INVOKING_XS_USER'; ORA_RAWCOMPARE : 'ORA_RAWCOMPARE'; ORA_RAWCONCAT : 'ORA_RAWCONCAT'; ORA_ROWSCN : 'ORA_ROWSCN'; ORA_ROWSCN_RAW : 'ORA_ROWSCN_RAW'; ORA_ROWVERSION : 'ORA_ROWVERSION'; ORA_TABVERSION : 'ORA_TABVERSION'; ORA_WRITE_TIME : 'ORA_WRITE_TIME'; ORDERED : 'ORDERED'; ORDERED_PREDICATES : 'ORDERED_PREDICATES'; ORDER : 'ORDER'; ORDINALITY : 'ORDINALITY'; OR_EXPAND : 'OR_EXPAND'; ORGANIZATION : 'ORGANIZATION'; OR : 'OR'; OR_PREDICATES : 'OR_PREDICATES'; OSERROR : 'OSERROR'; OTHER : 'OTHER'; OUTER_JOIN_TO_ANTI : 'OUTER_JOIN_TO_ANTI'; OUTER_JOIN_TO_INNER : 'OUTER_JOIN_TO_INNER'; OUTER : 'OUTER'; OUTLINE_LEAF : 'OUTLINE_LEAF'; OUTLINE : 'OUTLINE'; OUTPUTFORMAT : 'OUTPUTFORMAT'; OUT_OF_LINE : 'OUT_OF_LINE'; OUT : 'OUT'; OVERFLOW_NOMOVE : 'OVERFLOW_NOMOVE'; OVERFLOW_ : 'OVERFLOW'; OVERLAPS : 'OVERLAPS'; OVER : 'OVER'; OVERRIDE : 'OVERRIDE'; OVERRIDING : 'OVERRIDING'; OWNER : 'OWNER'; OWNERSHIP : 'OWNERSHIP'; OWN : 'OWN'; P_LETTER : 'P'; PACKAGE : 'PACKAGE'; PACKAGES : 'PACKAGES'; PARALLEL_ENABLE : 'PARALLEL_ENABLE'; PARALLEL_INDEX : 'PARALLEL_INDEX'; PARALLEL : 'PARALLEL'; PARAMETERFILE : 'PARAMETERFILE'; PARAMETERS : 'PARAMETERS'; PARAM : 'PARAM'; PARENT : 'PARENT'; PARENT_LEVEL_NAME : 'PARENT_LEVEL_NAME'; PARENT_UNIQUE_NAME : 'PARENT_UNIQUE_NAME'; PARITY : 'PARITY'; PARQUET : 'PARQUET'; PARTIAL_JOIN : 'PARTIAL_JOIN'; PARTIALLY : 'PARTIALLY'; PARTIAL : 'PARTIAL'; PARTIAL_ROLLUP_PUSHDOWN : 'PARTIAL_ROLLUP_PUSHDOWN'; PARTITION_HASH : 'PARTITION_HASH'; PARTITION_LIST : 'PARTITION_LIST'; PARTITION : 'PARTITION'; PARTITION_RANGE : 'PARTITION_RANGE'; PARTITIONS : 'PARTITIONS'; PARTNUMINST : 'PART$NUM$INST'; PASSING : 'PASSING'; PASSWORD_GRACE_TIME : 'PASSWORD_GRACE_TIME'; PASSWORD_LIFE_TIME : 'PASSWORD_LIFE_TIME'; PASSWORD_LOCK_TIME : 'PASSWORD_LOCK_TIME'; PASSWORD : 'PASSWORD'; PASSWORD_REUSE_MAX : 'PASSWORD_REUSE_MAX'; PASSWORD_REUSE_TIME : 'PASSWORD_REUSE_TIME'; PASSWORD_ROLLOVER_TIME : 'PASSWORD_ROLLOVER_TIME'; PASSWORD_VERIFY_FUNCTION : 'PASSWORD_VERIFY_FUNCTION'; PAST : 'PAST'; PATCH : 'PATCH'; PATH : 'PATH'; PATH_PREFIX : 'PATH_PREFIX'; PATHS : 'PATHS'; PATTERN : 'PATTERN'; PBL_HS_BEGIN : 'PBL_HS_BEGIN'; PBL_HS_END : 'PBL_HS_END'; PCTFREE : 'PCTFREE'; PCTINCREASE : 'PCTINCREASE'; PCTTHRESHOLD : 'PCTTHRESHOLD'; PCTUSED : 'PCTUSED'; PCTVERSION : 'PCTVERSION'; PENDING : 'PENDING'; PERCENT_FOUND : '%' SPACE* 'FOUND'; PERCENT_ISOPEN : '%' SPACE* 'ISOPEN'; PERCENT_NOTFOUND : '%' SPACE* 'NOTFOUND'; PERCENT_KEYWORD : 'PERCENT'; PERCENT_RANKM : 'PERCENT_RANKM'; PERCENT_ROWCOUNT : '%' SPACE* 'ROWCOUNT'; PERCENT_ROWTYPE : '%' SPACE* 'ROWTYPE'; PERCENT_TYPE : '%' SPACE* 'TYPE'; PERCENT_BULK_EXCEPTIONS : '%' SPACE* 'BULK_EXCEPTIONS'; PERCENT_BULK_ROWCOUNT : '%' SPACE* 'BULK_ROWCOUNT'; PERFORMANCE : 'PERFORMANCE'; PERIOD_KEYWORD : 'PERIOD'; PERMANENT : 'PERMANENT'; PERMISSION : 'PERMISSION'; PERMUTE : 'PERMUTE'; PER : 'PER'; PFILE : 'PFILE'; PHYSICAL : 'PHYSICAL'; PIKEY : 'PIKEY'; PIPELINED : 'PIPELINED'; PIPE : 'PIPE'; PIV_GB : 'PIV_GB'; PIVOT : 'PIVOT'; PIV_SSF : 'PIV_SSF'; PLACE_DISTINCT : 'PLACE_DISTINCT'; PLACE_GROUP_BY : 'PLACE_GROUP_BY'; PLAN : 'PLAN'; PLSCOPE_SETTINGS : 'PLSCOPE_SETTINGS'; PLS_INTEGER : 'PLS_INTEGER'; PLSQL_CCFLAGS : 'PLSQL_CCFLAGS'; PLSQL_CODE_TYPE : 'PLSQL_CODE_TYPE'; PLSQL_DEBUG : 'PLSQL_DEBUG'; PLSQL_OPTIMIZE_LEVEL : 'PLSQL_OPTIMIZE_LEVEL'; PLSQL_WARNINGS : 'PLSQL_WARNINGS'; PLUGGABLE : 'PLUGGABLE'; PMEM : 'PMEM'; POINT : 'POINT'; POLICY : 'POLICY'; POOL_16K : 'POOL_16K'; POOL_2K : 'POOL_2K'; POOL_32K : 'POOL_32K'; POOL_4K : 'POOL_4K'; POOL_8K : 'POOL_8K'; POSITION : 'POSITION'; POSITIVEN : 'POSITIVEN'; POSITIVE : 'POSITIVE'; POST_TRANSACTION : 'POST_TRANSACTION'; POWERMULTISET_BY_CARDINALITY : 'POWERMULTISET_BY_CARDINALITY'; POWERMULTISET : 'POWERMULTISET'; POWER : 'POWER'; PQ_CONCURRENT_UNION : 'PQ_CONCURRENT_UNION'; PQ_DISTRIBUTE : 'PQ_DISTRIBUTE'; PQ_DISTRIBUTE_WINDOW : 'PQ_DISTRIBUTE_WINDOW'; PQ_FILTER : 'PQ_FILTER'; PQ_MAP : 'PQ_MAP'; PQ_NOMAP : 'PQ_NOMAP'; PQ_REPLICATE : 'PQ_REPLICATE'; PQ_SKEW : 'PQ_SKEW'; PRAGMA : 'PRAGMA'; PREBUILT : 'PREBUILT'; PRECEDES : 'PRECEDES'; PRECEDING : 'PRECEDING'; PRECISION : 'PRECISION'; PRECOMPUTE_SUBQUERY : 'PRECOMPUTE_SUBQUERY'; PREDICATE_REORDERS : 'PREDICATE_REORDERS'; PRELOAD : 'PRELOAD'; PREPARE : 'PREPARE'; PREPROCESSOR : 'PREPROCESSOR'; PRESENTNNV : 'PRESENTNNV'; PRESENT : 'PRESENT'; PRESENTV : 'PRESENTV'; PRESERVE_OID : 'PRESERVE_OID'; PRESERVE : 'PRESERVE'; PRETTY : 'PRETTY'; PREVIOUS : 'PREVIOUS'; PREV : 'PREV'; PRIMARY : 'PRIMARY'; PRINTBLOBTOCLOB : 'PRINTBLOBTOCLOB'; PRIORITY : 'PRIORITY'; PRIOR : 'PRIOR'; PRIVATE : 'PRIVATE'; PRIVATE_SGA : 'PRIVATE_SGA'; PRIVILEGED : 'PRIVILEGED'; PRIVILEGE : 'PRIVILEGE'; PRIVILEGES : 'PRIVILEGES'; PROCEDURAL : 'PROCEDURAL'; PROCEDURE : 'PROCEDURE'; PROCESS : 'PROCESS'; PROFILE : 'PROFILE'; PROGRAM : 'PROGRAM'; PROJECT : 'PROJECT'; PROPAGATE : 'PROPAGATE'; PROPERTY : 'PROPERTY'; PROTECTED : 'PROTECTED'; PROTECTION : 'PROTECTION'; PROTOCOL : 'PROTOCOL'; PROXY : 'PROXY'; PRUNING : 'PRUNING'; PUBLIC : 'PUBLIC'; PULL_PRED : 'PULL_PRED'; PURGE : 'PURGE'; PUSH_PRED : 'PUSH_PRED'; PUSH_SUBQ : 'PUSH_SUBQ'; PX_FAULT_TOLERANCE : 'PX_FAULT_TOLERANCE'; PX_GRANULE : 'PX_GRANULE'; PX_JOIN_FILTER : 'PX_JOIN_FILTER'; QB_NAME : 'QB_NAME'; QUARTERS : 'QUARTERS'; QUERY_BLOCK : 'QUERY_BLOCK'; QUERY : 'QUERY'; QUEUE_CURR : 'QUEUE_CURR'; QUEUE : 'QUEUE'; QUEUE_ROWP : 'QUEUE_ROWP'; QUIESCE : 'QUIESCE'; QUORUM : 'QUORUM'; QUOTA : 'QUOTA'; QUOTAGROUP : 'QUOTAGROUP'; RAISE : 'RAISE'; RANDOM_LOCAL : 'RANDOM_LOCAL'; RANDOM : 'RANDOM'; RANGE : 'RANGE'; RANKM : 'RANKM'; RAPIDLY : 'RAPIDLY'; RAW : 'RAW'; RAWTOHEX : 'RAWTOHEX'; RAWTONHEX : 'RAWTONHEX'; RBA : 'RBA'; RBO_OUTLINE : 'RBO_OUTLINE'; RCFILE : 'RCFILE'; RDBA : 'RDBA'; READ : 'READ'; READS : 'READS'; READSIZE : 'READSIZE'; REALM : 'REALM'; REAL : 'REAL'; REBALANCE : 'REBALANCE'; REBUILD : 'REBUILD'; RECORD : 'RECORD'; RECORDS : 'RECORDS'; RECORDS_PER_BLOCK : 'RECORDS_PER_BLOCK'; RECOVERABLE : 'RECOVERABLE'; RECOVER : 'RECOVER'; RECOVERY : 'RECOVERY'; RECYCLEBIN : 'RECYCLEBIN'; RECYCLE : 'RECYCLE'; REDACTION : 'REDACTION'; REDEFINE : 'REDEFINE'; REDO : 'REDO'; REDUCED : 'REDUCED'; REDUNDANCY : 'REDUNDANCY'; REF_CASCADE_CURSOR : 'REF_CASCADE_CURSOR'; REFERENCED : 'REFERENCED'; REFERENCE : 'REFERENCE'; REFERENCES : 'REFERENCES'; REFERENCING : 'REFERENCING'; REF : 'REF'; REFRESH : 'REFRESH'; REFTOHEX : 'REFTOHEX'; REGEXP_COUNT : 'REGEXP_COUNT'; REGEXP_INSTR : 'REGEXP_INSTR'; REGEXP_LIKE : 'REGEXP_LIKE'; REGEXP_REPLACE : 'REGEXP_REPLACE'; REGEXP_SUBSTR : 'REGEXP_SUBSTR'; REGISTER : 'REGISTER'; REGR_AVGX : 'REGR_AVGX'; REGR_AVGY : 'REGR_AVGY'; REGR_COUNT : 'REGR_COUNT'; REGR_INTERCEPT : 'REGR_INTERCEPT'; REGR_R2 : 'REGR_R2'; REGR_SLOPE : 'REGR_SLOPE'; REGR_SXX : 'REGR_SXX'; REGR_SXY : 'REGR_SXY'; REGR_SYY : 'REGR_SYY'; REGULAR : 'REGULAR'; REJECT : 'REJECT'; REKEY : 'REKEY'; RELATIONAL : 'RELATIONAL'; RELIES_ON : 'RELIES_ON'; RELOCATE : 'RELOCATE'; RELY : 'RELY'; REMAINDER : 'REMAINDER'; REMOTE : 'REMOTE'; REMOTE_MAPPED : 'REMOTE_MAPPED'; REMOVE : 'REMOVE'; RENAME : 'RENAME'; REPAIR : 'REPAIR'; REPEAT : 'REPEAT'; REPLACE : 'REPLACE'; REPLICATION : 'REPLICATION'; REQUIRED : 'REQUIRED'; RESETLOGS : 'RESETLOGS'; RESET : 'RESET'; RESIZE : 'RESIZE'; RESOLVE : 'RESOLVE'; RESOLVER : 'RESOLVER'; RESOURCE : 'RESOURCE'; RESPECT : 'RESPECT'; RESTART : 'RESTART'; RESTORE_AS_INTERVALS : 'RESTORE_AS_INTERVALS'; RESTORE : 'RESTORE'; RESTRICT_ALL_REF_CONS : 'RESTRICT_ALL_REF_CONS'; RESTRICTED : 'RESTRICTED'; RESTRICT_REFERENCES : 'RESTRICT_REFERENCES'; RESTRICT : 'RESTRICT'; RESULT_CACHE : 'RESULT_CACHE'; RESULT : 'RESULT'; RESUMABLE : 'RESUMABLE'; RESUME : 'RESUME'; RETENTION : 'RETENTION'; RETRY_ON_ROW_CHANGE : 'RETRY_ON_ROW_CHANGE'; RETURNING : 'RETURNING'; RETURN : 'RETURN'; REUSE : 'REUSE'; REVERSE : 'REVERSE'; REVOKE : 'REVOKE'; REWRITE_OR_ERROR : 'REWRITE_OR_ERROR'; REWRITE : 'REWRITE'; RIGHT : 'RIGHT'; ROLE : 'ROLE'; ROLESET : 'ROLESET'; ROLES : 'ROLES'; ROLLBACK : 'ROLLBACK'; ROLLING : 'ROLLING'; ROLLUP : 'ROLLUP'; ROWDEPENDENCIES : 'ROWDEPENDENCIES'; ROWID_MAPPING_TABLE : 'ROWID_MAPPING_TABLE'; ROWID : 'ROWID'; ROWIDTOCHAR : 'ROWIDTOCHAR'; ROWIDTONCHAR : 'ROWIDTONCHAR'; ROW_LENGTH : 'ROW_LENGTH'; ROWNUM : 'ROWNUM'; ROW : 'ROW'; ROWS : 'ROWS'; RPAD : 'RPAD'; RTRIM : 'RTRIM'; RULE : 'RULE'; RULES : 'RULES'; RUNNING : 'RUNNING'; SALT : 'SALT'; SAMPLE : 'SAMPLE'; SAVE_AS_INTERVALS : 'SAVE_AS_INTERVALS'; SAVEPOINT : 'SAVEPOINT'; SAVE : 'SAVE'; SB4 : 'SB4'; SCALE_ROWS : 'SCALE_ROWS'; SCALE : 'SCALE'; SCAN_INSTANCES : 'SCAN_INSTANCES'; SCAN : 'SCAN'; SCHEDULER : 'SCHEDULER'; SCHEMACHECK : 'SCHEMACHECK'; SCHEMA : 'SCHEMA'; SCN_ASCENDING : 'SCN_ASCENDING'; SCN : 'SCN'; SCOPE : 'SCOPE'; SCRUB : 'SCRUB'; SD_ALL : 'SD_ALL'; SD_INHIBIT : 'SD_INHIBIT'; SDO_GEOM_MBR : 'SDO_GEOM_MBR'; SDO_GEOMETRY : 'SDO_GEOMETRY'; SD_SHOW : 'SD_SHOW'; SEARCH : 'SEARCH'; SECOND : 'SECOND'; SECONDS : 'SECONDS'; SECRET : 'SECRET'; SECUREFILE_DBA : 'SECUREFILE_DBA'; SECUREFILE : 'SECUREFILE'; SECURITY : 'SECURITY'; SEED : 'SEED'; SEG_BLOCK : 'SEG_BLOCK'; SEG_FILE : 'SEG_FILE'; SEGMENT : 'SEGMENT'; SELECTIVITY : 'SELECTIVITY'; SELECT : 'SELECT'; SELF : 'SELF'; SEMIJOIN_DRIVER : 'SEMIJOIN_DRIVER'; SEMIJOIN : 'SEMIJOIN'; SEMI_TO_INNER : 'SEMI_TO_INNER'; SEQUENCED : 'SEQUENCED'; SEQUENCE : 'SEQUENCE'; SEQUENCEFILE : 'SEQUENCEFILE'; SEQUENTIAL : 'SEQUENTIAL'; SEQ : 'SEQ'; SERDE : 'SERDE'; SERDEPROPERTIES : 'SERDEPROPERTIES'; SERIALIZABLE : 'SERIALIZABLE'; SERIALLY_REUSABLE : 'SERIALLY_REUSABLE'; SERIAL : 'SERIAL'; SERVERERROR : 'SERVERERROR'; SERVICE_NAME_CONVERT : 'SERVICE_NAME_CONVERT'; SERVICE : 'SERVICE'; SERVICES : 'SERVICES'; SESSION_CACHED_CURSORS : 'SESSION_CACHED_CURSORS'; SESSION : 'SESSION'; SESSIONS_PER_USER : 'SESSIONS_PER_USER'; SESSIONTIMEZONE : 'SESSIONTIMEZONE'; SESSIONTZNAME : 'SESSIONTZNAME'; SET : 'SET'; SETS : 'SETS'; SETTINGS : 'SETTINGS'; SET_TO_JOIN : 'SET_TO_JOIN'; SEVERE : 'SEVERE'; SHARD : 'SHARD'; SHARDSPACE : 'SHARDSPACE'; SHARED_POOL : 'SHARED_POOL'; SHARED : 'SHARED'; SHARE : 'SHARE'; SHARING : 'SHARING'; SHELFLIFE : 'SHELFLIFE'; SHOW : 'SHOW'; SHRINK : 'SHRINK'; SHUTDOWN : 'SHUTDOWN'; SIBLINGS : 'SIBLINGS'; SID : 'SID'; SITE : 'SITE'; SIGNAL_COMPONENT : 'SIGNAL_COMPONENT'; SIGNAL_FUNCTION : 'SIGNAL_FUNCTION'; SIGN : 'SIGN'; SIGNTYPE : 'SIGNTYPE'; SIMPLE_INTEGER : 'SIMPLE_INTEGER'; SIMPLE : 'SIMPLE'; SINGLE : 'SINGLE'; SINGLETASK : 'SINGLETASK'; SINH : 'SINH'; SIN : 'SIN'; SIZE : 'SIZE'; SIZES : 'SIZES'; SKIP_EXT_OPTIMIZER : 'SKIP_EXT_OPTIMIZER'; SKIP_ : 'SKIP'; SKIP_UNQ_UNUSABLE_IDX : 'SKIP_UNQ_UNUSABLE_IDX'; SKIP_UNUSABLE_INDEXES : 'SKIP_UNUSABLE_INDEXES'; SMALLFILE : 'SMALLFILE'; SMALLINT : 'SMALLINT'; SNAPSHOT : 'SNAPSHOT'; SOME : 'SOME'; SORT : 'SORT'; SOUNDEX : 'SOUNDEX'; SOURCE_FILE_DIRECTORY : 'SOURCE_FILE_DIRECTORY'; SOURCE_FILE_NAME_CONVERT : 'SOURCE_FILE_NAME_CONVERT'; SOURCE : 'SOURCE'; SPACE_KEYWORD : 'SPACE'; SPECIFICATION : 'SPECIFICATION'; SPFILE : 'SPFILE'; SPLIT : 'SPLIT'; SPREADSHEET : 'SPREADSHEET'; SQLDATA : 'SQLDATA'; SQLERROR : 'SQLERROR'; SQLLDR : 'SQLLDR'; SQL : 'SQL'; FILE_EXT : 'PKB' | 'PKS'; SQL_MACRO : 'SQL_MACRO'; SQL_TRACE : 'SQL_TRACE'; SQL_TRANSLATION_PROFILE : 'SQL_TRANSLATION_PROFILE'; SQRT : 'SQRT'; STALE : 'STALE'; STANDALONE : 'STANDALONE'; STANDARD : 'STANDARD'; STANDARD_HASH : 'STANDARD_HASH'; STANDBY_MAX_DATA_DELAY : 'STANDBY_MAX_DATA_DELAY'; STANDBYS : 'STANDBYS'; STANDBY : 'STANDBY'; STAR : 'STAR'; STAR_TRANSFORMATION : 'STAR_TRANSFORMATION'; START : 'START'; STARTOF : 'STARTOF'; STARTUP : 'STARTUP'; STATEMENT_ID : 'STATEMENT_ID'; STATEMENT_QUEUING : 'STATEMENT_QUEUING'; STATEMENTS : 'STATEMENTS'; STATEMENT : 'STATEMENT'; STATE : 'STATE'; STATIC : 'STATIC'; STATISTICS : 'STATISTICS'; STATS_BINOMIAL_TEST : 'STATS_BINOMIAL_TEST'; STATS_CROSSTAB : 'STATS_CROSSTAB'; STATS_F_TEST : 'STATS_F_TEST'; STATS_KS_TEST : 'STATS_KS_TEST'; STATS_MODE : 'STATS_MODE'; STATS_MW_TEST : 'STATS_MW_TEST'; STATS_ONE_WAY_ANOVA : 'STATS_ONE_WAY_ANOVA'; STATS_T_TEST_INDEP : 'STATS_T_TEST_INDEP'; STATS_T_TEST_INDEPU : 'STATS_T_TEST_INDEPU'; STATS_T_TEST_ONE : 'STATS_T_TEST_ONE'; STATS_T_TEST_PAIRED : 'STATS_T_TEST_PAIRED'; STATS_WSR_TEST : 'STATS_WSR_TEST'; STDDEV_POP : 'STDDEV_POP'; STDDEV_SAMP : 'STDDEV_SAMP'; STOP : 'STOP'; STORAGE : 'STORAGE'; STORE : 'STORE'; STREAMS : 'STREAMS'; STREAM : 'STREAM'; STRICT : 'STRICT'; STRING : 'STRING'; STRIPE_COLUMNS : 'STRIPE_COLUMNS'; STRIPE_WIDTH : 'STRIPE_WIDTH'; STRIP : 'STRIP'; STRUCTURE : 'STRUCTURE'; SUBMULTISET : 'SUBMULTISET'; SUBPARTITION_REL : 'SUBPARTITION_REL'; SUBPARTITIONS : 'SUBPARTITIONS'; SUBPARTITION : 'SUBPARTITION'; SUBQUERIES : 'SUBQUERIES'; SUBQUERY_PRUNING : 'SUBQUERY_PRUNING'; SUBSCRIBE : 'SUBSCRIBE'; SUBSET : 'SUBSET'; SUBSTITUTABLE : 'SUBSTITUTABLE'; SUBSTR2 : 'SUBSTR2'; SUBSTR4 : 'SUBSTR4'; SUBSTRB : 'SUBSTRB'; SUBSTRC : 'SUBSTRC'; SUBTYPE : 'SUBTYPE'; SUCCESSFUL : 'SUCCESSFUL'; SUCCESS : 'SUCCESS'; SUMMARY : 'SUMMARY'; SUPPLEMENTAL : 'SUPPLEMENTAL'; SUSPEND : 'SUSPEND'; SWAP_JOIN_INPUTS : 'SWAP_JOIN_INPUTS'; SWITCHOVER : 'SWITCHOVER'; SWITCH : 'SWITCH'; SYNCHRONOUS : 'SYNCHRONOUS'; SYNC : 'SYNC'; SYNONYM : 'SYNONYM'; SYS : 'SYS'; SYSASM : 'SYSASM'; SYS_AUDIT : 'SYS_AUDIT'; SYSAUX : 'SYSAUX'; SYSBACKUP : 'SYSBACKUP'; SYS_CHECKACL : 'SYS_CHECKACL'; SYS_CHECK_PRIVILEGE : 'SYS_CHECK_PRIVILEGE'; SYS_CONNECT_BY_PATH : 'SYS_CONNECT_BY_PATH'; SYS_CONTEXT : 'SYS_CONTEXT'; SYSDATE : 'SYSDATE'; SYSDBA : 'SYSDBA'; SYS_DBURIGEN : 'SYS_DBURIGEN'; SYSDG : 'SYSDG'; SYS_DL_CURSOR : 'SYS_DL_CURSOR'; SYS_DM_RXFORM_CHR : 'SYS_DM_RXFORM_CHR'; SYS_DM_RXFORM_NUM : 'SYS_DM_RXFORM_NUM'; SYS_DOM_COMPARE : 'SYS_DOM_COMPARE'; SYS_DST_PRIM2SEC : 'SYS_DST_PRIM2SEC'; SYS_DST_SEC2PRIM : 'SYS_DST_SEC2PRIM'; SYS_ET_BFILE_TO_RAW : 'SYS_ET_BFILE_TO_RAW'; SYS_ET_BLOB_TO_IMAGE : 'SYS_ET_BLOB_TO_IMAGE'; SYS_ET_IMAGE_TO_BLOB : 'SYS_ET_IMAGE_TO_BLOB'; SYS_ET_RAW_TO_BFILE : 'SYS_ET_RAW_TO_BFILE'; SYS_EXTPDTXT : 'SYS_EXTPDTXT'; SYS_EXTRACT_UTC : 'SYS_EXTRACT_UTC'; SYS_FBT_INSDEL : 'SYS_FBT_INSDEL'; SYS_FILTER_ACLS : 'SYS_FILTER_ACLS'; SYS_FNMATCHES : 'SYS_FNMATCHES'; SYS_FNREPLACE : 'SYS_FNREPLACE'; SYS_GET_ACLIDS : 'SYS_GET_ACLIDS'; SYS_GET_COL_ACLIDS : 'SYS_GET_COL_ACLIDS'; SYS_GET_PRIVILEGES : 'SYS_GET_PRIVILEGES'; SYS_GETTOKENID : 'SYS_GETTOKENID'; SYS_GETXTIVAL : 'SYS_GETXTIVAL'; SYS_GUID : 'SYS_GUID'; SYSGUID : 'SYSGUID'; SYSKM : 'SYSKM'; SYS_MAKE_XMLNODEID : 'SYS_MAKE_XMLNODEID'; SYS_MAKEXML : 'SYS_MAKEXML'; SYS_MKXMLATTR : 'SYS_MKXMLATTR'; SYS_MKXTI : 'SYS_MKXTI'; SYSOBJ : 'SYSOBJ'; SYS_OP_ADT2BIN : 'SYS_OP_ADT2BIN'; SYS_OP_ADTCONS : 'SYS_OP_ADTCONS'; SYS_OP_ALSCRVAL : 'SYS_OP_ALSCRVAL'; SYS_OP_ATG : 'SYS_OP_ATG'; SYS_OP_BIN2ADT : 'SYS_OP_BIN2ADT'; SYS_OP_BITVEC : 'SYS_OP_BITVEC'; SYS_OP_BL2R : 'SYS_OP_BL2R'; SYS_OP_BLOOM_FILTER_LIST : 'SYS_OP_BLOOM_FILTER_LIST'; SYS_OP_BLOOM_FILTER : 'SYS_OP_BLOOM_FILTER'; SYS_OP_C2C : 'SYS_OP_C2C'; SYS_OP_CAST : 'SYS_OP_CAST'; SYS_OP_CEG : 'SYS_OP_CEG'; SYS_OP_CL2C : 'SYS_OP_CL2C'; SYS_OP_COMBINED_HASH : 'SYS_OP_COMBINED_HASH'; SYS_OP_COMP : 'SYS_OP_COMP'; SYS_OP_CONVERT : 'SYS_OP_CONVERT'; SYS_OP_COUNTCHG : 'SYS_OP_COUNTCHG'; SYS_OP_CSCONV : 'SYS_OP_CSCONV'; SYS_OP_CSCONVTEST : 'SYS_OP_CSCONVTEST'; SYS_OP_CSR : 'SYS_OP_CSR'; SYS_OP_CSX_PATCH : 'SYS_OP_CSX_PATCH'; SYS_OP_CYCLED_SEQ : 'SYS_OP_CYCLED_SEQ'; SYS_OP_DECOMP : 'SYS_OP_DECOMP'; SYS_OP_DESCEND : 'SYS_OP_DESCEND'; SYS_OP_DISTINCT : 'SYS_OP_DISTINCT'; SYS_OP_DRA : 'SYS_OP_DRA'; SYS_OP_DUMP : 'SYS_OP_DUMP'; SYS_OP_DV_CHECK : 'SYS_OP_DV_CHECK'; SYS_OP_ENFORCE_NOT_NULL : 'SYS_OP_ENFORCE_NOT_NULL$'; SYSOPER : 'SYSOPER'; SYS_OP_EXTRACT : 'SYS_OP_EXTRACT'; SYS_OP_GROUPING : 'SYS_OP_GROUPING'; SYS_OP_GUID : 'SYS_OP_GUID'; SYS_OP_HASH : 'SYS_OP_HASH'; SYS_OP_IIX : 'SYS_OP_IIX'; SYS_OP_ITR : 'SYS_OP_ITR'; SYS_OP_KEY_VECTOR_CREATE : 'SYS_OP_KEY_VECTOR_CREATE'; SYS_OP_KEY_VECTOR_FILTER_LIST : 'SYS_OP_KEY_VECTOR_FILTER_LIST'; SYS_OP_KEY_VECTOR_FILTER : 'SYS_OP_KEY_VECTOR_FILTER'; SYS_OP_KEY_VECTOR_SUCCEEDED : 'SYS_OP_KEY_VECTOR_SUCCEEDED'; SYS_OP_KEY_VECTOR_USE : 'SYS_OP_KEY_VECTOR_USE'; SYS_OP_LBID : 'SYS_OP_LBID'; SYS_OP_LOBLOC2BLOB : 'SYS_OP_LOBLOC2BLOB'; SYS_OP_LOBLOC2CLOB : 'SYS_OP_LOBLOC2CLOB'; SYS_OP_LOBLOC2ID : 'SYS_OP_LOBLOC2ID'; SYS_OP_LOBLOC2NCLOB : 'SYS_OP_LOBLOC2NCLOB'; SYS_OP_LOBLOC2TYP : 'SYS_OP_LOBLOC2TYP'; SYS_OP_LSVI : 'SYS_OP_LSVI'; SYS_OP_LVL : 'SYS_OP_LVL'; SYS_OP_MAKEOID : 'SYS_OP_MAKEOID'; SYS_OP_MAP_NONNULL : 'SYS_OP_MAP_NONNULL'; SYS_OP_MSR : 'SYS_OP_MSR'; SYS_OP_NICOMBINE : 'SYS_OP_NICOMBINE'; SYS_OP_NIEXTRACT : 'SYS_OP_NIEXTRACT'; SYS_OP_NII : 'SYS_OP_NII'; SYS_OP_NIX : 'SYS_OP_NIX'; SYS_OP_NOEXPAND : 'SYS_OP_NOEXPAND'; SYS_OP_NTCIMG : 'SYS_OP_NTCIMG$'; SYS_OP_NUMTORAW : 'SYS_OP_NUMTORAW'; SYS_OP_OIDVALUE : 'SYS_OP_OIDVALUE'; SYS_OP_OPNSIZE : 'SYS_OP_OPNSIZE'; SYS_OP_PAR_1 : 'SYS_OP_PAR_1'; SYS_OP_PARGID_1 : 'SYS_OP_PARGID_1'; SYS_OP_PARGID : 'SYS_OP_PARGID'; SYS_OP_PAR : 'SYS_OP_PAR'; SYS_OP_PART_ID : 'SYS_OP_PART_ID'; SYS_OP_PIVOT : 'SYS_OP_PIVOT'; SYS_OP_R2O : 'SYS_OP_R2O'; SYS_OP_RAWTONUM : 'SYS_OP_RAWTONUM'; SYS_OP_RDTM : 'SYS_OP_RDTM'; SYS_OP_REF : 'SYS_OP_REF'; SYS_OP_RMTD : 'SYS_OP_RMTD'; SYS_OP_ROWIDTOOBJ : 'SYS_OP_ROWIDTOOBJ'; SYS_OP_RPB : 'SYS_OP_RPB'; SYS_OPTLOBPRBSC : 'SYS_OPTLOBPRBSC'; SYS_OP_TOSETID : 'SYS_OP_TOSETID'; SYS_OP_TPR : 'SYS_OP_TPR'; SYS_OP_TRTB : 'SYS_OP_TRTB'; SYS_OPTXICMP : 'SYS_OPTXICMP'; SYS_OPTXQCASTASNQ : 'SYS_OPTXQCASTASNQ'; SYS_OP_UNDESCEND : 'SYS_OP_UNDESCEND'; SYS_OP_VECAND : 'SYS_OP_VECAND'; SYS_OP_VECBIT : 'SYS_OP_VECBIT'; SYS_OP_VECOR : 'SYS_OP_VECOR'; SYS_OP_VECXOR : 'SYS_OP_VECXOR'; SYS_OP_VERSION : 'SYS_OP_VERSION'; SYS_OP_VREF : 'SYS_OP_VREF'; SYS_OP_VVD : 'SYS_OP_VVD'; SYS_OP_XMLCONS_FOR_CSX : 'SYS_OP_XMLCONS_FOR_CSX'; SYS_OP_XPTHATG : 'SYS_OP_XPTHATG'; SYS_OP_XPTHIDX : 'SYS_OP_XPTHIDX'; SYS_OP_XPTHOP : 'SYS_OP_XPTHOP'; SYS_OP_XTXT2SQLT : 'SYS_OP_XTXT2SQLT'; SYS_OP_ZONE_ID : 'SYS_OP_ZONE_ID'; SYS_ORDERKEY_DEPTH : 'SYS_ORDERKEY_DEPTH'; SYS_ORDERKEY_MAXCHILD : 'SYS_ORDERKEY_MAXCHILD'; SYS_ORDERKEY_PARENT : 'SYS_ORDERKEY_PARENT'; SYS_PARALLEL_TXN : 'SYS_PARALLEL_TXN'; SYS_PATHID_IS_ATTR : 'SYS_PATHID_IS_ATTR'; SYS_PATHID_IS_NMSPC : 'SYS_PATHID_IS_NMSPC'; SYS_PATHID_LASTNAME : 'SYS_PATHID_LASTNAME'; SYS_PATHID_LASTNMSPC : 'SYS_PATHID_LASTNMSPC'; SYS_PATH_REVERSE : 'SYS_PATH_REVERSE'; SYS_PXQEXTRACT : 'SYS_PXQEXTRACT'; SYS_RAW_TO_XSID : 'SYS_RAW_TO_XSID'; SYS_RID_ORDER : 'SYS_RID_ORDER'; SYS_ROW_DELTA : 'SYS_ROW_DELTA'; SYS_SC_2_XMLT : 'SYS_SC_2_XMLT'; SYS_SYNRCIREDO : 'SYS_SYNRCIREDO'; SYSTEM_DEFINED : 'SYSTEM_DEFINED'; SYSTEM : 'SYSTEM'; SYSTIMESTAMP : 'SYSTIMESTAMP'; SYS_TYPEID : 'SYS_TYPEID'; SYS_UMAKEXML : 'SYS_UMAKEXML'; SYS_XMLANALYZE : 'SYS_XMLANALYZE'; SYS_XMLCONTAINS : 'SYS_XMLCONTAINS'; SYS_XMLCONV : 'SYS_XMLCONV'; SYS_XMLEXNSURI : 'SYS_XMLEXNSURI'; SYS_XMLGEN : 'SYS_XMLGEN'; SYS_XMLI_LOC_ISNODE : 'SYS_XMLI_LOC_ISNODE'; SYS_XMLI_LOC_ISTEXT : 'SYS_XMLI_LOC_ISTEXT'; SYS_XMLINSTR : 'SYS_XMLINSTR'; SYS_XMLLOCATOR_GETSVAL : 'SYS_XMLLOCATOR_GETSVAL'; SYS_XMLNODEID_GETCID : 'SYS_XMLNODEID_GETCID'; SYS_XMLNODEID_GETLOCATOR : 'SYS_XMLNODEID_GETLOCATOR'; SYS_XMLNODEID_GETOKEY : 'SYS_XMLNODEID_GETOKEY'; SYS_XMLNODEID_GETPATHID : 'SYS_XMLNODEID_GETPATHID'; SYS_XMLNODEID_GETPTRID : 'SYS_XMLNODEID_GETPTRID'; SYS_XMLNODEID_GETRID : 'SYS_XMLNODEID_GETRID'; SYS_XMLNODEID_GETSVAL : 'SYS_XMLNODEID_GETSVAL'; SYS_XMLNODEID_GETTID : 'SYS_XMLNODEID_GETTID'; SYS_XMLNODEID : 'SYS_XMLNODEID'; SYS_XMLT_2_SC : 'SYS_XMLT_2_SC'; SYS_XMLTRANSLATE : 'SYS_XMLTRANSLATE'; SYS_XMLTYPE2SQL : 'SYS_XMLTYPE2SQL'; SYS_XQ_ASQLCNV : 'SYS_XQ_ASQLCNV'; SYS_XQ_ATOMCNVCHK : 'SYS_XQ_ATOMCNVCHK'; SYS_XQBASEURI : 'SYS_XQBASEURI'; SYS_XQCASTABLEERRH : 'SYS_XQCASTABLEERRH'; SYS_XQCODEP2STR : 'SYS_XQCODEP2STR'; SYS_XQCODEPEQ : 'SYS_XQCODEPEQ'; SYS_XQCON2SEQ : 'SYS_XQCON2SEQ'; SYS_XQCONCAT : 'SYS_XQCONCAT'; SYS_XQDELETE : 'SYS_XQDELETE'; SYS_XQDFLTCOLATION : 'SYS_XQDFLTCOLATION'; SYS_XQDOC : 'SYS_XQDOC'; SYS_XQDOCURI : 'SYS_XQDOCURI'; SYS_XQDURDIV : 'SYS_XQDURDIV'; SYS_XQED4URI : 'SYS_XQED4URI'; SYS_XQENDSWITH : 'SYS_XQENDSWITH'; SYS_XQERRH : 'SYS_XQERRH'; SYS_XQERR : 'SYS_XQERR'; SYS_XQESHTMLURI : 'SYS_XQESHTMLURI'; SYS_XQEXLOBVAL : 'SYS_XQEXLOBVAL'; SYS_XQEXSTWRP : 'SYS_XQEXSTWRP'; SYS_XQEXTRACT : 'SYS_XQEXTRACT'; SYS_XQEXTRREF : 'SYS_XQEXTRREF'; SYS_XQEXVAL : 'SYS_XQEXVAL'; SYS_XQFB2STR : 'SYS_XQFB2STR'; SYS_XQFNBOOL : 'SYS_XQFNBOOL'; SYS_XQFNCMP : 'SYS_XQFNCMP'; SYS_XQFNDATIM : 'SYS_XQFNDATIM'; SYS_XQFNLNAME : 'SYS_XQFNLNAME'; SYS_XQFNNM : 'SYS_XQFNNM'; SYS_XQFNNSURI : 'SYS_XQFNNSURI'; SYS_XQFNPREDTRUTH : 'SYS_XQFNPREDTRUTH'; SYS_XQFNQNM : 'SYS_XQFNQNM'; SYS_XQFNROOT : 'SYS_XQFNROOT'; SYS_XQFORMATNUM : 'SYS_XQFORMATNUM'; SYS_XQFTCONTAIN : 'SYS_XQFTCONTAIN'; SYS_XQFUNCR : 'SYS_XQFUNCR'; SYS_XQGETCONTENT : 'SYS_XQGETCONTENT'; SYS_XQINDXOF : 'SYS_XQINDXOF'; SYS_XQINSERT : 'SYS_XQINSERT'; SYS_XQINSPFX : 'SYS_XQINSPFX'; SYS_XQIRI2URI : 'SYS_XQIRI2URI'; SYS_XQLANG : 'SYS_XQLANG'; SYS_XQLLNMFRMQNM : 'SYS_XQLLNMFRMQNM'; SYS_XQMKNODEREF : 'SYS_XQMKNODEREF'; SYS_XQNILLED : 'SYS_XQNILLED'; SYS_XQNODENAME : 'SYS_XQNODENAME'; SYS_XQNORMSPACE : 'SYS_XQNORMSPACE'; SYS_XQNORMUCODE : 'SYS_XQNORMUCODE'; SYS_XQ_NRNG : 'SYS_XQ_NRNG'; SYS_XQNSP4PFX : 'SYS_XQNSP4PFX'; SYS_XQNSPFRMQNM : 'SYS_XQNSPFRMQNM'; SYS_XQPFXFRMQNM : 'SYS_XQPFXFRMQNM'; SYS_XQ_PKSQL2XML : 'SYS_XQ_PKSQL2XML'; SYS_XQPOLYABS : 'SYS_XQPOLYABS'; SYS_XQPOLYADD : 'SYS_XQPOLYADD'; SYS_XQPOLYCEL : 'SYS_XQPOLYCEL'; SYS_XQPOLYCSTBL : 'SYS_XQPOLYCSTBL'; SYS_XQPOLYCST : 'SYS_XQPOLYCST'; SYS_XQPOLYDIV : 'SYS_XQPOLYDIV'; SYS_XQPOLYFLR : 'SYS_XQPOLYFLR'; SYS_XQPOLYMOD : 'SYS_XQPOLYMOD'; SYS_XQPOLYMUL : 'SYS_XQPOLYMUL'; SYS_XQPOLYRND : 'SYS_XQPOLYRND'; SYS_XQPOLYSQRT : 'SYS_XQPOLYSQRT'; SYS_XQPOLYSUB : 'SYS_XQPOLYSUB'; SYS_XQPOLYUMUS : 'SYS_XQPOLYUMUS'; SYS_XQPOLYUPLS : 'SYS_XQPOLYUPLS'; SYS_XQPOLYVEQ : 'SYS_XQPOLYVEQ'; SYS_XQPOLYVGE : 'SYS_XQPOLYVGE'; SYS_XQPOLYVGT : 'SYS_XQPOLYVGT'; SYS_XQPOLYVLE : 'SYS_XQPOLYVLE'; SYS_XQPOLYVLT : 'SYS_XQPOLYVLT'; SYS_XQPOLYVNE : 'SYS_XQPOLYVNE'; SYS_XQREF2VAL : 'SYS_XQREF2VAL'; SYS_XQRENAME : 'SYS_XQRENAME'; SYS_XQREPLACE : 'SYS_XQREPLACE'; SYS_XQRESVURI : 'SYS_XQRESVURI'; SYS_XQRNDHALF2EVN : 'SYS_XQRNDHALF2EVN'; SYS_XQRSLVQNM : 'SYS_XQRSLVQNM'; SYS_XQRYENVPGET : 'SYS_XQRYENVPGET'; SYS_XQRYVARGET : 'SYS_XQRYVARGET'; SYS_XQRYWRP : 'SYS_XQRYWRP'; SYS_XQSEQ2CON4XC : 'SYS_XQSEQ2CON4XC'; SYS_XQSEQ2CON : 'SYS_XQSEQ2CON'; SYS_XQSEQDEEPEQ : 'SYS_XQSEQDEEPEQ'; SYS_XQSEQINSB : 'SYS_XQSEQINSB'; SYS_XQSEQRM : 'SYS_XQSEQRM'; SYS_XQSEQRVS : 'SYS_XQSEQRVS'; SYS_XQSEQSUB : 'SYS_XQSEQSUB'; SYS_XQSEQTYPMATCH : 'SYS_XQSEQTYPMATCH'; SYS_XQSTARTSWITH : 'SYS_XQSTARTSWITH'; SYS_XQSTATBURI : 'SYS_XQSTATBURI'; SYS_XQSTR2CODEP : 'SYS_XQSTR2CODEP'; SYS_XQSTRJOIN : 'SYS_XQSTRJOIN'; SYS_XQSUBSTRAFT : 'SYS_XQSUBSTRAFT'; SYS_XQSUBSTRBEF : 'SYS_XQSUBSTRBEF'; SYS_XQTOKENIZE : 'SYS_XQTOKENIZE'; SYS_XQTREATAS : 'SYS_XQTREATAS'; SYS_XQ_UPKXML2SQL : 'SYS_XQ_UPKXML2SQL'; SYS_XQXFORM : 'SYS_XQXFORM'; SYS_XSID_TO_RAW : 'SYS_XSID_TO_RAW'; SYS_ZMAP_FILTER : 'SYS_ZMAP_FILTER'; SYS_ZMAP_REFRESH : 'SYS_ZMAP_REFRESH'; T_LETTER : 'T'; TABLE_LOOKUP_BY_NL : 'TABLE_LOOKUP_BY_NL'; TABLESPACE_NO : 'TABLESPACE_NO'; TABLESPACE : 'TABLESPACE'; TABLES : 'TABLES'; TABLE_STATS : 'TABLE_STATS'; TABLE : 'TABLE'; TABNO : 'TABNO'; TAG : 'TAG'; TANH : 'TANH'; TAN : 'TAN'; TBLORIDXPARTNUM : 'TBL$OR$IDX$PART$NUM'; TEMPFILE : 'TEMPFILE'; TEMPLATE : 'TEMPLATE'; TEMPLATE_TABLE : 'TEMPLATE_TABLE'; TEMPORARY : 'TEMPORARY'; TEMP_TABLE : 'TEMP_TABLE'; TERMINATED : 'TERMINATED'; TEST : 'TEST'; TEXT : 'TEXT'; TEXTFILE : 'TEXTFILE'; THAN : 'THAN'; THEN : 'THEN'; THE : 'THE'; THESE : 'THESE'; THREAD : 'THREAD'; THROUGH : 'THROUGH'; TIER : 'TIER'; TIES : 'TIES'; TIMEOUT : 'TIMEOUT'; TIMESTAMP_LTZ_UNCONSTRAINED : 'TIMESTAMP_LTZ_UNCONSTRAINED'; TIMESTAMP : 'TIMESTAMP'; TIMESTAMP_TZ_UNCONSTRAINED : 'TIMESTAMP_TZ_UNCONSTRAINED'; TIMESTAMP_UNCONSTRAINED : 'TIMESTAMP_UNCONSTRAINED'; TIMES : 'TIMES'; TIME : 'TIME'; TIMEZONE : 'TIMEZONE'; TIMEZONE_ABBR : 'TIMEZONE_ABBR'; TIMEZONE_HOUR : 'TIMEZONE_HOUR'; TIMEZONE_MINUTE : 'TIMEZONE_MINUTE'; TIMEZONE_OFFSET : 'TIMEZONE_OFFSET'; TIMEZONE_REGION : 'TIMEZONE_REGION'; TIME_ZONE : 'TIME_ZONE'; TIMING : 'TIMING'; TINYINT : 'TINYINT'; TIV_GB : 'TIV_GB'; TIV_SSF : 'TIV_SSF'; TO_ACLID : 'TO_ACLID'; TO_BINARY_DOUBLE : 'TO_BINARY_DOUBLE'; TO_BINARY_FLOAT : 'TO_BINARY_FLOAT'; TO_BLOB : 'TO_BLOB'; TO_CLOB : 'TO_CLOB'; TO_DSINTERVAL : 'TO_DSINTERVAL'; TO_LOB : 'TO_LOB'; TO_MULTI_BYTE : 'TO_MULTI_BYTE'; TO_NCHAR : 'TO_NCHAR'; TO_NCLOB : 'TO_NCLOB'; TO_NUMBER : 'TO_NUMBER'; TOPLEVEL : 'TOPLEVEL'; TO_SINGLE_BYTE : 'TO_SINGLE_BYTE'; TO_TIMESTAMP : 'TO_TIMESTAMP'; TO_TIMESTAMP_TZ : 'TO_TIMESTAMP_TZ'; TO_TIME : 'TO_TIME'; TO_TIME_TZ : 'TO_TIME_TZ'; TO : 'TO'; TO_YMINTERVAL : 'TO_YMINTERVAL'; TRACE : 'TRACE'; TRACING : 'TRACING'; TRACKING : 'TRACKING'; TRAILING : 'TRAILING'; TRANSACTION : 'TRANSACTION'; TRANSFORM : 'TRANSFORM'; TRANSFORMS : 'TRANSFORMS'; TRANSFORM_DISTINCT_AGG : 'TRANSFORM_DISTINCT_AGG'; TRANSITIONAL : 'TRANSITIONAL'; TRANSITION : 'TRANSITION'; TRANSLATE : 'TRANSLATE'; TRANSLATION : 'TRANSLATION'; TREAT : 'TREAT'; TRIGGERS : 'TRIGGERS'; TRIGGER : 'TRIGGER'; TRUE : 'TRUE'; TRUNCATE : 'TRUNCATE'; TRUNC : 'TRUNC'; TRUSTED : 'TRUSTED'; TRUST : 'TRUST'; TUNING : 'TUNING'; TX : 'TX'; TYPES : 'TYPES'; TYPE : 'TYPE'; TZ_OFFSET : 'TZ_OFFSET'; UB2 : 'UB2'; UBA : 'UBA'; UCS2 : 'UCS2'; UDF : 'UDF'; UID : 'UID'; UNARCHIVED : 'UNARCHIVED'; UNBOUNDED : 'UNBOUNDED'; UNBOUND : 'UNBOUND'; UNCONDITIONAL : 'UNCONDITIONAL'; UNDER : 'UNDER'; UNDO : 'UNDO'; UNDROP : 'UNDROP'; UNIFORM : 'UNIFORM'; UNION : 'UNION'; UNIONTYPE : 'UNIONTYPE'; UNIQUE : 'UNIQUE'; UNISTR : 'UNISTR'; UNLIMITED : 'UNLIMITED'; UNLOAD : 'UNLOAD'; UNLOCK : 'UNLOCK'; UNMATCHED : 'UNMATCHED'; UNNEST_INNERJ_DISTINCT_VIEW : 'UNNEST_INNERJ_DISTINCT_VIEW'; UNNEST_NOSEMIJ_NODISTINCTVIEW : 'UNNEST_NOSEMIJ_NODISTINCTVIEW'; UNNEST_SEMIJ_VIEW : 'UNNEST_SEMIJ_VIEW'; UNNEST : 'UNNEST'; UNPACKED : 'UNPACKED'; UNPIVOT : 'UNPIVOT'; UNPLUG : 'UNPLUG'; UNPROTECTED : 'UNPROTECTED'; UNQUIESCE : 'UNQUIESCE'; UNRECOVERABLE : 'UNRECOVERABLE'; UNRESTRICTED : 'UNRESTRICTED'; UNSIGNED : 'UNSIGNED'; UNSUBSCRIBE : 'UNSUBSCRIBE'; UNTIL : 'UNTIL'; UNUSABLE : 'UNUSABLE'; UNUSED : 'UNUSED'; UPDATABLE : 'UPDATABLE'; UPDATED : 'UPDATED'; UPDATE : 'UPDATE'; UPDATEXML : 'UPDATEXML'; UPD_INDEXES : 'UPD_INDEXES'; UPD_JOININDEX : 'UPD_JOININDEX'; UPGRADE : 'UPGRADE'; UPPER : 'UPPER'; UPSERT : 'UPSERT'; UROWID : 'UROWID'; USABLE : 'USABLE'; USAGE : 'USAGE'; USE_ANTI : 'USE_ANTI'; USE_CONCAT : 'USE_CONCAT'; USE_CUBE : 'USE_CUBE'; USE_HASH_AGGREGATION : 'USE_HASH_AGGREGATION'; USE_HASH_GBY_FOR_PUSHDOWN : 'USE_HASH_GBY_FOR_PUSHDOWN'; USE_HASH : 'USE_HASH'; USE_HIDDEN_PARTITIONS : 'USE_HIDDEN_PARTITIONS'; USE_INVISIBLE_INDEXES : 'USE_INVISIBLE_INDEXES'; USE_MERGE_CARTESIAN : 'USE_MERGE_CARTESIAN'; USE_MERGE : 'USE_MERGE'; USE_NL : 'USE_NL'; USE_NL_WITH_INDEX : 'USE_NL_WITH_INDEX'; USE_PRIVATE_OUTLINES : 'USE_PRIVATE_OUTLINES'; USER_DATA : 'USER_DATA'; USER_DEFINED : 'USER_DEFINED'; USERENV : 'USERENV'; USERGROUP : 'USERGROUP'; USER_RECYCLEBIN : 'USER_RECYCLEBIN'; USERS : 'USERS'; USER_TABLESPACES : 'USER_TABLESPACES'; USER : 'USER'; USE_SEMI : 'USE_SEMI'; USE_STORED_OUTLINES : 'USE_STORED_OUTLINES'; USE_TTT_FOR_GSETS : 'USE_TTT_FOR_GSETS'; USE : 'USE'; USE_VECTOR_AGGREGATION : 'USE_VECTOR_AGGREGATION'; USE_WEAK_NAME_RESL : 'USE_WEAK_NAME_RESL'; USING_NO_EXPAND : 'USING_NO_EXPAND'; USING_NLS_COMP : 'USING_NLS_COMP'; USING : 'USING'; UTF16BE : 'UTF16BE'; UTF16LE : 'UTF16LE'; UTF32 : 'UTF32'; UTF8 : 'UTF8'; V1 : 'V1'; V2 : 'V2'; VALIDATE : 'VALIDATE'; VALIDATE_CONVERSION : 'VALIDATE_CONVERSION'; VALIDATION : 'VALIDATION'; VALID_TIME_END : 'VALID_TIME_END'; VALUES : 'VALUES'; VALUE : 'VALUE'; VARCHAR2 : 'VARCHAR2'; VARCHAR : 'VARCHAR'; VARCHARC : 'VARCHARC'; VARIABLE : 'VARIABLE'; VARRAW : 'VARRAW'; VARRAWC : 'VARRAWC'; VAR_POP : 'VAR_POP'; VARRAYS : 'VARRAYS'; VARRAY : 'VARRAY'; VAR_SAMP : 'VAR_SAMP'; VARYING : 'VARYING'; VECTOR_READ_TRACE : 'VECTOR_READ_TRACE'; VECTOR_READ : 'VECTOR_READ'; VECTOR_TRANSFORM_DIMS : 'VECTOR_TRANSFORM_DIMS'; VECTOR_TRANSFORM_FACT : 'VECTOR_TRANSFORM_FACT'; VECTOR_TRANSFORM : 'VECTOR_TRANSFORM'; VERIFIER : 'VERIFIER'; VERIFY : 'VERIFY'; VERSIONING : 'VERSIONING'; VERSIONS_ENDSCN : 'VERSIONS_ENDSCN'; VERSIONS_ENDTIME : 'VERSIONS_ENDTIME'; VERSIONS_OPERATION : 'VERSIONS_OPERATION'; VERSIONS_STARTSCN : 'VERSIONS_STARTSCN'; VERSIONS_STARTTIME : 'VERSIONS_STARTTIME'; VERSIONS : 'VERSIONS'; VERSIONS_XID : 'VERSIONS_XID'; VERSION : 'VERSION'; VIEW : 'VIEW'; VIOLATION : 'VIOLATION'; VIRTUAL : 'VIRTUAL'; VISIBILITY : 'VISIBILITY'; VISIBLE : 'VISIBLE'; VOLUME : 'VOLUME'; VSIZE : 'VSIZE'; WAIT : 'WAIT'; WALLET : 'WALLET'; WARNING : 'WARNING'; WEEKS : 'WEEKS'; WEEK : 'WEEK'; WELLFORMED : 'WELLFORMED'; WHENEVER : 'WHENEVER'; WHEN : 'WHEN'; WHERE : 'WHERE'; WHILE : 'WHILE'; WHITESPACE : 'WHITESPACE'; WIDTH_BUCKET : 'WIDTH_BUCKET'; WITHIN : 'WITHIN'; WITHOUT : 'WITHOUT'; WITH_PLSQL : 'WITH_PLSQL'; WITH : 'WITH'; WORK : 'WORK'; WORKERID : 'WORKERID'; WRAPPED : 'WRAPPED'; WRAPPER : 'WRAPPER'; WRITE : 'WRITE'; XDB_FASTPATH_INSERT : 'XDB_FASTPATH_INSERT'; XDB : 'XDB'; X_DYN_PRUNE : 'X_DYN_PRUNE'; XID : 'XID'; XML2OBJECT : 'XML2OBJECT'; XMLAGG : 'XMLAGG'; XMLATTRIBUTES : 'XMLATTRIBUTES'; XMLCAST : 'XMLCAST'; XMLCDATA : 'XMLCDATA'; XMLCOLATTVAL : 'XMLCOLATTVAL'; XMLCOMMENT : 'XMLCOMMENT'; XMLCONCAT : 'XMLCONCAT'; XMLDIFF : 'XMLDIFF'; XML_DML_RWT_STMT : 'XML_DML_RWT_STMT'; XMLELEMENT : 'XMLELEMENT'; XMLEXISTS2 : 'XMLEXISTS2'; XMLEXISTS : 'XMLEXISTS'; XMLFOREST : 'XMLFOREST'; XMLINDEX : 'XMLINDEX'; XMLINDEX_REWRITE_IN_SELECT : 'XMLINDEX_REWRITE_IN_SELECT'; XMLINDEX_REWRITE : 'XMLINDEX_REWRITE'; XMLINDEX_SEL_IDX_TBL : 'XMLINDEX_SEL_IDX_TBL'; XMLISNODE : 'XMLISNODE'; XMLISVALID : 'XMLISVALID'; XMLNAMESPACES : 'XMLNAMESPACES'; XMLPARSE : 'XMLPARSE'; XMLPATCH : 'XMLPATCH'; XMLPI : 'XMLPI'; XMLQUERYVAL : 'XMLQUERYVAL'; XMLQUERY : 'XMLQUERY'; XMLROOT : 'XMLROOT'; XMLSCHEMA : 'XMLSCHEMA'; XMLSERIALIZE : 'XMLSERIALIZE'; XMLTABLE : 'XMLTABLE'; XMLTAG : 'XMLTAG'; XMLTRANSFORMBLOB : 'XMLTRANSFORMBLOB'; XMLTRANSFORM : 'XMLTRANSFORM'; XMLTYPE : 'XMLTYPE'; XML : 'XML'; XPATHTABLE : 'XPATHTABLE'; XS_SYS_CONTEXT : 'XS_SYS_CONTEXT'; XS : 'XS'; XTRANSPORT : 'XTRANSPORT'; YEARS : 'YEARS'; YEAR : 'YEAR'; YEAR_TO_MONTH : 'YEAR_TO_MONTH'; YES : 'YES'; YMINTERVAL_UNCONSTRAINED : 'YMINTERVAL_UNCONSTRAINED'; ZONEMAP : 'ZONEMAP'; ZONE : 'ZONE'; ZONED : 'ZONED'; PREDICTION : 'PREDICTION'; PREDICTION_BOUNDS : 'PREDICTION_BOUNDS'; PREDICTION_COST : 'PREDICTION_COST'; PREDICTION_DETAILS : 'PREDICTION_DETAILS'; PREDICTION_PROBABILITY : 'PREDICTION_PROBABILITY'; PREDICTION_SET : 'PREDICTION_SET'; BLOCKCHAIN : 'BLOCKCHAIN'; COLLATE : 'COLLATE'; COLLATION : 'COLLATION'; DEFINITION : 'DEFINITION'; DUPLICATED : 'DUPLICATED'; EXTENDED : 'EXTENDED'; HASHING : 'HASHING'; IDLE : 'IDLE'; IMMUTABLE : 'IMMUTABLE'; ORACLE_DATAPUMP : 'ORACLE_DATAPUMP'; ORACLE_HDFS : 'ORACLE_HDFS'; ORACLE_HIVE : 'ORACLE_HIVE'; ORACLE_LOADER : 'ORACLE_LOADER'; SHA2_512_Q : '"SHA2_512"'; SHARDED : 'SHARDED'; V1_Q : '"V1"'; ISOLATE : 'ISOLATE'; ROOT : 'ROOT'; UNITE : 'UNITE'; ALGORITHM : 'ALGORITHM'; CUME_DIST : 'CUME_DIST'; DENSE_RANK : 'DENSE_RANK'; LISTAGG : 'LISTAGG'; PERCENT_RANK : 'PERCENT_RANK'; PERCENTILE_CONT : 'PERCENTILE_CONT'; PERCENTILE_DISC : 'PERCENTILE_DISC'; RANK : 'RANK'; AVG : 'AVG'; CORR : 'CORR'; COVAR_ : 'COVAR_'; DECODE : 'DECODE'; LAG : 'LAG'; LAG_DIFF : 'LAG_DIFF'; LAG_DIFF_PERCENT : 'LAG_DIFF_PERCENT'; LEAD : 'LEAD'; MAX : 'MAX'; MEDIAN : 'MEDIAN'; MEMOPTIMIZE : 'MEMOPTIMIZE'; MIN : 'MIN'; NTILE : 'NTILE'; NVL : 'NVL'; RATIO_TO_REPORT : 'RATIO_TO_REPORT'; REGR_ : 'REGR_'; ROUND : 'ROUND'; ROW_NUMBER : 'ROW_NUMBER'; SUBSTR : 'SUBSTR'; TO_CHAR : 'TO_CHAR'; TRIM : 'TRIM'; SUM : 'SUM'; STDDEV : 'STDDEV'; VAR_ : 'VAR_'; VARIANCE : 'VARIANCE'; LEAST : 'LEAST'; GREATEST : 'GREATEST'; TO_DATE : 'TO_DATE'; CHARSETID : 'CHARSETID'; CHARSETFORM : 'CHARSETFORM'; DURATION : 'DURATION'; EXTEND : 'EXTEND'; MAXLEN : 'MAXLEN'; PERSISTABLE : 'PERSISTABLE'; POLYMORPHIC : 'POLYMORPHIC'; STRUCT : 'STRUCT'; TDO : 'TDO'; WM_CONCAT : 'WM_CONCAT'; // Rule #358 - subtoken typecast in , it also incorporates // Lowercase 'n' is a usual addition to the standard NATIONAL_CHAR_STRING_LIT: 'N' '\'' (~('\'' | '\r' | '\n') | '\'' '\'' | NEWLINE)* '\''; // Rule #040 - subtoken typecast in // Lowercase 'b' is a usual addition to the standard BIT_STRING_LIT: 'B' ('\'' [01]* '\'')+; // Rule #284 - subtoken typecast in // Lowercase 'x' is a usual addition to the standard // The '0X' is used in external_table_clause sub-rules HEX_STRING_LIT : ('X' | '0X') ('\'' [A-F0-9]* '\'')+; DOUBLE_PERIOD : '..'; PERIOD : '.'; //{ Rule #238 // This rule is a bit tricky - it resolves the ambiguity with // It also incorporates and for the // Rule #501 was incorporated directly in the token // See also the rule #617 /* : ( UNSIGNED_INTEGER ( '.' UNSIGNED_INTEGER | {$type = UNSIGNED_INTEGER;} ) ( E ('+' | '-')? UNSIGNED_INTEGER {$type = APPROXIMATE_NUM_LIT;} )? | '.' UNSIGNED_INTEGER ( E ('+' | '-')? UNSIGNED_INTEGER {$type = APPROXIMATE_NUM_LIT;} )? ) (D | F)? ;*/ UNSIGNED_INTEGER : [0-9]+; APPROXIMATE_NUM_LIT : FLOAT_FRAGMENT ('E' ('+' | '-')? (FLOAT_FRAGMENT | [0-9]+))? ('D' | 'F')?; // Rule #--- is a base for Rule #065 , it incorporates // and a superfluous subtoken typecasting of the "QUOTE" CHAR_STRING: '\'' (~('\'' | '\r' | '\n') | '\'' '\'' | NEWLINE)* '\''; // See https://livesql.oracle.com/apex/livesql/file/content_CIREYU9EA54EOKQ7LAMZKRF6P.html // TODO: context sensitive string quotes (any characted after quote) CHAR_STRING_PERL: 'Q' '\'' ( QS_ANGLE | QS_BRACE | QS_BRACK | QS_PAREN | QS_EXCLAM | QS_SHARP | QS_QUOTE | QS_DQUOTE | QS_TILDA | QS_SOLIDUS | QS_RSOLIDUS ) '\'' -> type(CHAR_STRING) ; fragment QS_ANGLE : '<' .*? '>'; fragment QS_BRACE : '{' .*? '}'; fragment QS_BRACK : '[' .*? ']'; fragment QS_PAREN : '(' .*? ')'; fragment QS_EXCLAM : '!' .*? '!'; fragment QS_SHARP : '#' .*? '#'; fragment QS_QUOTE : '\'' .*? '\''; fragment QS_DQUOTE : '"' .*? '"'; fragment QS_TILDA : '~' .*? '~'; fragment QS_SOLIDUS : '/' .*? '/'; fragment QS_RSOLIDUS : '\\' .*? '\\'; DELIMITED_ID: '"' (~ [\u0000"] | '"' '"')+ '"'; PERCENT : '%'; AMPERSAND : '&'; LEFT_PAREN : '('; RIGHT_PAREN : ')'; DOUBLE_ASTERISK : '**'; ASTERISK : '*'; PLUS_SIGN : '+'; MINUS_SIGN : '-'; COMMA : ','; SOLIDUS : '/'; AT_SIGN : '@'; ASSIGN_OP : ':='; HASH_OP : '#'; LEFT_CURLY_PAREN : '{'; RIGHT_CURLY_PAREN : '}'; SQ: '\''; BINDVAR: ':' SIMPLE_LETTER (SIMPLE_LETTER | [0-9] | '_')* | ':' DELIMITED_ID // not used in SQL but spotted in v$sqltext when using cursor_sharing | ':' UNSIGNED_INTEGER | QUESTION_MARK // not in SQL, not in Oracle, not in OCI, use this for JDBC ; NOT_EQUAL_OP : '!=' | '<>' | '^=' | '~='; CARRET_OPERATOR_PART : '^'; TILDE_OPERATOR_PART : '~'; EXCLAMATION_OPERATOR_PART : '!'; GREATER_THAN_OP : '>'; LESS_THAN_OP : '<'; COLON : ':'; SEMICOLON : ';'; BAR : '|'; EQUALS_OP : '='; LEFT_BRACKET : '['; RIGHT_BRACKET : ']'; INTRODUCER: '_'; // Comments https://docs.oracle.com/cd/E11882_01/server.112/e41084/sql_elements006.htm SINGLE_LINE_COMMENT : '--' ~('\r' | '\n')* NEWLINE_EOF -> channel(HIDDEN); MULTI_LINE_COMMENT : '/*' .*? '*/' -> channel(HIDDEN); // https://docs.oracle.com/cd/E11882_01/server.112/e16604/ch_twelve034.htm#SQPUG054 REMARK_COMMENT: 'REM' {this.IsNewlineAtPos(-4)}? 'ARK'? (' ' ~('\r' | '\n')*)? NEWLINE_EOF -> channel(HIDDEN) ; // https://docs.oracle.com/cd/E11882_01/server.112/e16604/ch_twelve032.htm#SQPUG052 PROMPT_MESSAGE: 'PRO' {this.IsNewlineAtPos(-4)}? 'MPT'? (' ' ~('\r' | '\n')*)? NEWLINE_EOF; // TODO: should starts with newline START_CMD: // https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12002.htm '@' '@'? ; // https://docs.oracle.com/cd/B19306_01/server.102/b14357/ch12003.htm REGULAR_ID: SIMPLE_LETTER (SIMPLE_LETTER | '$' | '_' | '#' | [0-9])*; INQUIRY_DIRECTIVE: '$$' (SIMPLE_LETTER | '_')+; SPACES: [ \t\r\n]+ -> channel(HIDDEN); // Fragment rules fragment NEWLINE_EOF : NEWLINE | EOF; fragment QUESTION_MARK : '?'; fragment SIMPLE_LETTER : [\p{Letter}]; fragment FLOAT_FRAGMENT : UNSIGNED_INTEGER* '.'? UNSIGNED_INTEGER+; fragment NEWLINE : '\r'? '\n'; fragment SPACE : [ \t]; ================================================ FILE: superior-oracle-parser/src/main/antlr4/io/github/melin/superior/parser/oracle/antlr4/OracleParser.g4 ================================================ /** * Oracle(c) PL/SQL 11g Parser * * Copyright (c) 2009-2011 Alexandre Porcelli * Copyright (c) 2015-2019 Ivan Kochurkin (KvanTTT, kvanttt@gmail.com, Positive Technologies). * Copyright (c) 2017-2018 Mark Adams * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ parser grammar OracleParser; options { tokenVocab=OracleLexer; superClass=OracleParserBase; } sql_script : (sql_plus_command SEMICOLON?)* ( (sql_plus_command | unit_statement) (SEMICOLON '/'? (sql_plus_command | unit_statement))* SEMICOLON? '/'? ) EOF ; unit_statement : alter_analytic_view | alter_attribute_dimension | alter_audit_policy | alter_cluster | alter_database | alter_database_link | alter_dimension | alter_diskgroup | alter_flashback_archive | alter_function | alter_hierarchy | alter_index | alter_inmemory_join_group | alter_java | alter_library | alter_lockdown_profile | alter_materialized_view | alter_materialized_view_log | alter_materialized_zonemap | alter_operator | alter_outline | alter_package | alter_pmem_filestore | alter_procedure | alter_resource_cost | alter_role | alter_rollback_segment | alter_sequence | alter_session | alter_synonym | alter_table | alter_tablespace | alter_tablespace_set | alter_trigger | alter_type | alter_user | alter_view | anonymous_block | call_statement | create_analytic_view | create_attribute_dimension | create_audit_policy | create_cluster | create_context | create_controlfile | create_schema | create_database | create_database_link | create_dimension | create_directory | create_diskgroup | create_edition | create_flashback_archive | create_function_body | create_hierarchy | create_index | create_inmemory_join_group | create_java | create_library | create_lockdown_profile | create_materialized_view | create_materialized_view_log | create_materialized_zonemap | create_operator | create_outline | create_package | create_package_body | create_pmem_filestore | create_procedure_body | create_profile | create_restore_point | create_role | create_rollback_segment | create_sequence | create_spfile | create_synonym | create_table | create_tablespace | create_tablespace_set | create_trigger | create_type | create_user | create_view | drop_analytic_view | drop_attribute_dimension | drop_audit_policy | drop_cluster | drop_context | drop_database | drop_database_link | drop_directory | drop_diskgroup | drop_edition | drop_flashback_archive | drop_function | drop_hierarchy | drop_index | drop_indextype | drop_inmemory_join_group | drop_java | drop_library | drop_lockdown_profile | drop_materialized_view | drop_materialized_view_log | drop_materialized_zonemap | drop_operator | drop_outline | drop_package | drop_pmem_filestore | drop_procedure | drop_restore_point | drop_role | drop_rollback_segment | drop_sequence | drop_synonym | drop_table | drop_tablespace | drop_tablespace_set | drop_trigger | drop_type | drop_user | drop_view | administer_key_management | analyze | associate_statistics | audit_traditional | comment_on_column | comment_on_materialized | comment_on_table | data_manipulation_language_statements | disassociate_statistics | flashback_table | grant_statement | noaudit_statement | purge_statement | rename_object | revoke_statement | transaction_control_statements | truncate_cluster | truncate_table | unified_auditing ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-DISKGROUP.html alter_diskgroup : ALTER DISKGROUP ( id_expression ( ((add_disk_clause | drop_disk_clause)+ | resize_disk_clause) rebalance_diskgroup_clause? | ( replace_disk_clause | rename_disk_clause | disk_online_clause | disk_offline_clause | rebalance_diskgroup_clause | check_diskgroup_clause | diskgroup_template_clauses | diskgroup_directory_clauses | diskgroup_alias_clauses | diskgroup_volume_clauses | diskgroup_attributes | drop_diskgroup_file_clause | convert_redundancy_clause | usergroup_clauses | user_clauses | file_permissions_clause | file_owner_clause | scrub_clause | quotagroup_clauses | filegroup_clauses ) ) | (id_expression (',' id_expression)* | ALL) ( undrop_disk_clause | diskgroup_availability | enable_disable_volume ) ) ; add_disk_clause : ADD ( (SITE sn = id_expression)? quorum_regular? (FAILGROUP fgn = id_expression)? DISK qualified_disk_clause ( ',' qualified_disk_clause )* )+ ; drop_disk_clause : DROP ( quorum_regular? DISK id_expression force_noforce? (',' id_expression force_noforce?)* | DISKS IN quorum_regular? FAILGROUP id_expression force_noforce? ( ',' id_expression force_noforce? )* ) ; resize_disk_clause : RESIZE ALL (SIZE size_clause)? ; replace_disk_clause : REPLACE DISK id_expression WITH CHAR_STRING force_noforce? ( ',' id_expression WITH CHAR_STRING force_noforce? )* (POWER numeric)? wait_nowait? ; wait_nowait : WAIT | NOWAIT ; rename_disk_clause : RENAME ( DISK id_expression TO id_expression (',' id_expression TO id_expression)* | DISKS ALL ) ; disk_online_clause : ONLINE ( ( quorum_regular? DISK id_expression (',' id_expression)* | DISKS IN quorum_regular? FAILGROUP id_expression (',' id_expression)* )+ | ALL ) (POWER numeric)? wait_nowait? ; disk_offline_clause : OFFLINE ( quorum_regular? DISK id_expression (',' id_expression)* | DISKS IN quorum_regular? FAILGROUP id_expression (',' id_expression)* ) timeout_clause? ; timeout_clause : DROP AFTER numeric (M_LETTER | H_LETTER) ; rebalance_diskgroup_clause : REBALANCE ( ((WITH | WITHOUT) phase+)? (POWER numeric) (WAIT | NOWAIT)? | MODIFY POWER numeric? ) ; phase : id_expression //TODO ; check_diskgroup_clause : CHECK ALL? (REPAIR | NOREPAIR)? //inconsistent documentation ; diskgroup_template_clauses : (ADD | MODIFY) TEMPLATE id_expression qualified_template_clause ( ',' id_expression qualified_template_clause )* | DROP TEMPLATE id_expression (',' id_expression)* ; qualified_template_clause : ATTRIBUTES '(' redundancy_clause? striping_clause? ')' //inconsistent documentation ; redundancy_clause : MIRROR | HIGH | UNPROTECTED | PARITY | DOUBLE ; striping_clause : FINE | COARSE ; force_noforce : FORCE | NOFORCE ; diskgroup_directory_clauses : ADD DIRECTORY filename (',' filename)* | DROP DIRECTORY filename force_noforce? (',' filename force_noforce?)* | RENAME DIRECTORY dir_name TO dir_name (',' dir_name TO dir_name)* ; dir_name : CHAR_STRING ; diskgroup_alias_clauses : ADD ALIAS CHAR_STRING FOR CHAR_STRING (',' CHAR_STRING FOR CHAR_STRING)* | DROP ALIAS CHAR_STRING (',' CHAR_STRING)* | RENAME ALIAS CHAR_STRING TO CHAR_STRING (',' CHAR_STRING TO CHAR_STRING)* ; diskgroup_volume_clauses : add_volume_clause | modify_volume_clause | RESIZE VOLUME id_expression SIZE size_clause | DROP VOLUME id_expression ; add_volume_clause : ADD VOLUME id_expression SIZE size_clause redundancy_clause? ( STRIPE_WIDTH numeric (K_LETTER | M_LETTER) )? (STRIPE_COLUMNS numeric)? ; modify_volume_clause : MODIFY VOLUME id_expression (MOUNTPATH CHAR_STRING)? (USAGE CHAR_STRING)? ; diskgroup_attributes : SET ATTRIBUTE CHAR_STRING '=' CHAR_STRING ; drop_diskgroup_file_clause : DROP FILE filename (',' filename)* ; convert_redundancy_clause : CONVERT REDUNDANCY TO FLEX ; usergroup_clauses : ADD USERGROUP CHAR_STRING WITH MEMBER CHAR_STRING (',' CHAR_STRING)* | MODIFY USERGROUP CHAR_STRING (ADD | DROP) MEMBER CHAR_STRING (',' CHAR_STRING)* | DROP USERGROUP CHAR_STRING ; user_clauses : ADD USER CHAR_STRING (',' CHAR_STRING)* | DROP USER CHAR_STRING (',' CHAR_STRING)* CASCADE? | REPLACE USER CHAR_STRING WITH CHAR_STRING (',' CHAR_STRING WITH CHAR_STRING)* ; file_permissions_clause : SET PERMISSION (OWNER | GROUP | OTHER) '=' (NONE | READ (ONLY | WRITE)) ( ',' (OWNER | GROUP | OTHER) '=' (NONE | READ (ONLY | WRITE)) )* FOR FILE CHAR_STRING (',' CHAR_STRING)* ; file_owner_clause : SET OWNERSHIP (OWNER | GROUP) '=' CHAR_STRING (',' (OWNER | GROUP) '=' CHAR_STRING)* FOR FILE CHAR_STRING ( ',' CHAR_STRING )* ; scrub_clause : SCRUB (FILE CHAR_STRING | DISK id_expression)? (REPAIR | NOREPAIR)? ( POWER (AUTO | LOW | HIGH | MAX) )? wait_nowait? force_noforce? STOP? ; quotagroup_clauses : ADD QUOTAGROUP id_expression (SET property_name '=' property_value)? | MODIFY QUOTAGROUP id_expression SET property_name '=' property_value | MOVE QUOTAGROUP id_expression TO id_expression | DROP QUOTAGROUP id_expression ; property_name : id_expression ; property_value : id_expression ; filegroup_clauses : add_filegroup_clause | modify_filegroup_clause | move_to_filegroup_clause | drop_filegroup_clause ; add_filegroup_clause : ADD FILEGROUP id_expression ((DATABASE | CLUSTER | VOLUME) id_expression | TEMPLATE) ( FROM TEMPLATE id_expression )? (SET CHAR_STRING '=' CHAR_STRING)? ; modify_filegroup_clause : MODIFY FILEGROUP id_expression SET CHAR_STRING '=' CHAR_STRING ; move_to_filegroup_clause : MOVE FILE CHAR_STRING TO FILEGROUP id_expression ; drop_filegroup_clause : DROP FILEGROUP id_expression CASCADE? ; quorum_regular : QUORUM | REGULAR ; undrop_disk_clause : UNDROP DISKS ; diskgroup_availability : MOUNT (RESTRICTED | NORMAL)? (FORCE | NOFORCE)? | DISMOUNT (FORCE | NOFORCE)? ; enable_disable_volume : (ENABLE | DISABLE) VOLUME (id_expression (',' id_expression)* | ALL) ; // DDL -> SQL Statements for Stored PL/SQL Units // Function DDLs drop_function : DROP FUNCTION function_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-FLASHBACK-ARCHIVE.html alter_flashback_archive : ALTER FLASHBACK ARCHIVE fa = id_expression ( SET DEFAULT | (ADD | MODIFY) TABLESPACE ts = id_expression flashback_archive_quota? | REMOVE TABLESPACE rts = id_expression | MODIFY /*RETENTION*/ flashback_archive_retention // inconsistent documentation | PURGE (ALL | BEFORE (SCN expression | TIMESTAMP expression)) | NO? OPTIMIZE DATA ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-HIERARCHY.html alter_hierarchy : ALTER HIERARCHY (schema_name '.')? hn = id_expression ( RENAME TO nhn = id_expression | COMPILE ) ; alter_function : ALTER FUNCTION function_name ( EDITIONABLE | NONEDITIONABLE | COMPILE DEBUG? compiler_parameters_clause* (REUSE SETTINGS)? ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-JAVA.html alter_java : ALTER JAVA (SOURCE | CLASS) (schema_name '.')? o = id_expression ( RESOLVER '(' ('(' match_string ','? (schema_name | '-') ')')+ ')' )? (COMPILE | RESOLVE | invoker_rights_clause) ; match_string : DELIMITED_ID | '*' ; create_function_body : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? FUNCTION function_name ( '(' parameter (',' parameter)* ')' )? RETURN type_spec (SHARING '=' (METADATA | NONE))? ( invoker_rights_clause | accessible_by_clause | default_collation_clause | parallel_enable_clause | result_cache_clause | PIPELINED | DETERMINISTIC )* ( ((IS | AS) (DECLARE? seq_of_declare_specs? body | call_spec)) | aggregate_clause | pipelined_using_clause | sql_macro_body ) ; sql_macro_body : SQL_MACRO IS BEGIN RETURN quoted_string SEMICOLON END ; // Creation Function - Specific Clauses parallel_enable_clause : PARALLEL_ENABLE partition_by_clause? ; partition_by_clause : '(' PARTITION expression BY (ANY | (HASH | RANGE | LIST) paren_column_list) streaming_clause? ')' ; result_cache_clause : RESULT_CACHE relies_on_part? ('(' MODE (DEFAULT | FORCE ) ')')? ; accessible_by_clause : ACCESSIBLE BY '(' accessor (',' accessor)* ')' ; default_collation_clause : DEFAULT COLLATION USING_NLS_COMP ; aggregate_clause : AGGREGATE USING implementation_type_name ; pipelined_using_clause : PIPELINED ((ROW | TABLE) POLYMORPHIC)? USING implementation_type_name ; accessor : unitKind = (FUNCTION | PROCEDURE | PACKAGE | TRIGGER | TYPE) function_name ; relies_on_part : RELIES_ON '(' tableview_name (',' tableview_name)* ')' ; streaming_clause : (ORDER | CLUSTER) expression BY paren_column_list ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-OUTLINE.html alter_outline : ALTER OUTLINE (PUBLIC | PRIVATE)? o = id_expression outline_options+ ; outline_options : REBUILD | RENAME TO non = id_expression | CHANGE CATEGORY TO ncn = id_expression | ENABLE | DISABLE ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-LOCKDOWN-PROFILE.html alter_lockdown_profile : ALTER LOCKDOWN PROFILE id_expression ( lockdown_feature | lockdown_options | lockdown_statements ) (USERS '=' (ALL | COMMON | LOCAL))? ; lockdown_feature : disable_enable FEATURE ('=' '(' string_list ')' | ALL (EXCEPT '=' '(' string_list ')')?) ; lockdown_options : disable_enable OPTION ('=' '(' string_list ')' | ALL (EXCEPT '=' '(' string_list ')')?) ; lockdown_statements : disable_enable STATEMENT ( '=' '(' string_list ')' | '=' '(' CHAR_STRING ')' statement_clauses | ALL (EXCEPT '=' '(' string_list ')')? ) ; statement_clauses : CLAUSE ( '=' '(' string_list ')' | '=' '(' CHAR_STRING ')' clause_options | ALL (EXCEPT '=' '(' string_list ')')? ) ; clause_options : OPTION ( '=' '(' string_list ')' | '=' '(' CHAR_STRING ')' option_values+ | ALL (EXCEPT '=' '(' string_list ')')? ) ; option_values : VALUE '=' '(' string_list ')' | (MINVALUE | MAXVALUE) '=' CHAR_STRING ; string_list : CHAR_STRING (',' CHAR_STRING)* ; disable_enable : DISABLE | ENABLE ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-LOCKDOWN-PROFILE.html drop_lockdown_profile : DROP LOCKDOWN PROFILE p = id_expression ; // Package DDLs drop_package : DROP PACKAGE BODY? (schema_object_name '.')? package_name ; alter_package : ALTER PACKAGE package_name COMPILE DEBUG? (PACKAGE | BODY | SPECIFICATION)? compiler_parameters_clause* ( REUSE SETTINGS )? ; create_package : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? PACKAGE (schema_object_name '.')? package_name invoker_rights_clause? ( IS | AS ) package_obj_spec* END package_name? ; create_package_body : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? PACKAGE BODY (schema_object_name '.')? package_name ( IS | AS ) package_obj_body*? (BEGIN seq_of_statements (EXCEPTION exception_handler+)?)? END package_name? ; // Create Package Specific Clauses package_obj_spec : pragma_declaration | exception_declaration | procedure_spec | function_spec | variable_declaration | subtype_declaration | cursor_declaration | type_declaration ; procedure_spec : PROCEDURE identifier ('(' parameter ( ',' parameter)* ')')? ( accessible_by_clause | PARALLEL_ENABLE | DETERMINISTIC )* (AS call_spec)? ';' ; function_spec : FUNCTION identifier ('(' parameter ( ',' parameter)* ')')? RETURN type_spec ( DETERMINISTIC | PIPELINED | parallel_enable_clause | RESULT_CACHE | streaming_clause )* (AS call_spec)? ';' ; package_obj_body : pragma_declaration | exception_declaration | procedure_spec | function_spec | subtype_declaration | cursor_declaration | variable_declaration | type_declaration | procedure_body | function_body | selection_directive ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/alter-pmem-filestore.html alter_pmem_filestore : ALTER PMEM FILESTORE fsn = id_expression ( RESIZE size_clause | autoextend_clause | MOUNT (MOUNTPOINT file_path)? (BACKINGFILE filename)? FORCE? //inconsistent documentation | DISMOUNT ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/drop-pmem-filestore.html drop_pmem_filestore : DROP PMEM FILESTORE fsn = id_expression ((FORCE? INCLUDING | EXCLUDING) CONTENTS)? ; // Procedure DDLs drop_procedure : DROP PROCEDURE procedure_name ; alter_procedure : ALTER PROCEDURE procedure_name COMPILE DEBUG? compiler_parameters_clause* (REUSE SETTINGS)? ; function_body : FUNCTION identifier ('(' parameter (',' parameter)* ')')? RETURN type_spec ( PIPELINED | DETERMINISTIC | invoker_rights_clause | parallel_enable_clause | result_cache_clause | streaming_clause // see example in section "How Table Functions Stream their Input Data" on streaming_clause in Oracle 9i: https://docs.oracle.com/cd/B10501_01/appdev.920/a96624/08_subs.htm#20554 )* ( ( (IS | AS) (DECLARE? seq_of_declare_specs? body | call_spec)) | (PIPELINED | AGGREGATE) USING implementation_type_name ) ';' ; procedure_body : PROCEDURE identifier ('(' parameter (',' parameter)* ')')? ( accessible_by_clause | PARALLEL_ENABLE | DETERMINISTIC )* (IS | AS) (DECLARE? seq_of_declare_specs? body | call_spec | EXTERNAL) ';' ; create_procedure_body : CREATE (OR REPLACE)? PROCEDURE procedure_name ('(' parameter (',' parameter)* ')')? invoker_rights_clause? (PARALLEL_ENABLE | DETERMINISTIC)* ( IS | AS ) (DECLARE? seq_of_declare_specs? body | call_spec | EXTERNAL) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-RESOURCE-COST.html alter_resource_cost : ALTER RESOURCE COST ( (CPU_PER_SESSION | CONNECT_TIME | LOGICAL_READS_PER_SESSION | PRIVATE_SGA) UNSIGNED_INTEGER )+ ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-OUTLINE.html drop_outline : DROP OUTLINE o = id_expression ; // Rollback Segment DDLs //https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_2011.htm#SQLRF00816 alter_rollback_segment : ALTER ROLLBACK SEGMENT rollback_segment_name ( ONLINE | OFFLINE | storage_clause | SHRINK (TO size_clause)? ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-RESTORE-POINT.html drop_restore_point : DROP RESTORE POINT rp = id_expression (FOR PLUGGABLE DATABASE pdb = id_expression)? ; drop_rollback_segment : DROP ROLLBACK SEGMENT rollback_segment_name ; drop_role : DROP ROLE role_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/create-pmem-filestore.html create_pmem_filestore : CREATE PMEM FILESTORE fsn = id_expression pmem_filestore_options+ ; pmem_filestore_options : MOUNTPOINT file_path | BACKINGFILE filename REUSE? | (SIZE | BLOCKSIZE) size_clause | autoextend_clause ; file_path : CHAR_STRING ; create_rollback_segment : CREATE PUBLIC? ROLLBACK SEGMENT rollback_segment_name ( TABLESPACE tablespace | storage_clause )* ; // Trigger DDLs drop_trigger : DROP TRIGGER trigger_name ; alter_trigger : ALTER TRIGGER alter_trigger_name = trigger_name ( (ENABLE | DISABLE) | RENAME TO rename_trigger_name = trigger_name | COMPILE DEBUG? compiler_parameters_clause* (REUSE SETTINGS)? ) ; create_trigger : CREATE (OR REPLACE)? TRIGGER trigger_name ( simple_dml_trigger | compound_dml_trigger | non_dml_trigger ) trigger_follows_clause? (ENABLE | DISABLE)? trigger_when_clause? trigger_body ; trigger_follows_clause : FOLLOWS trigger_name (',' trigger_name)* ; trigger_when_clause : WHEN '(' condition ')' ; // Create Trigger Specific Clauses simple_dml_trigger : (BEFORE | AFTER | INSTEAD OF) dml_event_clause referencing_clause? for_each_row? ; for_each_row : FOR EACH ROW ; compound_dml_trigger : FOR dml_event_clause referencing_clause? ; non_dml_trigger : (BEFORE | AFTER) non_dml_event (OR non_dml_event)* ON (DATABASE | (schema_name '.')? SCHEMA) ; trigger_body : compound_trigger_block | CALL identifier | trigger_block ; compound_trigger_block : COMPOUND TRIGGER seq_of_declare_specs? timing_point_section+ END trigger_name? ; timing_point_section : bk = BEFORE STATEMENT IS tps_block BEFORE STATEMENT ';' | bk = BEFORE EACH ROW IS tps_block BEFORE EACH ROW ';' | ak = AFTER STATEMENT IS tps_block AFTER STATEMENT ';' | ak = AFTER EACH ROW IS tps_block AFTER EACH ROW ';' ; non_dml_event : ALTER | ANALYZE | ASSOCIATE STATISTICS | AUDIT | COMMENT | CREATE | DISASSOCIATE STATISTICS | DROP | GRANT | NOAUDIT | RENAME | REVOKE | TRUNCATE | DDL | STARTUP | SHUTDOWN | DB_ROLE_CHANGE | LOGON | LOGOFF | SERVERERROR | SUSPEND | DATABASE | SCHEMA | FOLLOWS ; dml_event_clause : dml_event_element (OR dml_event_element)* ON dml_event_nested_clause? tableview_name ; dml_event_element : (DELETE | INSERT | UPDATE) (OF column_list)? ; dml_event_nested_clause : NESTED TABLE tableview_name OF ; referencing_clause : (REFERENCING referencing_element | REFERENCES) referencing_element* ; referencing_element : (NEW | OLD | PARENT) column_alias ; // DDLs drop_type : DROP TYPE BODY? type_name (FORCE | VALIDATE)? ; alter_type : ALTER TYPE type_name ( compile_type_clause | replace_type_clause | alter_method_spec | alter_collection_clauses | modifier_clause | overriding_subprogram_spec ) dependent_handling_clause? ; // Alter Type Specific Clauses compile_type_clause : COMPILE DEBUG? (SPECIFICATION | BODY)? compiler_parameters_clause* (REUSE SETTINGS)? ; replace_type_clause : REPLACE invoker_rights_clause? AS OBJECT '(' object_member_spec (',' object_member_spec)* ')' ; alter_method_spec : alter_method_element (',' alter_method_element)* ; alter_method_element : (ADD | DROP) (map_order_function_spec | subprogram_spec) ; alter_collection_clauses : MODIFY (LIMIT expression | ELEMENT TYPE type_spec) ; dependent_handling_clause : INVALIDATE | CASCADE (CONVERT TO SUBSTITUTABLE | NOT? INCLUDING TABLE DATA)? dependent_exceptions_part? ; dependent_exceptions_part : FORCE? EXCEPTIONS INTO tableview_name ; create_type : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? TYPE (type_definition | type_body) ; // Create Type Specific Clauses type_definition : type_name (OID CHAR_STRING)? FORCE? object_type_def? ; object_type_def : invoker_rights_clause? (object_as_part | object_under_part) sqlj_object_type? ( '(' object_member_spec (',' object_member_spec)* ')' )? modifier_clause* ; object_as_part : (IS | AS) (OBJECT | varray_type_def | nested_table_type_def) ; object_under_part : UNDER type_spec ; nested_table_type_def : TABLE OF type_spec (NOT NULL_)? ; sqlj_object_type : EXTERNAL NAME expression LANGUAGE JAVA USING (SQLDATA | CUSTOMDATUM | ORADATA) ; type_body : BODY type_name (IS | AS) (type_body_elements)+ END ; type_body_elements : map_order_func_declaration | subprog_decl_in_type | overriding_subprogram_spec ; map_order_func_declaration : (MAP | ORDER) MEMBER func_decl_in_type ; subprog_decl_in_type : (MEMBER | STATIC)? (proc_decl_in_type | func_decl_in_type | constructor_declaration) ; proc_decl_in_type : PROCEDURE procedure_name ( '(' type_elements_parameter (',' type_elements_parameter)* ')' )? (IS | AS) (call_spec | DECLARE? seq_of_declare_specs? body ';') ; func_decl_in_type : FUNCTION function_name ('(' type_elements_parameter (',' type_elements_parameter)* ')')? RETURN type_spec ( IS | AS ) (call_spec | DECLARE? seq_of_declare_specs? body ';') ; constructor_declaration : FINAL? INSTANTIABLE? CONSTRUCTOR FUNCTION function_name ( '(' (SELF IN OUT type_spec ',')? (type_elements_parameter (',' type_elements_parameter)*)? ')' )? RETURN SELF AS RESULT (IS | AS) (call_spec | DECLARE? seq_of_declare_specs? body ';') ; // Common Type Clauses modifier_clause : NOT? (INSTANTIABLE | FINAL | OVERRIDING) ; object_member_spec : identifier type_spec sqlj_object_type_attr? | element_spec ; sqlj_object_type_attr : EXTERNAL NAME expression ; element_spec : modifier_clause? element_spec_options+ (',' pragma_clause)? ; element_spec_options : subprogram_spec | constructor_spec | map_order_function_spec ; subprogram_spec : (MEMBER | STATIC) (type_procedure_spec | type_function_spec) ; // TODO: should be refactored such as Procedure body and Function body, maybe Type_Function_Body and overriding_function_body overriding_subprogram_spec : OVERRIDING MEMBER overriding_function_spec | OVERRIDING MEMBER overriding_procedure_spec ; overriding_function_spec : FUNCTION function_name ('(' type_elements_parameter (',' type_elements_parameter)* ')')? RETURN ( type_spec | SELF AS RESULT ) (PIPELINED? (IS | AS) (DECLARE? seq_of_declare_specs? body))? ';'? ; overriding_procedure_spec : PROCEDURE procedure_name ( '(' type_elements_parameter (',' type_elements_parameter)* ')' )? (IS | AS) (call_spec | DECLARE? seq_of_declare_specs? body ';') ; type_procedure_spec : PROCEDURE procedure_name ('(' type_elements_parameter (',' type_elements_parameter)* ')')? ( (IS | AS) call_spec )? ; type_function_spec : FUNCTION function_name ('(' type_elements_parameter (',' type_elements_parameter)* ')')? RETURN ( type_spec | SELF AS RESULT ) ((IS | AS) call_spec | EXTERNAL VARIABLE? NAME expression)? ; constructor_spec : FINAL? INSTANTIABLE? CONSTRUCTOR FUNCTION type_spec ( '(' (SELF IN OUT type_spec ',')? (type_elements_parameter (',' type_elements_parameter)*)? ')' )? RETURN SELF AS RESULT ((IS | AS) call_spec)? ; map_order_function_spec : (MAP | ORDER) MEMBER type_function_spec ; pragma_clause : PRAGMA RESTRICT_REFERENCES '(' pragma_elements (',' pragma_elements)* ')' ; pragma_elements : identifier | DEFAULT ; type_elements_parameter : parameter_name (IN OUT NOCOPY | IN OUT | OUT NOCOPY | OUT | IN)? type_spec (ASSIGN_OP constant)? ; // Sequence DDLs drop_sequence : DROP SEQUENCE sequence_name ; alter_sequence : ALTER SEQUENCE sequence_name sequence_spec+ ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-SESSION.html alter_session : ALTER SESSION ( ADVISE ( COMMIT | ROLLBACK | NOTHING) | CLOSE DATABASE LINK parameter_name | enable_or_disable COMMIT IN PROCEDURE | enable_or_disable GUARD | (enable_or_disable | FORCE) PARALLEL (DML | DDL | QUERY) ( PARALLEL (literal | parameter_name) )? | SET alter_session_set_clause ) ; alter_session_set_clause : (parameter_name '=' parameter_value)+ | EDITION '=' en = id_expression | CONTAINER '=' cn = id_expression (SERVICE '=' sn = id_expression)? | ROW ARCHIVAL VISIBILITY '=' (ACTIVE | ALL) | DEFAULT_COLLATION '=' (c = id_expression | NONE) ; create_sequence : CREATE SEQUENCE (IF NOT EXISTS)? sequence_name sequence_spec* (SHARING '=' (METADATA | DATA | NONE))? ; // Common Sequence sequence_spec : INCREMENT BY UNSIGNED_INTEGER | sequence_start_clause | MAXVALUE UNSIGNED_INTEGER | NOMAXVALUE | MINVALUE UNSIGNED_INTEGER | NOMINVALUE | CYCLE | NOCYCLE | CACHE UNSIGNED_INTEGER | NOCACHE | ORDER | NOORDER | KEEP | NOKEEP | SCALE (EXTEND | NOEXTEND)? | NOSCALE | SHARD (EXTEND | NOEXTEND)? | NOSHARD | SESSION | GLOBAL ; sequence_start_clause : START WITH UNSIGNED_INTEGER ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-ANALYTIC-VIEW.html create_analytic_view : CREATE (OR REPLACE)? (NOFORCE | FORCE)? ANALYTIC VIEW av = id_expression ( SHARING '=' (METADATA | NONE) )? classification_clause* cav_using_clause? dim_by_clause? measures_clause? default_measure_clause? default_aggregate_clause? cache_clause? fact_columns_clause? qry_transform_clause? ; classification_clause // : (CAPTION c=quoted_string)? (DESCRIPTION d=quoted_string)? classification_item* // to handle - 'rule contains a closure with at least one alternative that can match an empty string' : (caption_clause description_clause? | caption_clause? description_clause) classification_item* | caption_clause? description_clause? classification_item+ ; caption_clause : CAPTION c = quoted_string ; description_clause : DESCRIPTION d = quoted_string ; classification_item : CLASSIFICATION cn = id_expression (VALUE cv = quoted_string)? (LANGUAGE language)? ; language : NULL_ | nls = id_expression ; cav_using_clause : USING (schema_name '.')? t = id_expression REMOTE? (AS? ta = id_expression)? ; dim_by_clause : DIMENSION BY '(' dim_key (',' dim_key)* ')' ; dim_key : dim_ref classification_clause* KEY ( '(' (a = id_expression '.')? f = column_name (',' (a = id_expression '.')? f = column_name)* ')' | (a = id_expression '.')? f = column_name ) REFERENCES DISTINCT? ('(' attribute_name (',' attribute_name) ')' | attribute_name) HIERARCHIES '(' hier_ref ( ',' hier_ref )* ')' ; dim_ref : (schema_name '.')? ad = id_expression (AS? da = id_expression)? ; hier_ref : (schema_name '.')? h = id_expression (AS? ha = id_expression)? DEFAULT? ; measures_clause : MEASURES '(' av_measure (',' av_measure)* ')' ; av_measure : mn = id_expression (base_meas_clause | calc_meas_clause)? //classification_clause* ; base_meas_clause : FACT /*FOR MEASURE*/ bm = id_expression meas_aggregate_clause? //FIXME inconsistent documentation ; meas_aggregate_clause : AGGREGATE BY aggregate_function_name ; calc_meas_clause : /*m=id_expression*/ AS '(' expression ')' //FIXME inconsistent documentation ; default_measure_clause : DEFAULT MEASURE m = id_expression ; default_aggregate_clause : DEFAULT AGGREGATE BY aggregate_function_name ; cache_clause : CACHE cache_specification (',' cache_specification)* ; cache_specification : MEASURE GROUP ( ALL | '(' id_expression (',' id_expression)* ')' levels_clause (',' levels_clause)* ) ; levels_clause : LEVELS '(' level_specification (',' level_specification)* ')' level_group_type ; level_specification : '(' ((d = id_expression '.')? h = id_expression '.')? l = id_expression ')' ; level_group_type : DYNAMIC | MATERIALIZED (USING (schema_name '.')? t = id_expression)? ; fact_columns_clause : FACT COLUMN f = column_name (AS? fa = id_expression (',' AS? fa = id_expression)*)? ; qry_transform_clause : ENABLE QUERY TRANSFORM (RELY | NORELY)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-ATTRIBUTE-DIMENSION.html create_attribute_dimension : CREATE (OR REPLACE)? (NOFORCE | FORCE)? ATTRIBUTE DIMENSION (schema_name '.')? ad = id_expression ( SHARING '=' (METADATA | NONE) )? classification_clause* (DIMENSION TYPE (STANDARD | TIME))? ad_using_clause attributes_clause ad_level_clause+ all_clause? ; ad_using_clause : USING source_clause (',' source_clause)* join_path_clause* ; source_clause : (schema_name '.')? ftov = id_expression REMOTE? (AS? a = id_expression)? ; join_path_clause : JOIN PATH jpn = id_expression ON join_condition ; join_condition : join_condition_item (AND join_condition_item)* ; join_condition_item : (a = id_expression '.')? column_name '=' (b = id_expression '.')? column_name ; attributes_clause : ATTRIBUTES '(' ad_attributes_clause (',' ad_attributes_clause)* ')' ; ad_attributes_clause : (a = id_expression '.')? column_name (AS? an = id_expression)? classification_clause* ; ad_level_clause : LEVEL l = id_expression (NOT NULL_ | SKIP_ WHEN NULL_)? ( LEVEL TYPE ( STANDARD | YEARS | HALF_YEARS | QUARTERS | MONTHS | WEEKS | DAYS | HOURS | MINUTES | SECONDS ) )? classification_clause* //inconsistent documentation - LEVEL TYPE goes after the classification_clause rule key_clause alternate_key_clause? (MEMBER NAME expression)? (MEMBER CAPTION expression)? ( MEMBER DESCRIPTION expression )? (ORDER BY (MIN | MAX)? dim_order_clause (',' (MIN | MAX)? dim_order_clause)*)? ( DETERMINES '(' id_expression (',' id_expression)* ')' )? ; key_clause : KEY (a = id_expression | '(' id_expression (',' id_expression)* ')') ; alternate_key_clause : ALTERNATE key_clause ; dim_order_clause : a = id_expression (ASC | DESC)? (NULLS (FIRST | LAST))? ; all_clause : ALL MEMBER ( NAME expression (MEMBER CAPTION expression)? | CAPTION expression (MEMBER DESCRIPTION expression)? | DESCRIPTION expression ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-AUDIT-POLICY-Unified-Auditing.html create_audit_policy : CREATE AUDIT POLICY p = id_expression privilege_audit_clause? action_audit_clause? role_audit_clause? ( WHEN quoted_string EVALUATE PER (STATEMENT | SESSION | INSTANCE) )? (ONLY TOPLEVEL)? container_clause? ; privilege_audit_clause : PRIVILEGES system_privilege (',' system_privilege)* ; action_audit_clause : (standard_actions | component_actions | system_actions)+ ; system_actions : ACTIONS system_privilege (',' system_privilege)* ; standard_actions : ACTIONS actions_clause (',' actions_clause)* ; actions_clause : (object_action | ALL) ON ( DIRECTORY directory_name | (MINING MODEL)? (schema_name '.')? id_expression ) | (system_action | ALL) ; object_action : ALTER | GRANT | READ | EXECUTE | AUDIT | COMMENT | DELETE | INDEX | INSERT | LOCK | SELECT | UPDATE | FLASHBACK | RENAME ; system_action : id_expression // SELECT name FROM AUDITABLE_SYSTEM_ACTIONS WHERE component = 'Standard'; | (CREATE | ALTER | DROP) JAVA | LOCK TABLE | (READ | WRITE | EXECUTE) DIRECTORY ; component_actions : ACTIONS COMPONENT '=' ( (DATAPUMP | DIRECT_LOAD | OLS | XS) component_action (',' component_action)* | DV component_action ON id_expression (',' component_action ON id_expression)* | PROTOCOL (FTP | HTTP | AUTHENTICATION) ) ; component_action : id_expression // SELECT name FROM auditable_system_actions WHERE component = 'Datapump'; ; role_audit_clause : ROLES role_name (',' role_name)* ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-CONTROLFILE.html create_controlfile : CREATE CONTROLFILE REUSE? SET? DATABASE d = id_expression logfile_clause? ( RESETLOGS | NORESETLOGS ) (DATAFILE file_specification (',' file_specification)*)? controlfile_options* character_set_clause? ; controlfile_options : MAXLOGFILES numeric | MAXLOGMEMBERS numeric | MAXLOGHISTORY numeric | MAXDATAFILES numeric | MAXINSTANCES numeric | ARCHIVELOG | NOARCHIVELOG | FORCE LOGGING | SET STANDBY NOLOGGING FOR (DATA AVAILABILITY | LOAD PERFORMANCE) ; logfile_clause : LOGFILE (GROUP? numeric)? file_specification (',' (GROUP? numeric)? file_specification)* ; character_set_clause : CHARACTER SET cs = id_expression ; file_specification : datafile_tempfile_spec | redo_log_file_spec ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-DISKGROUP.html create_diskgroup : CREATE DISKGROUP id_expression ( (HIGH | NORMAL | FLEX | EXTENDED (SITE sn = id_expression)? | EXTERNAL) REDUNDANCY )? ( quorum_regular? (FAILGROUP fg = id_expression)? DISK qualified_disk_clause ( ',' qualified_disk_clause )* )+ (ATTRIBUTE an = CHAR_STRING '=' av = CHAR_STRING (',' CHAR_STRING '=' CHAR_STRING)*)? ; qualified_disk_clause : ss = CHAR_STRING (NAME dn = id_expression)? (SIZE size_clause)? force_noforce? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-EDITION.html create_edition : CREATE EDITION e = id_expression (AS CHILD OF pe = id_expression)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-FLASHBACK-ARCHIVE.html create_flashback_archive : CREATE FLASHBACK ARCHIVE DEFAULT? fa = id_expression TABLESPACE ts = id_expression flashback_archive_quota? ( NO? OPTIMIZE DATA )? flashback_archive_retention ; flashback_archive_quota : QUOTA UNSIGNED_INTEGER (M_LETTER | G_LETTER | T_LETTER | P_LETTER | E_LETTER) ; flashback_archive_retention : RETENTION UNSIGNED_INTEGER (YEAR | MONTH | DAY) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-HIERARCHY.html create_hierarchy : CREATE (OR REPLACE)? (NO? FORCE)? HIERARCHY (schema_name '.')? h = id_expression ( SHARING '=' (METADATA | NONE) )? classification_clause* hier_using_clause level_hier_clause hier_attrs_clause? ; hier_using_clause : USING (schema_name '.')? ad = id_expression ; level_hier_clause : '(' (l = id_expression (CHILD OF)?)+ ')' ; hier_attrs_clause : HIERARCHICAL ATTRIBUTES '(' hier_attr_clause ')' ; hier_attr_clause : hier_attr_name classification_clause* ; hier_attr_name : MEMBER_NAME | MEMBER_UNIQUE_NAME | MEMBER_CAPTION | MEMBER_DESCRIPTION | LEVEL_NAME | HIER_ORDER | DEPTH | IS_LEAF | PARENT_LEVEL_NAME | PARENT_UNIQUE_NAME ; create_index : CREATE (UNIQUE | BITMAP)? INDEX index_name (IF NOT EXISTS)? ON ( cluster_index_clause | table_index_clause | bitmap_join_index_clause ) (USABLE | UNUSABLE)? ((DEFERRED | IMMEDIATE) INVALIDATION)? ; cluster_index_clause : CLUSTER cluster_name index_attributes? ; cluster_name : (id_expression '.')? id_expression ; table_index_clause : tableview_name table_alias? '(' index_expr (ASC | DESC)? (',' index_expr (ASC | DESC)?)* ')' index_properties? ; bitmap_join_index_clause : tableview_name '(' (tableview_name | table_alias)? column_name (ASC | DESC)? ( ',' (tableview_name | table_alias)? column_name (ASC | DESC)? )* ')' FROM tableview_name table_alias (',' tableview_name table_alias)* where_clause local_partitioned_index? index_attributes? ; index_expr : column_name | expression ; index_properties : (global_partitioned_index | local_partitioned_index | index_attributes)+ | INDEXTYPE IS (domain_index_clause | xmlindex_clause) ; domain_index_clause : indextype local_domain_index_clause? parallel_clause? (PARAMETERS '(' odci_parameters ')')? ; local_domain_index_clause : LOCAL ( '(' PARTITION partition_name (PARAMETERS '(' odci_parameters ')')? ( ',' PARTITION partition_name (PARAMETERS '(' odci_parameters ')')? )* ')' )? ; xmlindex_clause : (XDB '.')? XMLINDEX local_xmlindex_clause? parallel_clause? //TODO xmlindex_parameters_clause? ; local_xmlindex_clause : LOCAL ( '(' PARTITION partition_name ( ',' PARTITION partition_name //TODO xmlindex_parameters_clause? )* ')' )? ; global_partitioned_index : GLOBAL PARTITION BY ( RANGE '(' column_name (',' column_name)* ')' '(' index_partitioning_clause ( ',' index_partitioning_clause )* ')' | HASH '(' column_name (',' column_name)* ')' ( individual_hash_partitions | hash_partitions_by_quantity ) ) ; index_partitioning_clause : PARTITION partition_name? VALUES LESS THAN '(' index_partitioning_values_list ')' segment_attributes_clause? ; index_partitioning_values_list : literal (',' literal)* | TIMESTAMP literal (',' TIMESTAMP literal)* ; local_partitioned_index : LOCAL ( on_range_partitioned_table | on_list_partitioned_table | on_hash_partitioned_table | on_comp_partitioned_table )? ; on_range_partitioned_table : '(' partitioned_table (',' partitioned_table)* ')' ; on_list_partitioned_table : '(' partitioned_table (',' partitioned_table)* ')' ; partitioned_table : PARTITION partition_name? (segment_attributes_clause | key_compression)* UNUSABLE? ; on_hash_partitioned_table : STORE IN '(' tablespace (',' tablespace)* ')' | '(' on_hash_partitioned_clause (',' on_hash_partitioned_clause)* ')' ; on_hash_partitioned_clause : PARTITION partition_name? (TABLESPACE tablespace)? key_compression? UNUSABLE? ; on_comp_partitioned_table : (STORE IN '(' tablespace (',' tablespace)* ')')? '(' on_comp_partitioned_clause ( ',' on_comp_partitioned_clause )* ')' ; on_comp_partitioned_clause : PARTITION partition_name? (segment_attributes_clause | key_compression)* UNUSABLE? index_subpartition_clause? ; index_subpartition_clause : STORE IN '(' tablespace (',' tablespace)* ')' | '(' index_subpartition_subclause (',' index_subpartition_subclause)* ')' ; index_subpartition_subclause : SUBPARTITION subpartition_name? (TABLESPACE tablespace)? key_compression? UNUSABLE? ; odci_parameters : CHAR_STRING ; indextype : (id_expression '.')? id_expression ; //https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_1010.htm#SQLRF00805 alter_index : ALTER INDEX index_name (alter_index_ops_set1 | alter_index_ops_set2) ; alter_index_ops_set1 : ( deallocate_unused_clause | allocate_extent_clause | shrink_clause | parallel_clause | physical_attributes_clause | logging_clause )+ ; alter_index_ops_set2 : rebuild_clause | PARAMETERS '(' odci_parameters ')' | COMPILE | enable_or_disable | UNUSABLE | visible_or_invisible | RENAME TO new_index_name | COALESCE | monitoring_nomonitoring USAGE | UPDATE BLOCK REFERENCES | alter_index_partitioning ; visible_or_invisible : VISIBLE | INVISIBLE ; monitoring_nomonitoring : MONITORING | NOMONITORING ; rebuild_clause : REBUILD (PARTITION partition_name | SUBPARTITION subpartition_name | REVERSE | NOREVERSE)? ( parallel_clause | TABLESPACE tablespace | PARAMETERS '(' odci_parameters ')' //TODO | xmlindex_parameters_clause | ONLINE | physical_attributes_clause | key_compression | logging_clause )* ; alter_index_partitioning : modify_index_default_attrs | add_hash_index_partition | modify_index_partition | rename_index_partition | drop_index_partition | split_index_partition | coalesce_index_partition | modify_index_subpartition ; modify_index_default_attrs : MODIFY DEFAULT ATTRIBUTES (FOR PARTITION partition_name)? ( physical_attributes_clause | TABLESPACE (tablespace | DEFAULT) | logging_clause ) ; add_hash_index_partition : ADD PARTITION partition_name? (TABLESPACE tablespace)? key_compression? parallel_clause? ; coalesce_index_partition : COALESCE PARTITION parallel_clause? ; modify_index_partition : MODIFY PARTITION partition_name ( modify_index_partitions_ops+ | PARAMETERS '(' odci_parameters ')' | COALESCE | UPDATE BLOCK REFERENCES | UNUSABLE ) ; modify_index_partitions_ops : deallocate_unused_clause | allocate_extent_clause | physical_attributes_clause | logging_clause | key_compression | shrink_clause ; rename_index_partition : RENAME (PARTITION partition_name | SUBPARTITION subpartition_name) TO new_partition_name ; drop_index_partition : DROP PARTITION partition_name ; split_index_partition : SPLIT PARTITION partition_name_old AT '(' literal (',' literal)* ')' ( INTO '(' index_partition_description ',' index_partition_description ')' )? parallel_clause? ; index_partition_description : PARTITION ( partition_name ( (segment_attributes_clause | key_compression)+ | PARAMETERS '(' odci_parameters ')' ) UNUSABLE? )? ; modify_index_subpartition : MODIFY SUBPARTITION subpartition_name (UNUSABLE | modify_index_partitions_ops) ; partition_name_old : partition_name ; new_partition_name : partition_name ; new_index_name : index_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-INMEMORY-JOIN-GROUP.html alter_inmemory_join_group : ALTER INMEMORY JOIN GROUP (schema_name '.')? jg = id_expression (ADD | REMOVE) '(' ( schema_name '.' )? t = id_expression '(' c = id_expression ')' ')' ; create_user : CREATE USER user_object_name (IF NOT EXISTS)? ( identified_by | identified_other_clause | user_tablespace_clause | quota_clause | profile_clause | password_expire_clause | user_lock_clause | user_editions_clause | container_clause )+ ; // The standard clauses only permit one user per statement. // The proxy clause allows multiple users for a proxy designation. alter_user : ALTER USER user_object_name ( alter_identified_by | identified_other_clause | user_tablespace_clause | quota_clause | profile_clause | user_default_role_clause | password_expire_clause | user_lock_clause | alter_user_editions_clause | container_clause | container_data_clause )+ | user_object_name (',' user_object_name)* proxy_clause ; drop_user : DROP USER user_object_name (IF EXISTS)? CASCADE? ; alter_identified_by : identified_by (REPLACE id_expression)? ; identified_by : IDENTIFIED BY id_expression ; identified_other_clause : IDENTIFIED (EXTERNALLY | GLOBALLY) (AS quoted_string)? ; user_tablespace_clause : (DEFAULT | TEMPORARY) TABLESPACE id_expression ; quota_clause : QUOTA (size_clause | UNLIMITED) ON id_expression ; profile_clause : PROFILE id_expression ; role_clause : role_name (',' role_name)* | ALL (EXCEPT role_name (',' role_name)*)* ; user_default_role_clause : DEFAULT ROLE (NONE | role_clause) ; password_expire_clause : PASSWORD EXPIRE ; user_lock_clause : ACCOUNT (LOCK | UNLOCK) ; user_editions_clause : ENABLE EDITIONS ; alter_user_editions_clause : user_editions_clause (FOR regular_id (',' regular_id)*)? FORCE? ; proxy_clause : REVOKE CONNECT THROUGH (ENTERPRISE USERS | user_object_name) | GRANT CONNECT THROUGH ( ENTERPRISE USERS | user_object_name (WITH (NO ROLES | ROLE role_clause))? (AUTHENTICATION REQUIRED)? ( AUTHENTICATED USING (PASSWORD | CERTIFICATE | DISTINGUISHED NAME) )? ) ; container_names : LEFT_PAREN id_expression (',' id_expression)* RIGHT_PAREN ; set_container_data : SET CONTAINER_DATA EQUALS_OP (ALL | DEFAULT | container_names) ; add_rem_container_data : (ADD | REMOVE) CONTAINER_DATA EQUALS_OP container_names ; container_data_clause : set_container_data | add_rem_container_data (FOR container_tableview_name)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ADMINISTER-KEY-MANAGEMENT.html administer_key_management : ADMINISTER KEY MANAGEMENT ( keystore_management_clauses | key_management_clauses | secret_management_clauses | zero_downtime_software_patching_clauses ) ; keystore_management_clauses : create_keystore | open_keystore | close_keystore | backup_keystore | alter_keystore_password | merge_into_new_keystore | merge_into_existing_keystore | isolate_keystore | unite_keystore ; create_keystore : CREATE ( KEYSTORE ksl = CHAR_STRING | LOCAL? AUTO_LOGIN KEYSTORE FROM KEYSTORE ksl = CHAR_STRING ) IDENTIFIED BY keystore_password ; open_keystore : SET KEYSTORE OPEN force_keystore? identified_by_store container_clause? ; force_keystore : FORCE KEYSTORE ; close_keystore : SET KEYSTORE CLOSE identified_by_store? container_clause? ; backup_keystore : BACKUP KEYSTORE (USING bi = CHAR_STRING)? force_keystore? identified_by_store ( TO ksl = CHAR_STRING )? ; alter_keystore_password : ALTER KEYSTORE PASSWORD force_keystore? IDENTIFIED BY o = keystore_password SET n = keystore_password with_backup_clause? ; merge_into_new_keystore : MERGE KEYSTORE ksl1 = CHAR_STRING identified_by_password_clause? AND KEYSTORE ksl2 = CHAR_STRING identified_by_password_clause? INTO NEW KEYSTORE ksl2 = CHAR_STRING identified_by_password_clause ; merge_into_existing_keystore : MERGE KEYSTORE ksl1 = CHAR_STRING identified_by_password_clause? INTO EXISTING KEYSTORE ksl2 = CHAR_STRING identified_by_password_clause with_backup_clause? ; isolate_keystore : FORCE? ISOLATE KEYSTORE IDENTIFIED BY i = keystore_password FROM ROOT KEYSTORE force_keystore? identified_by_store with_backup_clause? ; unite_keystore : UNITE KEYSTORE IDENTIFIED BY i = keystore_password WITH ROOT KEYSTORE force_keystore? identified_by_store with_backup_clause? ; key_management_clauses : set_key | create_key | use_key | set_key_tag | export_keys | import_keys | migrate_keys | reverse_migrate_keys | move_keys ; set_key : SET ENCRYPTION? KEY ((mkid ':')? mk)? using_tag_clause? using_algorithm_clause? force_keystore? identified_by_store with_backup_clause? container_clause? ; create_key : CREATE ENCRYPTION? KEY ((mkid ':')? mk)? using_tag_clause? using_algorithm_clause? force_keystore? identified_by_store with_backup_clause? container_clause? ; mkid : CHAR_STRING ; mk : CHAR_STRING ; use_key : USE ENCRYPTION? KEY k = CHAR_STRING using_tag_clause? force_keystore? identified_by_store with_backup_clause? ; set_key_tag : SET TAG t = CHAR_STRING FOR k = CHAR_STRING force_keystore? identified_by_store with_backup_clause? ; export_keys : EXPORT ENCRYPTION? KEYS WITH SECRET secret TO filename force_keystore? identified_by_store ( WITH IDENTIFIER IN (CHAR_STRING (',' CHAR_STRING)* | '(' subquery ')') )? ; import_keys : IMPORT ENCRYPTION? KEYS WITH SECRET secret FROM filename force_keystore? identified_by_store with_backup_clause? ; migrate_keys : SET ENCRYPTION? KEY IDENTIFIED BY hsm = secret force_keystore? MIGRATE USING keystore_password with_backup_clause? ; reverse_migrate_keys : SET ENCRYPTION? KEY IDENTIFIED BY s = secret force_keystore? REVERSE MIGRATE USING hsm = secret ; move_keys : MOVE ENCRYPTION? KEYS TO NEW KEYSTORE ksl1 = CHAR_STRING IDENTIFIED BY ksp1 = keystore_password FROM FORCE? KEYSTORE IDENTIFIED BY ksp = keystore_password (WITH IDENTIFIER IN (CHAR_STRING (',' CHAR_STRING)* | subquery))? with_backup_clause? ; identified_by_store : IDENTIFIED BY (EXTERNAL STORE | keystore_password) ; using_algorithm_clause : USING ALGORITHM ea = CHAR_STRING ; using_tag_clause : USING TAG t = CHAR_STRING ; secret_management_clauses : add_update_secret | delete_secret | add_update_secret_seps | delete_secret_seps ; add_update_secret : (ADD | UPDATE) SECRET s = CHAR_STRING FOR CLIENT ci = CHAR_STRING using_tag_clause? force_keystore? identified_by_store? with_backup_clause? ; delete_secret : DELETE SECRET FOR CLIENT ci = CHAR_STRING force_keystore? identified_by_store with_backup_clause? ; add_update_secret_seps : (ADD | UPDATE) SECRET s = CHAR_STRING FOR CLIENT ci = CHAR_STRING using_tag_clause? TO LOCAL? AUTO_LOGIN KEYSTORE directory_path ; delete_secret_seps : DELETE SECRET s = CHAR_STRING SQ FOR CLIENT ci = CHAR_STRING FROM LOCAL? AUTO_LOGIN KEYSTORE directory_path ; zero_downtime_software_patching_clauses : SWITCHOVER TO? LIBRARY path FOR ALL CONTAINERS //inconsistent documentation ; with_backup_clause : WITH BACKUP (USING bi = CHAR_STRING)? ; identified_by_password_clause : IDENTIFIED BY keystore_password ; keystore_password : DELIMITED_ID ; path : CHAR_STRING ; secret : DELIMITED_ID ; // https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_4005.htm#SQLRF01105 analyze : ( ANALYZE (TABLE tableview_name | INDEX index_name) partition_extention_clause? | ANALYZE CLUSTER cluster_name ) ( validation_clauses | compute_clauses | ESTIMATE SYSTEM? STATISTICS for_clause? (SAMPLE UNSIGNED_INTEGER (ROWS | PERCENT_KEYWORD))? | LIST CHAINED ROWS into_clause1? | DELETE SYSTEM? STATISTICS) ; partition_extention_clause : PARTITION ( '(' partition_name ')' | FOR '(' partition_key_value (',' partition_key_value)* ')' ) | SUBPARTITION ( '(' subpartition_name ')' | FOR '(' subpartition_key_value (',' subpartition_key_value)* ')' ) ; validation_clauses : VALIDATE REF UPDATE (SET DANGLING TO NULL_)? | VALIDATE STRUCTURE (CASCADE FAST | CASCADE online_or_offline? into_clause? | CASCADE)? online_or_offline? into_clause? ; compute_clauses : COMPUTE SYSTEM? STATISTICS for_clause? ; for_clause : FOR ( TABLE for_clause* | ALL (INDEXED? COLUMNS (SIZE UNSIGNED_INTEGER)? for_clause* | LOCAL? INDEXES) | COLUMNS (SIZE UNSIGNED_INTEGER)? (column_name SIZE UNSIGNED_INTEGER)+ for_clause* ) ; online_or_offline : OFFLINE | ONLINE ; into_clause1 : INTO tableview_name? ; //Making assumption on partition ad subpartition key value clauses partition_key_value : literal | TIMESTAMP quoted_string ; subpartition_key_value : literal | TIMESTAMP quoted_string ; //https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_4006.htm#SQLRF01106 associate_statistics : ASSOCIATE STATISTICS WITH (column_association | function_association) storage_table_clause? ; column_association : COLUMNS tableview_name '.' column_name (',' tableview_name '.' column_name)* using_statistics_type ; function_association : ( FUNCTIONS function_name (',' function_name)* | PACKAGES package_name (',' package_name)* | TYPES type_name (',' type_name)* | INDEXES index_name (',' index_name)* | INDEXTYPES indextype_name (',' indextype_name)* ) ( using_statistics_type | default_cost_clause (',' default_selectivity_clause)? | default_selectivity_clause (',' default_cost_clause)? ) ; indextype_name : id_expression ; using_statistics_type : USING (statistics_type_name | NULL_) ; statistics_type_name : regular_id ; default_cost_clause : DEFAULT COST '(' cpu_cost ',' io_cost ',' network_cost ')' ; cpu_cost : UNSIGNED_INTEGER ; io_cost : UNSIGNED_INTEGER ; network_cost : UNSIGNED_INTEGER ; default_selectivity_clause : DEFAULT SELECTIVITY default_selectivity ; default_selectivity : UNSIGNED_INTEGER ; storage_table_clause : WITH (SYSTEM | USER) MANAGED STORAGE TABLES ; // https://docs.oracle.com/database/121/SQLRF/statements_4008.htm#SQLRF56110 unified_auditing : {this.isVersion12()}? AUDIT ( POLICY policy_name ((BY | EXCEPT) audit_user (',' audit_user)*)? (WHENEVER NOT? SUCCESSFUL)? | CONTEXT NAMESPACE oracle_namespace ATTRIBUTES attribute_name (',' attribute_name)* ( BY audit_user (',' audit_user)* )? ) ; policy_name : identifier ; // https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_4007.htm#SQLRF01107 // https://docs.oracle.com/database/121/SQLRF/statements_4007.htm#SQLRF01107 audit_traditional : AUDIT ( audit_operation_clause (auditing_by_clause | IN SESSION CURRENT)? | audit_schema_object_clause | NETWORK | audit_direct_path ) (BY (SESSION | ACCESS))? (WHENEVER NOT? SUCCESSFUL)? audit_container_clause? ; audit_direct_path : {this.isVersion12()}? DIRECT_PATH auditing_by_clause ; audit_container_clause : {this.isVersion12()}? (CONTAINER EQUALS_OP (CURRENT | ALL)) ; audit_operation_clause : ( (sql_statement_shortcut | ALL STATEMENTS?) (',' (sql_statement_shortcut | ALL STATEMENTS?))* | (system_privilege | ALL PRIVILEGES) (',' (system_privilege | ALL PRIVILEGES))* ) ; auditing_by_clause : BY audit_user (',' audit_user)* ; audit_user : regular_id ; audit_schema_object_clause : (sql_operation (',' sql_operation)* | ALL) auditing_on_clause ; sql_operation : ALTER | AUDIT | COMMENT | DELETE | EXECUTE | FLASHBACK | GRANT | INDEX | INSERT | LOCK | READ | RENAME | SELECT | UPDATE ; auditing_on_clause : ON ( object_name | DIRECTORY regular_id | MINING MODEL model_name | {this.isVersion12()}? SQL TRANSLATION PROFILE profile_name | DEFAULT ) ; model_name : (id_expression '.')? id_expression ; object_name : (id_expression '.')? id_expression ; profile_name : (id_expression '.')? id_expression ; sql_statement_shortcut : ALTER SYSTEM | CLUSTER | CONTEXT | DATABASE LINK | DIMENSION | DIRECTORY | INDEX | MATERIALIZED VIEW | NOT EXISTS | OUTLINE | {this.isVersion12()}? PLUGGABLE DATABASE | PROCEDURE | PROFILE | PUBLIC DATABASE LINK | PUBLIC SYNONYM | ROLE | ROLLBACK SEGMENT | SEQUENCE | SESSION | SYNONYM | SYSTEM AUDIT | SYSTEM GRANT | TABLE | TABLESPACE | TRIGGER | TYPE | USER | VIEW | ALTER SEQUENCE | ALTER TABLE | COMMENT TABLE | DELETE TABLE | EXECUTE PROCEDURE | GRANT DIRECTORY | GRANT PROCEDURE | GRANT SEQUENCE | GRANT TABLE | GRANT TYPE | INSERT TABLE | LOCK TABLE | SELECT SEQUENCE | SELECT TABLE | UPDATE TABLE ; drop_index : DROP INDEX index_name (IF EXISTS)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DISASSOCIATE-STATISTICS.html disassociate_statistics : DISASSOCIATE STATISTICS FROM ( COLUMNS (schema_name '.')? tb = id_expression '.' c = id_expression ( ',' (schema_name '.')? tb = id_expression '.' c = id_expression )* | FUNCTIONS (schema_name '.')? fn = id_expression ( ',' (schema_name '.')? fn = id_expression )* | PACKAGES (schema_name '.')? pkg = id_expression ( ',' (schema_name '.')? pkg = id_expression )* | TYPES (schema_name '.')? t = id_expression (',' (schema_name '.')? t = id_expression)* | INDEXES (schema_name '.')? ix = id_expression (',' (schema_name '.')? ix = id_expression)* | INDEXTYPES (schema_name '.')? it = id_expression ( ',' (schema_name '.')? it = id_expression )* ) FORCE? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-INDEXTYPE.html drop_indextype : DROP INDEXTYPE (schema_name '.')? it = id_expression FORCE? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-INMEMORY-JOIN-GROUP.html drop_inmemory_join_group : DROP INMEMORY JOIN GROUP (schema_name '.')? jg = id_expression ; flashback_table : FLASHBACK TABLE tableview_name (',' tableview_name)* TO ( ((SCN | TIMESTAMP) expression | RESTORE POINT restore_point) ((ENABLE | DISABLE) TRIGGERS)? | BEFORE DROP (RENAME TO tableview_name)? ) ; restore_point : identifier ('.' id_expression)* ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/PURGE.html purge_statement : PURGE ( (TABLE | INDEX) id_expression | TABLESPACE SET? ts = id_expression (USER u = id_expression)? | RECYCLEBIN | DBA_RECYCLEBIN ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/NOAUDIT-Traditional-Auditing.html noaudit_statement : NOAUDIT ( audit_operation_clause auditing_by_clause? | audit_schema_object_clause | NETWORK | DIRECT_PATH LOAD auditing_by_clause? ) (WHENEVER NOT? SUCCESSFUL)? container_clause? ; rename_object : RENAME object_name TO object_name ; grant_statement : GRANT (','? (role_name | system_privilege | object_privilege paren_column_list?))+ ( ON grant_object_name )? TO (grantee_name | PUBLIC) (',' (grantee_name | PUBLIC))* (WITH (ADMIN | DELEGATE) OPTION)? ( WITH HIERARCHY OPTION )? (WITH GRANT OPTION)? container_clause? ; container_clause : CONTAINER EQUALS_OP (CURRENT | ALL) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/REVOKE.html revoke_statement : REVOKE ( (revoke_system_privilege | revoke_object_privileges) container_clause? | revoke_roles_from_programs ) ; revoke_system_privilege : (system_privilege | role_name | ALL PRIVILEGES) FROM revokee_clause ; revokee_clause : (id_expression | PUBLIC) (',' (id_expression | PUBLIC))* ; revoke_object_privileges : (object_privilege | ALL PRIVILEGES?) (',' (object_privilege | ALL PRIVILEGES?))* on_object_clause FROM revokee_clause ( CASCADE CONSTRAINTS | FORCE )? ; on_object_clause : ON ( (schema_name '.')? o = id_expression | USER id_expression (',' id_expression)* | DIRECTORY directory_name | EDITION edition_name | MINING MODEL (schema_name '.')? mmn = id_expression | JAVA (SOURCE | RESOURCE) (schema_name '.')? o2 = id_expression | SQL TRANSLATION PROFILE (schema_name '.')? p = id_expression ) ; revoke_roles_from_programs : (role_name (',' role_name)* | ALL) FROM program_unit (',' program_unit)* ; program_unit : (FUNCTION | PROCEDURE | PACKAGE) (schema_name '.')? id_expression ; create_dimension : CREATE DIMENSION identifier level_clause+ ( hierarchy_clause | attribute_clause | extended_attribute_clause )+ ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-DIRECTORY.html create_directory : CREATE (OR REPLACE)? DIRECTORY directory_name (SHARING '=' (METADATA | NONE))? AS directory_path ; directory_name : regular_id ; directory_path : CHAR_STRING ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-INMEMORY-JOIN-GROUP.html create_inmemory_join_group : CREATE INMEMORY JOIN GROUP (schema_name '.')? jg = id_expression '(' (schema_name '.')? t = id_expression '(' c = id_expression ')' ( ',' (schema_name '.')? t = id_expression '(' c = id_expression ')' )+ ')' ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-HIERARCHY.html drop_hierarchy : DROP HIERARCHY (schema_name '.')? hn = id_expression ; // https://docs.oracle.com/cd/E11882_01/appdev.112/e25519/alter_library.htm#LNPLS99946 // https://docs.oracle.com/database/121/LNPLS/alter_library.htm#LNPLS99946 alter_library : ALTER LIBRARY library_name ( COMPILE library_debug? compiler_parameters_clause* (REUSE SETTINGS)? | library_editionable ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-JAVA.html drop_java : DROP JAVA (SOURCE | CLASS | RESOURCE) (schema_name '.')? id_expression ; drop_library : DROP LIBRARY library_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-JAVA.html create_java : CREATE (OR REPLACE)? (AND (RESOLVE | COMPILE))? NOFORCE? JAVA ( (SOURCE | RESOURCE) NAMED (schema_name '.')? pn = id_expression | CLASS (SCHEMA id_expression)? ) (SHARING '=' (METADATA | NONE))? invoker_rights_clause? ( RESOLVER '(' ('(' CHAR_STRING ','? (sn = id_expression | '-') ')')+ ')' )? ( USING ( BFILE '(' d = id_expression ',' filename ')' | (CLOB | BLOB | BFILE) subquery | CHAR_STRING ) | AS CHAR_STRING ) ; create_library : CREATE (OR REPLACE)? (EDITIONABLE | NONEDITIONABLE)? LIBRARY plsql_library_source ; plsql_library_source : library_name (IS | AS) quoted_string (IN directory_name)? (AGENT quoted_string)? ( CREDENTIAL credential_name )? ; credential_name : (id_expression '.')? id_expression ; library_editionable : {this.isVersion12()}? (EDITIONABLE | NONEDITIONABLE) ; library_debug : {this.isVersion12()}? DEBUG ; compiler_parameters_clause : parameter_name EQUALS_OP parameter_value ; parameter_value : regular_id | CHAR_STRING ; library_name : (regular_id '.')? regular_id ; alter_dimension : ALTER DIMENSION identifier ( (ADD (level_clause | hierarchy_clause | attribute_clause | extended_attribute_clause))+ | ( DROP ( LEVEL identifier (RESTRICT | CASCADE)? | HIERARCHY identifier | ATTRIBUTE identifier ( LEVEL identifier (COLUMN column_name (',' COLUMN column_name)*)? )? ) )+ | COMPILE ) ; level_clause : LEVEL identifier IS ( table_name '.' column_name | '(' table_name '.' column_name (',' table_name '.' column_name)* ')' ) (SKIP_ WHEN NULL_)? ; hierarchy_clause : HIERARCHY identifier '(' identifier (CHILD OF identifier)+ dimension_join_clause? ')' ; dimension_join_clause : (JOIN KEY column_one_or_more_sub_clause REFERENCES identifier)+ ; attribute_clause : (ATTRIBUTE identifier DETERMINES column_one_or_more_sub_clause)+ ; extended_attribute_clause : ATTRIBUTE identifier (LEVEL identifier DETERMINES column_one_or_more_sub_clause)+ ; column_one_or_more_sub_clause : column_name | '(' column_name (',' column_name)* ')' ; // https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_4004.htm#SQLRF01104 // https://docs.oracle.com/database/121/SQLRF/statements_4004.htm#SQLRF01104 alter_view : ALTER VIEW tableview_name ( ADD out_of_line_constraint | MODIFY CONSTRAINT constraint_name (RELY | NORELY) | DROP ( CONSTRAINT constraint_name | PRIMARY KEY | UNIQUE '(' column_name (',' column_name)* ')' ) | COMPILE | READ (ONLY | WRITE) | alter_view_editionable? ) ; alter_view_editionable : {this.isVersion12()}? (EDITIONABLE | NONEDITIONABLE) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-VIEW.html create_view : CREATE (OR REPLACE)? (NO? FORCE)? editioning_clause? VIEW (schema_name '.')? v = id_expression ( IF NOT EXISTS )? (SHARING '=' (METADATA | EXTENDED? DATA | NONE))? view_options? ( DEFAULT COLLATION cn = id_expression )? (BEQUEATH (CURRENT_USER | DEFINER))? AS select_only_statement subquery_restriction_clause? ( CONTAINER_MAP | CONTAINERS_DEFAULT )? ; editioning_clause : EDITIONING | EDITIONABLE EDITIONING? | NONEDITIONABLE ; view_options : view_alias_constraint | object_view_clause | xmltype_view_clause ; view_alias_constraint : '(' (','? (table_alias inline_constraint* | out_of_line_constraint))+ ')' ; object_view_clause : OF (schema_name '.')? tn = id_expression ( WITH OBJECT (IDENTIFIER | ID) (DEFAULT | '(' REGULAR_ID (',' REGULAR_ID)* ')') | UNDER (schema_name '.')? sv = id_expression ) ('(' (','? (out_of_line_constraint | REGULAR_ID inline_constraint))+ ')')* ; inline_constraint : (CONSTRAINT constraint_name)? ( NOT? NULL_ | UNIQUE | PRIMARY KEY | references_clause | check_constraint ) constraint_state? ; inline_ref_constraint : SCOPE IS tableview_name | WITH ROWID | (CONSTRAINT constraint_name)? references_clause constraint_state? ; out_of_line_ref_constraint : SCOPE FOR '(' ref_col_or_attr = regular_id ')' IS tableview_name | REF '(' ref_col_or_attr = regular_id ')' WITH ROWID | (CONSTRAINT constraint_name)? FOREIGN KEY '(' (','? ref_col_or_attr = regular_id)+ ')' references_clause constraint_state? ; out_of_line_constraint : ( ((CONSTRAINT | CONSTRAINTS) constraint_name)? ( UNIQUE '(' column_name (',' column_name)* ')' | PRIMARY KEY '(' column_name (',' column_name)* ')' | foreign_key_clause | CHECK '(' condition ')' ) ) constraint_state? parallel_clause? ; constraint_state : ( NOT? DEFERRABLE | INITIALLY (IMMEDIATE | DEFERRED) | (RELY | NORELY) | (ENABLE | DISABLE) | (VALIDATE | NOVALIDATE) | using_index_clause )+ ; xmltype_view_clause : OF XMLTYPE xml_schema_spec? WITH OBJECT (IDENTIFIER | ID) ( DEFAULT | '(' expression (',' expression)* ')' ) ; xml_schema_spec : (XMLSCHEMA xml_schema_url)? ELEMENT (element | xml_schema_url '#' element) ( STORE ALL VARRAYS AS (LOBS | TABLES) )? (allow_or_disallow NONSCHEMA)? (allow_or_disallow ANYSCHEMA)? ; xml_schema_url : DELIMITED_ID ; element : DELIMITED_ID ; alter_tablespace : ALTER TABLESPACE tablespace ( DEFAULT table_compression? storage_clause? | MINIMUM EXTENT size_clause | RESIZE size_clause | COALESCE | SHRINK SPACE_KEYWORD (KEEP size_clause)? | RENAME TO new_tablespace_name | begin_or_end BACKUP | datafile_tempfile_clauses | tablespace_logging_clauses | tablespace_group_clause | tablespace_state_clauses | autoextend_clause | flashback_mode_clause | tablespace_retention_clause ) ; datafile_tempfile_clauses : ADD (datafile_specification | tempfile_specification) | DROP (DATAFILE | TEMPFILE) (filename | UNSIGNED_INTEGER) (KEEP size_clause)? | SHRINK TEMPFILE (filename | UNSIGNED_INTEGER) (KEEP size_clause)? | RENAME DATAFILE filename (',' filename)* TO filename (',' filename)* | (DATAFILE | TEMPFILE) (online_or_offline) ; tablespace_logging_clauses : logging_clause | NO? FORCE LOGGING ; tablespace_group_clause : TABLESPACE GROUP (tablespace_group_name | CHAR_STRING) ; tablespace_group_name : regular_id ; tablespace_state_clauses : ONLINE | OFFLINE (NORMAL | TEMPORARY | IMMEDIATE)? | READ (ONLY | WRITE) | PERMANENT | TEMPORARY ; flashback_mode_clause : FLASHBACK (ON | OFF) ; new_tablespace_name : tablespace ; create_tablespace : CREATE (BIGFILE | SMALLFILE)? ( permanent_tablespace_clause | temporary_tablespace_clause | undo_tablespace_clause ) ; permanent_tablespace_clause : TABLESPACE id_expression (IF NOT EXISTS)? datafile_specification? ( MINIMUM EXTENT size_clause | BLOCKSIZE size_clause | logging_clause | FORCE LOGGING | (ONLINE | OFFLINE) | ENCRYPTION tablespace_encryption_spec | DEFAULT //TODO table_compression? storage_clause? | extent_management_clause | segment_management_clause | flashback_mode_clause )* ; tablespace_encryption_spec : USING encrypt_algorithm = CHAR_STRING ; logging_clause : LOGGING | NOLOGGING | FILESYSTEM_LIKE_LOGGING ; extent_management_clause : EXTENT MANAGEMENT LOCAL (AUTOALLOCATE | UNIFORM (SIZE size_clause)?)? ; segment_management_clause : SEGMENT SPACE_KEYWORD MANAGEMENT (AUTO | MANUAL) ; temporary_tablespace_clause : TEMPORARY TABLESPACE tablespace_name = id_expression (IF NOT EXISTS)? tempfile_specification? tablespace_group_clause? extent_management_clause? ; undo_tablespace_clause : UNDO TABLESPACE tablespace_name = id_expression (IF NOT EXISTS)? datafile_specification? extent_management_clause? tablespace_retention_clause? ; tablespace_retention_clause : RETENTION (GUARANTEE | NOGUARANTEE) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-TABLESPACE-SET.html create_tablespace_set : CREATE TABLESPACE SET tss = id_expression (IN SHARDSPACE ss = id_expression)? ( USING TEMPLATE '(' (DATAFILE file_specification (',' file_specification)*)? permanent_tablespace_attrs+ ')' )? ; permanent_tablespace_attrs : MINIMUM EXTENT size_clause | BLOCKSIZE numeric K_LETTER? | logging_clause | FORCE LOGGING | tablespace_encryption_clause | default_tablespace_params | ONLINE | OFFLINE | extent_management_clause | segment_management_clause | flashback_mode_clause | lost_write_protection ; tablespace_encryption_clause : ENCRYPTION (tablespace_encryption_spec? ENCRYPT | DECRYPT) ; default_tablespace_params : DEFAULT default_table_compression? default_index_compression? inmmemory_clause? ilm_clause? storage_clause? ; default_table_compression : TABLE (COMPRESS FOR (OLTP | QUERY low_high | ARCHIVE low_high) | NOCOMPRESS) ; low_high : LOW | HIGH ; default_index_compression : INDEX (COMPRESS ADVANCED low_high | NOCOMPRESS) ; inmmemory_clause : INMEMORY inmemory_attributes? ( TEXT ( column_name (',' column_name)* | column_name USING policy_name (',' column_name USING policy_name)* ) )? | NO INMEMORY ; // asm_filename is just a charater string. Would need to parse the string // to find diskgroup... datafile_specification : DATAFILE (','? datafile_tempfile_spec) ; tempfile_specification : TEMPFILE (','? datafile_tempfile_spec) ; datafile_tempfile_spec : CHAR_STRING? (SIZE size_clause)? REUSE? autoextend_clause? ; redo_log_file_spec : (filename | '(' filename (',' filename)* ')') (SIZE size_clause)? (BLOCKSIZE size_clause)? REUSE? ; autoextend_clause : AUTOEXTEND (OFF | ON (NEXT size_clause)? maxsize_clause?) ; maxsize_clause : MAXSIZE (UNLIMITED | size_clause) ; build_clause : BUILD (IMMEDIATE | DEFERRED) ; parallel_clause : NOPARALLEL | PARALLEL ( parallel_count = UNSIGNED_INTEGER parallel_instances_clause? // Deprecated, legacy format from Oracle 8 and prior, and while this is no longer documented, // the DEGREE syntax continues to be accepted by the database engine. | '(' DEGREE parallel_count = UNSIGNED_INTEGER parallel_instances_clause? ')' )? ; // This is Oracle RAC specific. // In modern Oracle, parallelism is controlled by the database initialization parameter PARALLEL_DEGREE_POLICY, // however, the database continues to accept and record this SQL syntax if its used. parallel_instances_clause : INSTANCES (UNSIGNED_INTEGER | DEFAULT) ; alter_materialized_view : ALTER MATERIALIZED VIEW tableview_name ( physical_attributes_clause | modify_mv_column_clause | table_compression | lob_storage_clause (',' lob_storage_clause)* | modify_lob_storage_clause (',' modify_lob_storage_clause)* //TODO | alter_table_partitioning | parallel_clause | logging_clause | allocate_extent_clause | deallocate_unused_clause | shrink_clause | (cache_or_nocache) )? alter_iot_clauses? (USING INDEX physical_attributes_clause)? alter_mv_option1? ( enable_or_disable QUERY REWRITE | COMPILE | CONSIDER FRESH )? ; alter_mv_option1 : alter_mv_refresh //TODO | MODIFY scoped_table_ref_constraint ; alter_mv_refresh : REFRESH ( FAST | COMPLETE | FORCE | ON (DEMAND | COMMIT) | START WITH expression | NEXT expression | WITH PRIMARY KEY | USING DEFAULT? MASTER ROLLBACK SEGMENT rollback_segment? | USING (ENFORCED | TRUSTED) CONSTRAINTS )+ ; rollback_segment : regular_id ; modify_mv_column_clause : MODIFY '(' column_name (ENCRYPT encryption_spec | DECRYPT)? ')' ; alter_materialized_view_log : ALTER MATERIALIZED VIEW LOG FORCE? ON tableview_name ( physical_attributes_clause | add_mv_log_column_clause //TODO | alter_table_partitioning | parallel_clause | logging_clause | allocate_extent_clause | shrink_clause | move_mv_log_clause | cache_or_nocache )? mv_log_augmentation? mv_log_purge_clause? ; add_mv_log_column_clause : ADD '(' column_name ')' ; move_mv_log_clause : MOVE segment_attributes_clause parallel_clause? ; mv_log_augmentation : ADD ( (OBJECT ID | PRIMARY KEY | ROWID | SEQUENCE) ('(' column_name (',' column_name)* ')')? | '(' column_name (',' column_name)* ')' ) new_values_clause? ; create_materialized_view_log : CREATE MATERIALIZED VIEW LOG ON tableview_name ( ( physical_attributes_clause | TABLESPACE tablespace_name = id_expression | logging_clause | (CACHE | NOCACHE) )+ )? parallel_clause? // table_partitioning_clauses TODO ( WITH (','? ( OBJECT ID | PRIMARY KEY | ROWID | SEQUENCE | COMMIT SCN))* ( '(' ( ','? regular_id)+ ')' new_values_clause? )? mv_log_purge_clause? )* ; new_values_clause : (INCLUDING | EXCLUDING) NEW VALUES ; mv_log_purge_clause : PURGE ( IMMEDIATE (SYNCHRONOUS | ASYNCHRONOUS)? // |START WITH CLAUSES TODO ) ; create_materialized_zonemap : CREATE MATERIALIZED ZONEMAP zonemap_name (LEFT_PAREN column_list RIGHT_PAREN)? zonemap_attributes? zonemap_refresh_clause? ( (ENABLE | DISABLE) PRUNING )? (create_zonemap_on_table | create_zonemap_as_subquery) ; alter_materialized_zonemap : ALTER MATERIALIZED ZONEMAP zonemap_name ( zonemap_attributes | zonemap_refresh_clause | (ENABLE | DISABLE) PRUNING | COMPILE | REBUILD | UNUSABLE ) ; drop_materialized_zonemap : DROP MATERIALIZED ZONEMAP zonemap_name ; zonemap_refresh_clause : REFRESH (FAST | COMPILE | FORCE)? ( ON (DEMAND | COMMIT | LOAD | DATA MOVEMENT | LOAD DATA MOVEMENT) )? ; zonemap_attributes : ( PCTFREE numeric | PCTUSED numeric | SCALE numeric | TABLESPACE tablespace | (CACHE | NOCACHE) )+ ; zonemap_name : identifier ('.' id_expression)? ; operator_name : identifier ('.' id_expression)? ; operator_function_name : identifier ('.' id_expression)* ; create_zonemap_on_table : ON tableview_name LEFT_PAREN column_list RIGHT_PAREN ; create_zonemap_as_subquery : AS subquery ; alter_operator : ALTER OPERATOR operator_name (add_binding_clause | drop_binding_clause | COMPILE) ; drop_operator : DROP OPERATOR operator_name FORCE? ; create_operator : CREATE (OR REPLACE)? OPERATOR operator_name BINDING binding_clause (COMMA binding_clause)* ( SHARING '=' (METADATA | NONE) )? ; binding_clause : LEFT_PAREN datatype (COMMA datatype)* RIGHT_PAREN RETURN LEFT_PAREN? datatype RIGHT_PAREN? implementation_clause? using_function_clause ; add_binding_clause : ADD BINDING binding_clause ; implementation_clause : ANCILLARY TO primary_operator_list | operator_context_clause ; primary_operator_list : primary_operator_item (COMMA primary_operator_item)* ; primary_operator_item : schema_object_name LEFT_PAREN datatype (COMMA datatype)* RIGHT_PAREN ; operator_context_clause : WITH INDEX CONTEXT COMMA SCAN CONTEXT implementation_type_name (COMPUTE ANCILLARY DATA)? ( WITH COLUMN CONTEXT )? ; using_function_clause : USING operator_function_name ; drop_binding_clause : DROP BINDING LEFT_PAREN datatype (COMMA datatype)* RIGHT_PAREN FORCE? ; create_materialized_view : CREATE MATERIALIZED VIEW tableview_name (OF type_name)? ( '(' (scoped_table_ref_constraint | mv_column_alias) ( ',' (scoped_table_ref_constraint | mv_column_alias) )* ')' )? ( ON PREBUILT TABLE ( (WITH | WITHOUT) REDUCED PRECISION)? | physical_properties? (CACHE | NOCACHE)? parallel_clause? build_clause? ) ( USING INDEX ((physical_attributes_clause | TABLESPACE mv_tablespace = id_expression)+)* | USING NO INDEX )? create_mv_refresh? (FOR UPDATE)? ((DISABLE | ENABLE) QUERY REWRITE)? AS select_only_statement ; scoped_table_ref_constraint : SCOPE FOR '(' ref_column_or_attribute = identifier ')' IS (schema_name '.')? scope_table_name_or_c_alias = identifier ; mv_column_alias : (identifier | quoted_string) (ENCRYPT encryption_spec)? ; create_mv_refresh : ( NEVER REFRESH | REFRESH ( (FAST | COMPLETE | FORCE) | ON (DEMAND | COMMIT) | (START WITH | NEXT) //date goes here TODO | WITH (PRIMARY KEY | ROWID) | USING ( DEFAULT (MASTER | LOCAL)? ROLLBACK SEGMENT | (MASTER | LOCAL)? ROLLBACK SEGMENT rb_segment = REGULAR_ID ) | USING (ENFORCED | TRUSTED) CONSTRAINTS )+ ) ; drop_materialized_view : DROP MATERIALIZED VIEW tableview_name (PRESERVE TABLE)? ; drop_materialized_view_log : DROP MATERIALIZED VIEW LOG (IF EXISTS)? ON tableview_name ; create_context : CREATE (OR REPLACE)? CONTEXT oracle_namespace USING (schema_object_name '.')? package_name ( INITIALIZED (EXTERNALLY | GLOBALLY) | ACCESSED GLOBALLY )? ; oracle_namespace : id_expression ; //https://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_5001.htm#SQLRF01201 create_cluster : CREATE CLUSTER cluster_name '(' column_name datatype SORT? (',' column_name datatype SORT?)* ')' ( physical_attributes_clause | SIZE size_clause | TABLESPACE tablespace | INDEX | (SINGLE TABLE)? HASHKEYS UNSIGNED_INTEGER (HASH IS expression)? )* parallel_clause? (ROWDEPENDENCIES | NOROWDEPENDENCIES)? (CACHE | NOCACHE)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-PROFILE.html create_profile : CREATE MANDATORY? PROFILE p = id_expression LIMIT (resource_parameters | password_parameters)+ container_clause? ; resource_parameters : ( SESSIONS_PER_USER | CPU_PER_SESSION | CPU_PER_CALL | CONNECT_TIME | IDLE_TIME | LOGICAL_READS_PER_SESSION | LOGICAL_READS_PER_CALL | COMPOSITE_LIMIT ) (UNSIGNED_INTEGER | UNLIMITED | DEFAULT) | PRIVATE_SGA (size_clause | UNLIMITED | DEFAULT) ; password_parameters : ( FAILED_LOGIN_ATTEMPTS | PASSWORD_LIFE_TIME | PASSWORD_REUSE_TIME | PASSWORD_REUSE_MAX | PASSWORD_LOCK_TIME | PASSWORD_GRACE_TIME | INACTIVE_ACCOUNT_TIME ) (expression | UNLIMITED | DEFAULT) | PASSWORD_VERIFY_FUNCTION (function_name | NULL_ | DEFAULT) | PASSWORD_ROLLOVER_TIME (expression | DEFAULT) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-LOCKDOWN-PROFILE.html create_lockdown_profile : CREATE LOCKDOWN PROFILE id_expression (static_base_profile | dynamic_base_profile)? ; static_base_profile : FROM bp = id_expression ; dynamic_base_profile : INCLUDING bp = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-OUTLINE.html create_outline : CREATE (OR REPLACE)? (PUBLIC | PRIVATE)? OUTLINE (o = id_expression)? ( FROM (PUBLIC | PRIVATE)? so = id_expression )? (FOR CATEGORY c = id_expression)? (ON statement)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-RESTORE-POINT.html create_restore_point : CREATE CLEAN? RESTORE POINT rp = id_expression (FOR PLUGGABLE DATABASE pdb = id_expression)? ( AS OF (TIMESTAMP | SCN) expression )? (PRESERVE | GUARANTEE FLASHBACK DATABASE)? ; create_role : CREATE ROLE role_name role_identified_clause? container_clause? ; create_table : CREATE ( (GLOBAL | PRIVATE) TEMPORARY | SHARDED | DUPLICATED | IMMUTABLE? BLOCKCHAIN | IMMUTABLE )? TABLE (schema_name '.')? table_name (IF NOT EXISTS)? ( SHARING '=' (METADATA | EXTENDED? DATA | NONE) )? (relational_table | xmltype_table | object_table) memoptimize_read_write_clause? ( PARENT tableview_name )? (USAGE QUEUE)? ; xmltype_table : OF XMLTYPE ('(' object_properties ')')? (XMLTYPE xmltype_storage)? xmlschema_spec? xmltype_virtual_columns? ( ON COMMIT (DELETE | PRESERVE) ROWS )? oid_clause? oid_index_clause? physical_properties? table_properties? ; xmltype_virtual_columns : VIRTUAL COLUMNS '(' column_name AS '(' expression ')' (',' column_name AS '(' expression ')')* ')' ; xmltype_column_properties : XMLTYPE COLUMN? column_name xmltype_storage? xmlschema_spec? ; xmltype_storage : STORE AS ( OBJECT RELATIONAL | (SECUREFILE | BASICFILE)? (CLOB | BINARY XML) ( lob_segname ('(' lob_parameters ')')? | '(' lob_parameters ')' )? ) | STORE VARRAYS AS (LOBS | TABLES) ; xmlschema_spec : (XMLSCHEMA DELIMITED_ID)? ELEMENT DELIMITED_ID (allow_or_disallow NONSCHEMA)? ( allow_or_disallow ANYSCHEMA )? ; object_table : OF (schema_name '.')? object_type object_table_substitution? ( '(' object_properties (',' object_properties)* ')' )? (ON COMMIT (DELETE | PRESERVE) ROWS)? oid_clause? oid_index_clause? physical_properties? table_properties? ; object_type : regular_id ; oid_index_clause : OIDINDEX index_name? '(' (physical_attributes_clause | TABLESPACE tablespace)+ ')' ; oid_clause : OBJECT IDENTIFIER IS (SYSTEM GENERATED | PRIMARY KEY) ; object_properties : (column_name | attribute_name) (DEFAULT expression)? ( inline_constraint (',' inline_constraint)* | inline_ref_constraint )? | out_of_line_constraint | out_of_line_ref_constraint | supplemental_logging_props ; object_table_substitution : NOT? SUBSTITUTABLE AT ALL LEVELS ; relational_table : ('(' relational_property (',' relational_property)* ')')? relational_table_properties? ; relational_table_properties : relational_table_property+ ; relational_table_property : immutable_table_clauses | blockchain_table_clauses | DEFAULT COLLATION collation_name | ON COMMIT ((DROP | PRESERVE) DEFINITION | (DELETE | PRESERVE) ROWS) | physical_properties | table_properties ; immutable_table_clauses : immutable_table_no_drop_clause | immutable_table_no_delete_clause ; immutable_table_no_drop_clause : NO DROP (UNTIL numeric DAYS IDLE)? ; immutable_table_no_delete_clause : NO DELETE (LOCKED? | UNTIL numeric DAYS AFTER INSERT LOCKED?) ; blockchain_table_clauses : blockchain_drop_table_clause blockchain_row_retention_clause blockchain_hash_and_data_format_clause ; blockchain_drop_table_clause : NO DROP (UNTIL numeric DAYS IDLE)? ; blockchain_row_retention_clause : NO DELETE (LOCKED? | UNTIL numeric DAYS AFTER INSERT LOCKED?) ; blockchain_hash_and_data_format_clause : HASHING USING SHA2_512_Q VERSION V1_Q ; collation_name : identifier ; // While Oracle's documented grammar defines an explicit order of clauses, in practice these clauses can // be specified in any order. This rule is designed to follow the grammar intent, and so semantic checks // should exist in the listeners to deal with concepts such as duplicates. table_properties : column_properties | read_only_clause | indexing_clause | table_partitioning_clauses | attribute_clustering_clause | (CACHE | NOCACHE) | result_cache_clause | parallel_clause | monitoring_nomonitoring | (ROWDEPENDENCIES | NOROWDEPENDENCIES) | enable_disable_clause | row_movement_clause | logical_replication_clause | flashback_archive_clause | physical_properties | ROW ARCHIVAL | AS select_only_statement | FOR EXCHANGE WITH TABLE (schema_name '.')? table_name | annotations_clause ; read_only_clause : READ (ONLY | WRITE) ; indexing_clause : INDEXING (ON | OFF) ; attribute_clustering_clause : CLUSTERING clustering_join? cluster_clause (yes_no? ON LOAD)? (yes_no? ON DATA MOVEMENT)? zonemap_clause? ; clustering_join : (schema_name '.')? table_name clustering_join_item (',' clustering_join_item)* ; clustering_join_item : JOIN (schema_name '.')? table_name ON '(' equijoin_condition ')' ; equijoin_condition : expression ; cluster_clause : BY (LINEAR | INTERLEAVED)? ORDER clustering_columns ; clustering_columns : clustering_column_group | '(' clustering_column_group (',' clustering_column_group)* ')' ; clustering_column_group : '(' column_name (',' column_name)* ')' ; yes_no : YES | NO ; zonemap_clause : WITH MATERIALIZED ZONEMAP ('(' zonemap_name ')')? | WITHOUT MATERIALIZED ZONEMAP ; logical_replication_clause : DISABLE LOGICAL REPLICATION | ENABLE LOGICAL REPLICATION ( (ALL | ALLOW NOVALIDATE) KEYS | NO? PARTIAL JSON )? ; table_name : identifier ; relational_property : out_of_line_constraint | out_of_line_ref_constraint | column_definition | virtual_column_definition | period_definition | supplemental_logging_props ; table_partitioning_clauses : range_partitions | list_partitions | hash_partitions | composite_range_partitions | composite_list_partitions | composite_hash_partitions | reference_partitioning | system_partitioning ; range_partitions : PARTITION BY RANGE '(' column_name (',' column_name)* ')' ( INTERVAL '(' expression ')' (STORE IN '(' tablespace (',' tablespace)* ')')? )? '(' PARTITION partition_name? range_values_clause table_partition_description ( ',' PARTITION partition_name? range_values_clause table_partition_description )* ')' ; list_partitions : PARTITION BY LIST '(' column_name ')' ( AUTOMATIC (STORE IN '(' tablespace (',' tablespace)* ')')? )? ( '(' PARTITION partition_name? list_values_clause table_partition_description ( ',' PARTITION partition_name? list_values_clause table_partition_description )* ')' )? ; hash_partitions : PARTITION BY HASH '(' column_name (',' column_name)* ')' ( individual_hash_partitions | hash_partitions_by_quantity ) ; individual_hash_partitions : '(' PARTITION partition_name? partitioning_storage_clause? ( ',' PARTITION partition_name? partitioning_storage_clause? )* ')' ; hash_partitions_by_quantity : PARTITIONS hash_partition_quantity (STORE IN '(' tablespace (',' tablespace)* ')')? ( table_compression | key_compression )? (OVERFLOW_ STORE IN '(' tablespace (',' tablespace)* ')')? ; hash_partition_quantity : UNSIGNED_INTEGER ; composite_range_partitions : PARTITION BY RANGE '(' column_name (',' column_name)* ')' ( INTERVAL '(' expression ')' (STORE IN '(' tablespace (',' tablespace)* ')')? )? (subpartition_by_range | subpartition_by_list | subpartition_by_hash) '(' range_partition_desc ( ',' range_partition_desc )* ')' ; composite_list_partitions : PARTITION BY LIST '(' column_name ')' ( subpartition_by_range | subpartition_by_list | subpartition_by_hash ) '(' list_partition_desc (',' list_partition_desc)* ')' ; composite_hash_partitions : PARTITION BY HASH '(' (',' column_name)+ ')' ( subpartition_by_range | subpartition_by_list | subpartition_by_hash ) (individual_hash_partitions | hash_partitions_by_quantity) ; reference_partitioning : PARTITION BY REFERENCE '(' constraint_name ')' ( '(' reference_partition_desc (',' reference_partition_desc)* ')' )? ; reference_partition_desc : PARTITION partition_name? table_partition_description ; system_partitioning : PARTITION BY SYSTEM ( PARTITIONS UNSIGNED_INTEGER | reference_partition_desc (',' reference_partition_desc)* )? ; range_partition_desc : PARTITION partition_name? range_values_clause? table_partition_description ( ( '(' ( range_subpartition_desc (',' range_subpartition_desc)* | list_subpartition_desc (',' list_subpartition_desc)* | individual_hash_subparts (',' individual_hash_subparts)* ) ')' | hash_subparts_by_quantity ) )? ; list_partition_desc : PARTITION partition_name? list_values_clause? table_partition_description ( ( '(' ( range_subpartition_desc (',' range_subpartition_desc)* | list_subpartition_desc (',' list_subpartition_desc)* | individual_hash_subparts (',' individual_hash_subparts)* ) ')' | hash_subparts_by_quantity ) )? ; subpartition_template : SUBPARTITION TEMPLATE ( ( '(' ( range_subpartition_desc (',' range_subpartition_desc)* | list_subpartition_desc (',' list_subpartition_desc)* | individual_hash_subparts (',' individual_hash_subparts)* ) ')' | hash_subpartition_quantity ) ) ; hash_subpartition_quantity : UNSIGNED_INTEGER ; subpartition_by_range : SUBPARTITION BY RANGE '(' column_name (',' column_name)* ')' subpartition_template? ; subpartition_by_list : SUBPARTITION BY LIST '(' column_name ')' subpartition_template? ; subpartition_by_hash : SUBPARTITION BY HASH '(' column_name (',' column_name)* ')' ( SUBPARTITIONS UNSIGNED_INTEGER (STORE IN '(' tablespace (',' tablespace)* ')')? | subpartition_template )? ; subpartition_name : partition_name ; range_subpartition_desc : SUBPARTITION subpartition_name? range_values_clause partitioning_storage_clause? ; list_subpartition_desc : SUBPARTITION subpartition_name? list_values_clause partitioning_storage_clause? ; individual_hash_subparts : SUBPARTITION subpartition_name? partitioning_storage_clause? ; hash_subparts_by_quantity : SUBPARTITIONS UNSIGNED_INTEGER (STORE IN '(' tablespace (',' tablespace)* ')')? ; range_values_clause : VALUES LESS THAN '(' range_values_list ')' ; range_values_list : literal (',' literal)* | TIMESTAMP literal (',' TIMESTAMP literal)* ; list_values_clause : VALUES '(' (literal (',' literal)* | TIMESTAMP literal (',' TIMESTAMP literal)* | DEFAULT) ')' ; table_partition_description : (INTERNAL | EXTERNAL)? deferred_segment_creation? read_only_clause? indexing_clause? segment_attributes_clause? ( table_compression | key_compression )? inmemory_table_clause? ilm_clause? ( OVERFLOW_ segment_attributes_clause? )? (lob_storage_clause | varray_col_properties | nested_table_col_properties)* ; partitioning_storage_clause : ( TABLESPACE tablespace | OVERFLOW_ (TABLESPACE tablespace)? | table_compression | key_compression | inmemory_table_clause | lob_partitioning_storage | VARRAY varray_item STORE AS (BASICFILE | SECUREFILE)? LOB lob_segname )+ ; lob_partitioning_storage : LOB '(' lob_item ')' STORE AS (BASICFILE | SECUREFILE)? ( lob_segname ('(' TABLESPACE tablespace ')')? | '(' TABLESPACE tablespace ')' ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/size_clause.html // Technically, this should only allow 'K' | 'M' | 'G' | 'T' | 'P' | 'E' // but having issues with examples/numbers01.sql line 11 "sysdate -1m" size_clause : UNSIGNED_INTEGER (K_LETTER | M_LETTER | G_LETTER | T_LETTER | P_LETTER | E_LETTER)? ; table_compression : COMPRESS ( BASIC | FOR ( OLTP | (QUERY | ARCHIVE) (LOW | HIGH)? | ALL OPERATIONS | DIRECT_LOAD OPERATIONS ) )? | ROW STORE COMPRESS (BASIC | ADVANCED)? | COLUMN STORE COMPRESS (FOR (QUERY | ARCHIVE) (LOW | HIGH)?)? (NO? ROW LEVEL LOCKING)? | NOCOMPRESS ; // avoid to match an empty string in inmemory_table_clause : inmemory_column_clause+ | (INMEMORY inmemory_attributes? | NO INMEMORY) inmemory_column_clause* ; inmemory_attributes : ( inmemory_memcompress | inmemory_priority | inmemory_distribute | inmemory_duplicate )+ ; inmemory_memcompress : MEMCOMPRESS FOR (DML | (QUERY | CAPACITY) (LOW | HIGH)?) | NO MEMCOMPRESS ; inmemory_priority : PRIORITY (NONE | LOW | MEDIUM | HIGH | CRITICAL) ; inmemory_distribute : DISTRIBUTE (AUTO | BY (ROWID RANGE | PARTITION | SUBPARTITION))? ( FOR SERVICE (DEFAULT | ALL | identifier | NONE) )? ; inmemory_duplicate : DUPLICATE ALL? | NO DUPLICATE ; inmemory_column_clause : (INMEMORY inmemory_memcompress? | NO INMEMORY) '(' column_list ')' ; physical_attributes_clause : ( PCTFREE pctfree = UNSIGNED_INTEGER | PCTUSED pctused = UNSIGNED_INTEGER | INITRANS inittrans = UNSIGNED_INTEGER | MAXTRANS maxtrans = UNSIGNED_INTEGER | storage_clause | compute_clauses )+ ; storage_clause : STORAGE '(' ( INITIAL initial_size = size_clause | NEXT next_size = size_clause | MINEXTENTS minextents = (UNSIGNED_INTEGER | UNLIMITED) | MAXEXTENTS minextents = (UNSIGNED_INTEGER | UNLIMITED) | PCTINCREASE pctincrease = UNSIGNED_INTEGER | FREELISTS freelists = UNSIGNED_INTEGER | FREELIST GROUPS freelist_groups = UNSIGNED_INTEGER | OPTIMAL (size_clause | NULL_) | BUFFER_POOL (KEEP | RECYCLE | DEFAULT) | FLASH_CACHE (KEEP | NONE | DEFAULT) | CELL_FLASH_CACHE (KEEP | NONE | DEFAULT) | ENCRYPT )+ ')' ; deferred_segment_creation : SEGMENT CREATION (IMMEDIATE | DEFERRED) ; segment_attributes_clause : ( physical_attributes_clause | TABLESPACE (tablespace_name = id_expression | SET? identifier) | table_compression | logging_clause )+ ; physical_properties : deferred_segment_creation | segment_attributes_clause | table_compression | inmemory_table_clause | ilm_clause | ORGANIZATION ( HEAP segment_attributes_clause? heap_org_table_clause | INDEX segment_attributes_clause? index_org_table_clause? | EXTERNAL external_table_clause ) | EXTERNAL PARTITION ATTRIBUTES external_table_clause (REJECT LIMIT)? | CLUSTER cluster_name '(' column_name (',' column_name)* ')' ; ilm_clause : ILM ( ADD POLICY ilm_policy_clause | (DELETE | ENABLE | DISABLE) POLICY ilm_policy_clause | DELETE_ALL | ENABLE_ALL | DISABLE_ALL ) ; ilm_policy_clause : ilm_compression_policy | ilm_tiering_policy | ilm_inmemory_policy ; ilm_compression_policy : table_compression segment_group ilm_after_on | ((ROW | COLUMN) STORE COMPRESS (ADVANCED | FOR QUERY)) ROW AFTER ilm_time_period OF NO MODIFICATION ; ilm_tiering_policy : TIER TO tablespace ( segment_group? (ON function_name)? | READ ONLY segment_group? ilm_after_on ) ; ilm_after_on : AFTER ilm_time_period OF (NO (ACCESS | MODIFICATION) | CREATION) | ON function_name ; segment_group : SEGMENT | GROUP ; ilm_inmemory_policy : (SET INMEMORY inmemory_attributes? | MODIFY INMEMORY inmemory_memcompress | NO INMEMORY) SEGMENT? ilm_after_on ; ilm_time_period : numeric (DAY | DAYS | MONTH | MONTHS | YEAR | YEARS) ; heap_org_table_clause : table_compression? inmemory_table_clause? ilm_clause? ; external_table_clause : '(' (TYPE access_driver_type)? external_table_data_props ')' parallel_clause? ( REJECT LIMIT (numeric | UNLIMITED) )? inmemory_table_clause? ; access_driver_type : ORACLE_LOADER | ORACLE_DATAPUMP | ORACLE_HDFS | ORACLE_HIVE ; external_table_data_props : (DEFAULT DIRECTORY external_table_directory)? ( ACCESS PARAMETERS ( '(' CHAR_STRING ')' | '(' external_table_data_format+ ')' | USING CLOB select_only_statement ) )? (LOCATION '(' external_table_directory (',' external_table_directory)* ')')? ; external_table_data_format : RECORDS DELIMITED BY NEWLINE_ | COLUMN TRANSFORMS '(' external_table_transform (',' external_table_transform)* ')' | external_table_records | external_table_fields | external_table_datapump | external_table_hive ; external_table_transform : column_name FROM ( NULL_ | CONSTANT quoted_string | (CONCAT | LOBFILE) (external_table_field | CONSTANT quoted_string) | ( FROM '(' external_table_directory (',' external_table_directory)* ')' | CLOB | BLOB | CHARACTERSET '=' char_set_name ) | STARTOF external_table_field_list '(' UNSIGNED_INTEGER ')' ) ; external_table_field : column_name type_name? (NOT NULL_)? default_value_part? ; external_table_field_list : external_table_fields_clause (',' external_table_fields_clause)* ; external_table_fields_clause : external_table_field ( external_table_position_clause | external_table_datatype_clause | external_table_init_clause | external_table_lls_clause )* ; external_table_position_clause : POSITION? '(' ('*'? ('+' | '-')? UNSIGNED_INTEGER?) (BINDVAR | (':' ('+' | '-')? UNSIGNED_INTEGER)) ')' ; external_table_datatype_clause : UNSIGNED? INTEGER EXTERNAL? UNSIGNED_INTEGER? external_table_delimit_clause? | (DECIMAL | ZONED) ( '(' UNSIGNED_INTEGER (',' UNSIGNED_INTEGER)? ')' | EXTERNAL ('(' UNSIGNED_INTEGER ')')? external_table_delimit_clause? ) | ORACLE_DATE | ORACLE_NUMBER COUNTED? | FLOAT EXTERNAL? UNSIGNED_INTEGER? external_table_delimit_clause? | DOUBLE | BINARY_FLOAT EXTERNAL? UNSIGNED_INTEGER? external_table_delimit_clause? | BINARY_DOUBLE | RAW UNSIGNED_INTEGER? | CHAR EXTERNAL? ('(' UNSIGNED_INTEGER ')' )? external_table_delimit_clause? external_table_trim_clause? external_table_date_format_clause? | (VARCHAR | VARRAW | VARCHARC | VARRAWC) '(' (UNSIGNED_INTEGER ',')? UNSIGNED_INTEGER ')' ; external_table_delimit_clause : ENCLOSED BY quoted_string (AND quoted_string)? | TERMINATED BY (quoted_string | WHITESPACE) (OPTIONALLY? ENCLOSED BY quoted_string (AND quoted_string)?)? ; external_table_trim_clause : LRTRIM | NOTRIM | LTRIM | RTRIM | LDRTRIM ; external_table_date_format_clause : DATE_FORMAT? ( DATE | TIMESTAMP (WITH LOCAL? TIME ZONE)? MASK quoted_string | INTERVAL (YEAR_TO_MONTH | DAY_TO_SECOND) ) ; external_table_init_clause : (DEFAULTIF | NULLIF) external_table_condition_clause ; external_table_condition_clause : (field_spec | '(' UNSIGNED_INTEGER BINDVAR ')') relational_operator (quoted_string | HEX_STRING_LIT | BLANKS) | external_table_condition_clause (AND | OR) external_table_condition_clause ; external_table_lls_clause : LLS external_table_directory ; external_table_records : RECORDS ( FIXED UNSIGNED_INTEGER | VARIABLE UNSIGNED_INTEGER | DELIMITED BY (DETECTED? NEWLINE_ | quoted_string) | XMLTAG '('? id_expression (',' id_expression)* ')'? ) external_table_record_options_clause* | external_table_record_options_clause+ ; external_table_record_options_clause : CHARACTERSET char_set_name | EXTERNAL VARIABLE DATA | PREPROCESSOR external_table_directory | DATA IS (LITTLE | BIG) ENDIAN | BYTEORDERMARK (CHECK | NOCHECK) | STRING SIZES ARE IN (BYTES | CHARACTERS) | LOAD WHEN external_table_condition_clause | external_table_output_files | READSIZE '='? UNSIGNED_INTEGER | DISABLE_DIRECTORY_LINK_CHECK | DATE_CACHE UNSIGNED_INTEGER | SKIP_ UNSIGNED_INTEGER | IO_OPTIONS (DIRECTIO | NODIRECTIO) | (DNFS_ENABLE | DNFS_DISABLE) | DNFS_READBUFFERS UNSIGNED_INTEGER ; external_table_output_files : ( (NOBADFILE | NODISCARDFILE | NOLOGFILE) | (BADFILE | DISCARDFILE | LOGFILE) external_table_directory? filename ) ; external_table_fields : FIELDS IGNORE_CHARS_AFTER_EOR? (CSV (WITH | WITHOUT) EMBEDDED)? external_table_delimit_clause? external_table_trim_clause? (ALL FIELDS OVERRIDE THESE FIELDS)? (MISSING FIELD VALUES ARE NULL_)? (REJECT ROWS WITH ALL NULL_ FIELDS)? (DATE_FORMAT (DATE | TIMESTAMP) MASK quoted_string)? (NULLIF (EQUALS_OP | NOT_EQUAL_OP) (quoted_string | HEX_STRING_LIT | BLANKS) | NONULLIF)? '('? external_table_field_list? ')'? ; external_table_datapump : ENCRYPTION (ENABLE | DISABLED) | NOLOGFILE | LOGFILE external_table_directory? filename | COMPRESSION (ENABLED (BASIC | LOW | MEDIUM | HIGH)? | DISABLED)? | HADOOP_TRAILERS (ENABLED | DISABLED) VERSION (COMPATIBLE | LATEST | quoted_string) | NOLOG | DEBUG '=' '(' UNSIGNED_INTEGER ',' UNSIGNED_INTEGER ')' | DATAPUMP INTERNAL TABLE tableview_name | TEMPLATE_TABLE tableview_name | JOB '(' schema_name ',' tableview_name ',' UNSIGNED_INTEGER ')' | WORKERID UNSIGNED_INTEGER | PARALLEL UNSIGNED_INTEGER | VERSION quoted_string | ENCRYPTPASSWORDISNULL | DBLINK quoted_string ; external_table_hive : id_expression ('.' id_expression)* ('=' | ':') ( tableview_name | external_table_hive_parameter_map | '[' external_table_hive_parameter_map (',' external_table_hive_parameter_map)* ']' | external_table_field datatype (COMMENT quoted_string)? (',' COMMENT quoted_string)* | SEQUENCEFILE | TEXTFILE | RCFILE | ORC | PARQUET | INPUTFORMAT quoted_string OUTPUTFORMAT quoted_string | external_table_directory | DELIMITED? ( FIELDS TERMINATED BY CHARACTER (ESCAPED BY CHARACTER) | (COLLECTION ITEMS | MAP KEYS | LINES ) TERMINATED BY CHARACTER | NULL_ DEFINED AS CHARACTER ) | SERDE quoted_string ( WITH SERDEPROPERTIES ( quoted_string '=' quoted_string (',' quoted_string '=' quoted_string)* ) )? ) external_table_hive? ; external_table_hive_parameter_map : LEFT_CURLY_PAREN (external_table_hive_parameter_map_entry (',' external_table_hive_parameter_map_entry)*) RIGHT_CURLY_PAREN ; external_table_hive_parameter_map_entry : id_expression BINDVAR | id_expression ':' '[' id_expression (',' id_expression)* ']' | '[' id_expression (',' id_expression)* ']' ; external_table_directory : directory_name COLON CHAR_STRING | (directory_name object_name? COLON)? CHAR_STRING | quoted_string | variable_name ; row_movement_clause : (ENABLE | DISABLE)? ROW MOVEMENT ; flashback_archive_clause : FLASHBACK ARCHIVE fa = id_expression? | NO FLASHBACK ARCHIVE ; log_grp : UNSIGNED_INTEGER | identifier ; supplemental_table_logging : ADD SUPPLEMENTAL LOG (supplemental_log_grp_clause | supplemental_id_key_clause) ( ',' SUPPLEMENTAL LOG (supplemental_log_grp_clause | supplemental_id_key_clause) )* | DROP SUPPLEMENTAL LOG (supplemental_id_key_clause | GROUP log_grp) ( ',' SUPPLEMENTAL LOG (supplemental_id_key_clause | GROUP log_grp) )* ; supplemental_log_grp_clause : GROUP log_grp '(' column_name (NO LOG)? (',' column_name (NO LOG)?)* ')' ALWAYS? ; supplemental_id_key_clause : DATA '(' (','? ( ALL | PRIMARY KEY | UNIQUE INDEX? | FOREIGN KEY))+ ')' COLUMNS ; allocate_extent_clause : ALLOCATE EXTENT ( '(' ( SIZE size_clause | DATAFILE datafile = CHAR_STRING | INSTANCE inst_num = UNSIGNED_INTEGER )+ ')' )? ; deallocate_unused_clause : DEALLOCATE UNUSED (KEEP size_clause)? ; // CHECK is an internal, undocumented Oracle option that is allowed and sometimes specified, used to check for proper // segment type and segment attributes allowed to shrink. shrink_clause : SHRINK SPACE_KEYWORD COMPACT? CASCADE? CHECK? ; records_per_block_clause : (MINIMIZE | NOMINIMIZE)? RECORDS_PER_BLOCK ; upgrade_table_clause : UPGRADE (NOT? INCLUDING DATA) column_properties ; truncate_table : TRUNCATE TABLE tableview_name ((PRESERVE | PURGE) (MATERIALIZED VIEW LOG)?)? ((DROP ALL? | REUSE) STORAGE)? CASCADE? ; drop_table : DROP TABLE tableview_name (IF EXISTS)? (AS tableview_name)? (CASCADE (CONSTRAINT | CONSTRAINTS))? PURGE? (AS table_alias)? FORCE? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-TABLESPACE.html drop_tablespace : DROP TABLESPACE ts = id_expression (IF EXISTS)? ((DROP | KEEP) QUOTA?)? including_contents_clause? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-TABLESPACE-SET.html drop_tablespace_set : DROP TABLESPACE SET tss = id_expression including_contents_clause? ; including_contents_clause : INCLUDING CONTENTS ((AND | KEEP) DATAFILES)? (CASCADE CONSTRAINTS)? ; drop_view : DROP VIEW tableview_name (IF EXISTS)? (CASCADE CONSTRAINT)? ; comment_on_column : COMMENT ON COLUMN column_name IS quoted_string ; enable_or_disable : ENABLE | DISABLE ; allow_or_disallow : ALLOW | DISALLOW ; // Synonym DDL Clauses alter_synonym : ALTER PUBLIC? SYNONYM (schema_name '.')? synonym_name ( EDITIONABLE | NONEDITIONABLE | COMPILE ) ; create_synonym // Synonym's schema cannot be specified for public synonyms : CREATE (OR REPLACE)? PUBLIC SYNONYM synonym_name FOR (schema_name PERIOD)? schema_object_name ( AT_SIGN link_name )? | CREATE (OR REPLACE)? SYNONYM (schema_name PERIOD)? synonym_name FOR (schema_name PERIOD)? schema_object_name ( AT_SIGN (schema_name PERIOD)? link_name )? ; drop_synonym : DROP PUBLIC? SYNONYM (schema_name '.')? synonym_name FORCE? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-SPFILE.html create_spfile : CREATE SPFILE ('=' spfile_name)? FROM (PFILE ('=' pfile_name)? (AS COPY)? | MEMORY) ; spfile_name : CHAR_STRING ; pfile_name : CHAR_STRING ; comment_on_table : COMMENT ON TABLE tableview_name IS quoted_string ; comment_on_materialized : COMMENT ON MATERIALIZED VIEW tableview_name IS quoted_string ; alter_analytic_view : ALTER ANALYTIC VIEW (schema_name '.')? av = id_expression ( RENAME TO id_expression | COMPILE | alter_add_cache_clause | alter_drop_cache_clause ) ; alter_add_cache_clause : ADD CACHE MEASURE GROUP '(' (ALL | measure_list)? ')' LEVELS '(' levels_item ( ',' levels_item )* ')' ; levels_item : ((d = id_expression '.')? h = id_expression '.')? l = id_expression ; measure_list : id_expression (',' id_expression)* ; alter_drop_cache_clause : DROP CACHE MEASURE GROUP '(' (ALL | measure_list)? ')' LEVELS '(' levels_item ( ',' levels_item )* ')' ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-ATTRIBUTE-DIMENSION.html alter_attribute_dimension : ALTER ATTRIBUTE DIMENSION (schema_name '.')? ad = id_expression ( RENAME TO nad = id_expression | COMPILE ) ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-AUDIT-POLICY-Unified-Auditing.html alter_audit_policy : ALTER AUDIT POLICY p = id_expression ADD? ( privilege_audit_clause? action_audit_clause? role_audit_clause? | (ONLY TOPLEVEL)? ) DROP? (privilege_audit_clause? action_audit_clause? role_audit_clause? | (ONLY TOPLEVEL)?) ( CONDITION (DROP | CHAR_STRING EVALUATE PER (STATEMENT | SESSION | INSTANCE)) )? ; alter_cluster : ALTER CLUSTER cluster_name ( physical_attributes_clause | SIZE size_clause | allocate_extent_clause | deallocate_unused_clause | cache_or_nocache )+ parallel_clause? ; drop_analytic_view : DROP ANALYTIC VIEW (schema_name '.')? av = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-ATTRIBUTE-DIMENSION.html drop_attribute_dimension : DROP ATTRIBUTE DIMENSION (schema_name '.')? ad = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-AUDIT-POLICY-Unified-Auditing.html drop_audit_policy : DROP AUDIT POLICY p = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-FLASHBACK-ARCHIVE.html drop_flashback_archive : DROP FLASHBACK ARCHIVE fa = id_expression ; drop_cluster : DROP CLUSTER cluster_name (INCLUDING TABLES (CASCADE CONSTRAINTS)?)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-CONTEXT.html drop_context : DROP CONTEXT ns = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-DIRECTORY.html drop_directory : DROP DIRECTORY dn = id_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-DISKGROUP.html drop_diskgroup : DROP DISKGROUP dgn = id_expression ((FORCE? INCLUDING | EXCLUDING) CONTENTS)? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-EDITION.html drop_edition : DROP EDITION e = id_expression CASCADE? ; truncate_cluster : TRUNCATE CLUSTER cluster_name ((DROP | REUSE) STORAGE)? ; cache_or_nocache : CACHE | NOCACHE ; database_name : id_expression ; alter_database : ALTER database_clause ( startup_clauses | recovery_clauses | database_file_clauses | logfile_clauses | controlfile_clauses | standby_database_clauses | default_settings_clause | instance_clauses | security_clause | prepare_clause | drop_mirror_clause | lost_write_protection | cdb_fleet_clauses | property_clauses | replay_upgrade_clauses ) ; database_clause : PLUGGABLE? DATABASE database_name? ; startup_clauses : MOUNT ((STANDBY | CLONE) DATABASE)? | OPEN (READ WRITE)? resetlogs_or_noresetlogs? upgrade_or_downgrade? | OPEN READ ONLY ; resetlogs_or_noresetlogs : RESETLOGS | NORESETLOGS ; upgrade_or_downgrade : UPGRADE | DOWNGRADE ; recovery_clauses : general_recovery | managed_standby_recovery | begin_or_end BACKUP ; begin_or_end : BEGIN | END ; general_recovery : RECOVER AUTOMATIC? (FROM CHAR_STRING)? ( (full_database_recovery | partial_database_recovery | LOGFILE CHAR_STRING)? ( (TEST | ALLOW UNSIGNED_INTEGER CORRUPTION | parallel_clause)+ )? | CONTINUE DEFAULT? | CANCEL ) ; //Need to come back to full_database_recovery : STANDBY? DATABASE ( ( UNTIL (CANCEL | TIME CHAR_STRING | CHANGE UNSIGNED_INTEGER | CONSISTENT) | USING BACKUP CONTROLFILE | SNAPSHOT TIME CHAR_STRING )+ )? ; partial_database_recovery : TABLESPACE tablespace (',' tablespace)* | DATAFILE CHAR_STRING | filenumber (',' CHAR_STRING | filenumber)* | partial_database_recovery_10g ; partial_database_recovery_10g : {this.isVersion10()}? STANDBY ( TABLESPACE tablespace (',' tablespace)* | DATAFILE CHAR_STRING | filenumber (',' CHAR_STRING | filenumber)* ) UNTIL (CONSISTENT WITH)? CONTROLFILE ; managed_standby_recovery : RECOVER ( MANAGED STANDBY DATABASE ( ( USING CURRENT LOGFILE | DISCONNECT (FROM SESSION)? | NODELAY | UNTIL CHANGE UNSIGNED_INTEGER | UNTIL CONSISTENT | parallel_clause )+ | FINISH | CANCEL )? | TO LOGICAL STANDBY (db_name | KEEP IDENTITY) ) ; db_name : regular_id ; database_file_clauses : RENAME FILE filename (',' filename)* TO filename | create_datafile_clause | alter_datafile_clause | alter_tempfile_clause | move_datafile_clause ; create_datafile_clause : CREATE DATAFILE (filename | filenumber) (',' (filename | filenumber))* ( AS ( //TODO (','? file_specification)+ | NEW ) )? ; alter_datafile_clause : DATAFILE (filename | filenumber) (',' (filename | filenumber))* ( ONLINE | OFFLINE (FOR DROP)? | RESIZE size_clause | autoextend_clause | END BACKUP ) ; alter_tempfile_clause : TEMPFILE (filename | filenumber) (',' (filename | filenumber))* ( RESIZE size_clause | autoextend_clause | DROP (INCLUDING DATAFILES) | ONLINE | OFFLINE ) ; move_datafile_clause : MOVE DATAFILE (filename | filenumber) (',' (filename | filenumber))* (TO filename)? REUSE? KEEP? ; logfile_clauses : (ARCHIVELOG MANUAL? | NOARCHIVELOG) | NO? FORCE LOGGING | SET STANDBY NOLOGGING FOR (DATA AVAILABILITY | LOAD PERFORMANCE) | RENAME FILE filename (',' filename)* TO filename | CLEAR UNARCHIVED? LOGFILE logfile_descriptor (',' logfile_descriptor)* ( UNRECOVERABLE DATAFILE )? | add_logfile_clauses | drop_logfile_clauses | switch_logfile_clause | supplemental_db_logging ; add_logfile_clauses : ADD STANDBY? LOGFILE ( (INSTANCE CHAR_STRING | THREAD UNSIGNED_INTEGER)? group_redo_logfile+ | MEMBER filename REUSE? (',' filename REUSE?)* TO logfile_descriptor ( ',' logfile_descriptor )* ) ; group_redo_logfile : (GROUP UNSIGNED_INTEGER)? redo_log_file_spec ; drop_logfile_clauses : DROP STANDBY? LOGFILE ( logfile_descriptor (',' logfile_descriptor)* | MEMBER filename (',' filename)* ) ; switch_logfile_clause : SWITCH ALL LOGFILES TO BLOCKSIZE UNSIGNED_INTEGER ; supplemental_db_logging : add_or_drop SUPPLEMENTAL LOG (DATA | supplemental_id_key_clause | supplemental_plsql_clause) ; add_or_drop : ADD | DROP ; supplemental_plsql_clause : DATA FOR PROCEDURAL REPLICATION ; logfile_descriptor : GROUP UNSIGNED_INTEGER | '(' filename (',' filename)* ')' | filename ; controlfile_clauses : CREATE (LOGICAL | PHYSICAL)? STANDBY CONTROLFILE AS filename REUSE? | BACKUP CONTROLFILE TO (filename REUSE? | trace_file_clause) ; trace_file_clause : TRACE (AS filename REUSE?)? (RESETLOGS | NORESETLOGS)? ; standby_database_clauses : ( activate_standby_db_clause | maximize_standby_db_clause | register_logfile_clause | commit_switchover_clause | start_standby_clause | stop_standby_clause | convert_database_clause ) parallel_clause? ; activate_standby_db_clause : ACTIVATE (PHYSICAL | LOGICAL)? STANDBY DATABASE (FINISH APPLY)? ; maximize_standby_db_clause : SET STANDBY DATABASE TO MAXIMIZE (PROTECTION | AVAILABILITY | PERFORMANCE) ; register_logfile_clause : REGISTER (OR REPLACE)? (PHYSICAL | LOGICAL) LOGFILE //TODO (','? file_specification)+ //TODO (FOR logminer_session_name)? ; commit_switchover_clause : (PREPARE | COMMIT) TO SWITCHOVER ( ( TO ( ((PHYSICAL | LOGICAL)? PRIMARY | PHYSICAL? STANDBY) ( (WITH | WITHOUT)? SESSION SHUTDOWN (WAIT | NOWAIT) )? | LOGICAL STANDBY ) | LOGICAL STANDBY ) | CANCEL )? ; start_standby_clause : START LOGICAL STANDBY APPLY IMMEDIATE? NODELAY? ( NEW PRIMARY regular_id | INITIAL scn_value = UNSIGNED_INTEGER? | SKIP_ FAILED TRANSACTION | FINISH )? ; stop_standby_clause : (STOP | ABORT) LOGICAL STANDBY APPLY ; convert_database_clause : CONVERT TO (PHYSICAL | SNAPSHOT) STANDBY ; default_settings_clause : DEFAULT EDITION EQUALS_OP edition_name | SET DEFAULT (BIGFILE | SMALLFILE) TABLESPACE | DEFAULT TABLESPACE tablespace | DEFAULT TEMPORARY TABLESPACE (tablespace | tablespace_group_name) | RENAME GLOBAL_NAME TO database ('.' domain)+ | ENABLE BLOCK CHANGE TRACKING (USING FILE filename REUSE?)? | DISABLE BLOCK CHANGE TRACKING | flashback_mode_clause | set_time_zone_clause ; set_time_zone_clause : SET TIMEZONE EQUALS_OP CHAR_STRING ; instance_clauses : enable_or_disable INSTANCE CHAR_STRING ; security_clause : GUARD (ALL | STANDBY | NONE) ; domain : id_expression ; database : id_expression ; edition_name : regular_id ; filenumber : UNSIGNED_INTEGER ; filename : CHAR_STRING ; prepare_clause : PREPARE MIRROR COPY c = id_expression (WITH (UNPROTECTED | MIRROR | HIGH) REDUNDANCY)? ( FOR DATABASE id_expression )? ; drop_mirror_clause : DROP MIRROR COPY mn = id_expression ; lost_write_protection : (ENABLE | DISABLE | REMOVE | SUSPEND) LOST WRITE PROTECTION ; cdb_fleet_clauses : lead_cdb_clause | lead_cdb_uri_clause ; lead_cdb_clause : SET LEAD_CDB '=' (TRUE | FALSE) ; lead_cdb_uri_clause : SET LEAD_CDB_URI '=' CHAR_STRING ; property_clauses : PROPERTY (SET | REMOVE) DEFAULT_CREDENTIAL '=' qcn = id_expression ; replay_upgrade_clauses : UPGRADE SYNC (ON | OFF) ; alter_database_link : ALTER SHARED? PUBLIC? DATABASE LINK local_link_name ( CONNECT TO user_object_name IDENTIFIED BY password_value link_authentication? | link_authentication ) ; password_value : id_expression | numeric | VALUES CHAR_STRING ; link_authentication : AUTHENTICATED BY user_object_name IDENTIFIED BY password_value ; //https://docs.oracle.com/en/database/oracle/oracle-database/23/sqlrf/CREATE-SCHEMA.html create_schema : CREATE SCHEMA AUTHORIZATION schema_name (create_table | create_view | grant_statement)* ; // added by zrh create_database : CREATE DATABASE database_name ( USER (SYS | SYSTEM) IDENTIFIED BY password_value | CONTROLFILE REUSE | (MAXDATAFILES | MAXINSTANCES) UNSIGNED_INTEGER | NATIONAL? CHARACTER SET char_set_name | SET DEFAULT (BIGFILE | SMALLFILE) TABLESPACE | database_logging_clauses | tablespace_clauses | set_time_zone_clause | (BIGFILE | SMALLFILE)? USER_DATA TABLESPACE tablespace_group_name DATAFILE datafile_tempfile_spec ( ',' datafile_tempfile_spec )* | enable_pluggable_database )+ ; database_logging_clauses : LOGFILE database_logging_sub_clause (',' database_logging_sub_clause)* | (MAXLOGFILES | MAXLOGMEMBERS | MAXLOGHISTORY) UNSIGNED_INTEGER | ARCHIVELOG | NOARCHIVELOG | FORCE LOGGING ; database_logging_sub_clause : (GROUP UNSIGNED_INTEGER)? file_specification ; tablespace_clauses : EXTENT MANAGEMENT LOCAL | SYSAUX? DATAFILE file_specification (',' file_specification)* | default_tablespace | default_temp_tablespace | undo_tablespace ; enable_pluggable_database : ENABLE PLUGGABLE DATABASE ( SEED file_name_convert? (SYSTEM tablespace_datafile_clauses)? ( SYSAUX tablespace_datafile_clauses )? )? undo_mode_clause? ; file_name_convert : FILE_NAME_CONVERT EQUALS_OP ( '(' filename_convert_sub_clause (',' filename_convert_sub_clause)* ')' | NONE ) ; filename_convert_sub_clause : CHAR_STRING (',' CHAR_STRING)? ; tablespace_datafile_clauses : DATAFILES (SIZE size_clause | autoextend_clause)+ ; undo_mode_clause : LOCAL UNDO (ON | OFF) ; default_tablespace : DEFAULT TABLESPACE tablespace (DATAFILE datafile_tempfile_spec)? extent_management_clause? ; default_temp_tablespace : (BIGFILE | SMALLFILE)? DEFAULT ( TEMPORARY TABLESPACE | LOCAL TEMPORARY TABLESPACE FOR (ALL | LEAF) ) tablespace (TEMPFILE file_specification (',' file_specification)*)? extent_management_clause? ; undo_tablespace : (BIGFILE | SMALLFILE)? UNDO TABLESPACE tablespace ( DATAFILE file_specification (',' file_specification)* )? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/DROP-DATABASE.html drop_database : DROP DATABASE (INCLUDING BACKUPS)? NOPROMPT? ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-DATABASE-LINK.html create_database_link : CREATE SHARED? PUBLIC? DATABASE LINK link_name ( CONNECT TO ( CURRENT_USER | user_object_name IDENTIFIED BY password_value link_authentication? ) | link_authentication )* (USING CHAR_STRING)? ; drop_database_link : DROP PUBLIC? DATABASE LINK link_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/ALTER-TABLESPACE-SET.html alter_tablespace_set : ALTER TABLESPACE SET tss = id_expression alter_tablespace_attrs ; alter_tablespace_attrs : default_tablespace_params | MINIMUM EXTENT size_clause | RESIZE size_clause | COALESCE | SHRINK SPACE_KEYWORD (KEEP size_clause)? | RENAME TO nts = id_expression | (BEGIN | END) BACKUP | datafile_tempfile_clauses | tablespace_logging_clauses | tablespace_group_clause | tablespace_state_clauses | autoextend_clause | flashback_mode_clause | tablespace_retention_clause | alter_tablespace_encryption | lost_write_protection ; alter_tablespace_encryption : ENCRYPTION ( OFFLINE (tablespace_encryption_spec? ENCRYPT | DECRYPT) | ONLINE (tablespace_encryption_spec? (ENCRYPT | REKEY) | DECRYPT) ts_file_name_convert? | FINISH (ENCRYPT | REKEY | DECRYPT) ts_file_name_convert? ) ; ts_file_name_convert : FILE_NAME_CONVERT '=' '(' CHAR_STRING ',' CHAR_STRING (',' CHAR_STRING ',' CHAR_STRING)* ')' KEEP? ; alter_role : ALTER ROLE role_name role_identified_clause container_clause? ; role_identified_clause : NOT IDENTIFIED | IDENTIFIED ( BY identifier | USING identifier ('.' id_expression)? | EXTERNALLY | GLOBALLY (AS CHAR_STRING)? ) ; alter_table : ALTER TABLE tableview_name memoptimize_read_write_clause* ( | alter_table_properties | constraint_clauses | column_clauses | alter_table_partitioning //TODO | alter_external_table | move_table_clause ) ((enable_disable_clause | enable_or_disable (TABLE LOCK | ALL TRIGGERS))+)? ; memoptimize_read_write_clause : NO? MEMOPTIMIZE FOR (READ | WRITE) ; alter_table_properties : alter_table_properties_1 | RENAME TO tableview_name | shrink_clause | READ ONLY | READ WRITE | REKEY CHAR_STRING | annotations_clause ; alter_table_partitioning : add_table_partition | drop_table_partition | merge_table_partition | modify_table_partition | split_table_partition | truncate_table_partition | exchange_table_partition | coalesce_table_partition | alter_interval_partition | move_table_partition | rename_table_partition ; add_table_partition : ADD ( range_partition_desc | list_partition_desc | PARTITION partition_name? (TABLESPACE tablespace)? key_compression? UNUSABLE? ) ; drop_table_partition : DROP (partition_extended_names | subpartition_extended_names) ( update_index_clauses parallel_clause? )? ; merge_table_partition : MERGE PARTITION partition_name AND partition_name INTO PARTITION partition_name ; modify_table_partition : MODIFY ( (PARTITION | SUBPARTITION) partition_name ((ADD | DROP) list_values_clause)? (ADD range_subpartition_desc)? ( REBUILD? UNUSABLE LOCAL INDEXES )? shrink_clause? | range_partitions ) ; split_table_partition : SPLIT partition_extended_names ( AT '(' literal (',' literal)* ')' INTO '(' range_partition_desc (',' range_partition_desc)* ')' | INTO '(' ( range_partition_desc (',' range_partition_desc)* | list_partition_desc (',' list_partition_desc)* ) ')' ) (update_global_index_clause | update_index_clauses | ONLINE)? ; truncate_table_partition : TRUNCATE (partition_extended_names | subpartition_extended_names) ( (DROP ALL? | REUSE)? STORAGE )? CASCADE? (update_index_clauses parallel_clause?)? ; exchange_table_partition : EXCHANGE PARTITION partition_name WITH TABLE tableview_name ((INCLUDING | EXCLUDING) INDEXES)? ( (WITH | WITHOUT) VALIDATION )? ; coalesce_table_partition : COALESCE PARTITION parallel_clause? (allow_or_disallow CLUSTERING)? ; alter_interval_partition : SET INTERVAL '(' (constant | expression)? ')' ; move_table_partition : MOVE ( partition_extended_names (MAPPING TABLE)? table_partition_description | subpartition_extended_names indexing_clause? partitioning_storage_clause? ) ( filter_condition | update_index_clauses | parallel_clause | allow_or_disallow CLUSTERING | ONLINE )* ; filter_condition : INCLUDING ROWS where_clause ; rename_table_partition : RENAME (partition_extended_names | subpartition_extended_names) TO partition_name ; partition_extended_names : (PARTITION | PARTITIONS) ( partition_name (',' partition_name)* | '(' partition_name (',' partition_name)* ')' | FOR '('? partition_key_value (',' partition_key_value)* ')'? ) ; subpartition_extended_names : (SUBPARTITION | SUBPARTITIONS) ( partition_name (UPDATE INDEXES)? | '(' partition_name (',' partition_name)* ')' | FOR '('? subpartition_key_value (',' subpartition_key_value)* ')'? ) ; alter_table_properties_1 : ( physical_attributes_clause | logging_clause | table_compression | inmemory_table_clause | supplemental_table_logging | allocate_extent_clause | deallocate_unused_clause | (CACHE | NOCACHE) | RESULT_CACHE '(' MODE (DEFAULT | FORCE) ')' | upgrade_table_clause | records_per_block_clause | parallel_clause | row_movement_clause | logical_replication_clause | flashback_archive_clause )+ alter_iot_clauses? ; alter_iot_clauses : index_org_table_clause | alter_overflow_clause | alter_mapping_table_clause | COALESCE ; alter_mapping_table_clause : MAPPING TABLE (allocate_extent_clause | deallocate_unused_clause) ; alter_overflow_clause : add_overflow_clause | OVERFLOW_ ( segment_attributes_clause | allocate_extent_clause | shrink_clause | deallocate_unused_clause )+ ; add_overflow_clause : ADD OVERFLOW_ segment_attributes_clause? ( '(' PARTITION segment_attributes_clause? (',' PARTITION segment_attributes_clause?)* ')' )? ; update_index_clauses : update_global_index_clause | update_all_indexes_clause ; update_global_index_clause : (UPDATE | INVALIDATE) GLOBAL INDEXES ; update_all_indexes_clause : UPDATE INDEXES ('(' update_all_indexes_index_clause ')')? ; update_all_indexes_index_clause : index_name '(' (update_index_partition | update_index_subpartition) ')' ( ',' update_all_indexes_clause )* ; update_index_partition : index_partition_description index_subpartition_clause? (',' update_index_partition)* ; update_index_subpartition : SUBPARTITION subpartition_name? (TABLESPACE tablespace)? (',' update_index_subpartition)* ; enable_disable_clause : (ENABLE | DISABLE) (VALIDATE | NOVALIDATE)? ( UNIQUE '(' column_name (',' column_name)* ')' | PRIMARY KEY | CONSTRAINT constraint_name ) using_index_clause? exceptions_clause? CASCADE? ((KEEP | DROP) INDEX)? ; using_index_clause : USING INDEX (index_name | '(' create_index ')' | index_properties) ; index_attributes : ( physical_attributes_clause | logging_clause | TABLESPACE (tablespace | DEFAULT) | key_compression | sort_or_nosort | REVERSE | visible_or_invisible | parallel_clause )+ ; sort_or_nosort : SORT | NOSORT ; exceptions_clause : EXCEPTIONS INTO tableview_name ; move_table_clause : MOVE ONLINE? segment_attributes_clause? table_compression? index_org_table_clause? ( lob_storage_clause | varray_col_properties )* parallel_clause? ; index_org_table_clause : (mapping_table_clause | PCTTHRESHOLD UNSIGNED_INTEGER | key_compression)+ index_org_overflow_clause? | index_org_overflow_clause // rule move_table_clause contains an optional block with at least one alternative that can match an empty string ; mapping_table_clause : MAPPING TABLE | NOMAPPING ; key_compression : NOCOMPRESS | COMPRESS UNSIGNED_INTEGER ; index_org_overflow_clause : (INCLUDING column_name)? OVERFLOW_ segment_attributes_clause? ; column_clauses : add_modify_drop_column_clauses | rename_column_clause | modify_collection_retrieval | modify_lob_storage_clause ; modify_collection_retrieval : MODIFY NESTED TABLE collection_item RETURN AS (LOCATOR | VALUE) ; collection_item : tableview_name ; rename_column_clause : RENAME COLUMN old_column_name TO new_column_name ; old_column_name : column_name ; new_column_name : column_name ; add_modify_drop_column_clauses : (constraint_clauses | add_column_clause | modify_column_clauses | drop_column_clause)+ ; drop_column_clause : SET UNUSED (COLUMN column_name | ('(' column_name (',' column_name)* ')')) ( CASCADE CONSTRAINTS | INVALIDATE )* | DROP (COLUMN column_name | '(' column_name (',' column_name)* ')') ( CASCADE CONSTRAINTS | INVALIDATE )* (CHECKPOINT UNSIGNED_INTEGER)? | DROP (UNUSED COLUMNS | COLUMNS CONTINUE) (CHECKPOINT UNSIGNED_INTEGER) ; modify_column_clauses : MODIFY ( '(' modify_col_properties (',' modify_col_properties)* ')' | '(' modify_col_visibility (',' modify_col_visibility)* ')' | modify_col_properties | modify_col_visibility | modify_col_substitutable ) ; modify_col_properties : column_name datatype? (DEFAULT (ON NULL_)? expression)? (ENCRYPT encryption_spec | DECRYPT)? inline_constraint* lob_storage_clause? annotations_clause? //TODO alter_xmlschema_clause ; modify_col_visibility : column_name (VISIBLE | INVISIBLE) ; modify_col_substitutable : COLUMN column_name NOT? SUBSTITUTABLE AT ALL LEVELS FORCE? ; add_column_clause : ADD ( '(' (column_definition | virtual_column_definition) ( ',' (column_definition | virtual_column_definition) )* ')' | ( column_definition | virtual_column_definition) ) column_properties? ; varray_col_properties : VARRAY varray_item ( substitutable_column_clause? varray_storage_clause | substitutable_column_clause ) ; varray_storage_clause : STORE AS (SECUREFILE | BASICFILE)? LOB ( lob_segname? '(' lob_storage_parameters ')' | lob_segname )? ; lob_segname : regular_id ; lob_item : regular_id | quoted_string | DELIMITED_ID ; lob_storage_parameters : TABLESPACE tablespace_name = id_expression | (lob_parameters storage_clause?) | storage_clause ; lob_storage_clause : LOB ( '(' lob_item (',' lob_item)* ')' STORE AS ( (SECUREFILE | BASICFILE) | '(' lob_storage_parameters* ')' )+ | '(' lob_item ')' STORE AS ( (SECUREFILE | BASICFILE) | lob_segname | '(' lob_storage_parameters* ')' )+ ) ; modify_lob_storage_clause : MODIFY LOB '(' lob_item ')' '(' modify_lob_parameters ')' ; modify_lob_parameters : ( storage_clause | (PCTVERSION | FREEPOOLS) UNSIGNED_INTEGER | REBUILD FREEPOOLS | lob_retention_clause | lob_deduplicate_clause | lob_compression_clause | ENCRYPT encryption_spec | DECRYPT | CACHE | (CACHE | NOCACHE | CACHE READS) logging_clause? | allocate_extent_clause | shrink_clause | deallocate_unused_clause )+ ; lob_parameters : ( (ENABLE | DISABLE) STORAGE IN ROW | CHUNK UNSIGNED_INTEGER | PCTVERSION UNSIGNED_INTEGER | FREEPOOLS UNSIGNED_INTEGER | lob_retention_clause | lob_deduplicate_clause | lob_compression_clause | ENCRYPT encryption_spec | DECRYPT | (CACHE | NOCACHE | CACHE READS) logging_clause? )+ ; lob_deduplicate_clause : DEDUPLICATE | KEEP_DUPLICATES ; lob_compression_clause : NOCOMPRESS | COMPRESS (HIGH | MEDIUM | LOW)? ; lob_retention_clause : RETENTION (MAX | MIN UNSIGNED_INTEGER | AUTO | NONE)? ; encryption_spec : (USING CHAR_STRING)? (IDENTIFIED BY REGULAR_ID)? CHAR_STRING? (NO? SALT)? ; tablespace : id_expression ; varray_item : (id_expression '.')? (id_expression '.')? id_expression ; column_properties : ( object_type_col_properties | nested_table_col_properties | (varray_col_properties | lob_storage_clause) ( '(' lob_partition_storage (',' lob_partition_storage)* ')' )? //TODO '(' ( ','? lob_partition_storage)+ ')' | xmltype_column_properties )+ ; lob_partition_storage : LOB ( '(' lob_item (',' lob_item) ')' STORE AS ( (SECUREFILE | BASICFILE) | '(' lob_storage_parameters ')' )+ | '(' lob_item ')' STORE AS ( (SECUREFILE | BASICFILE) | lob_segname | '(' lob_storage_parameters ')' )+ ) ; period_definition : {this.isVersion12()}? PERIOD FOR column_name ('(' start_time_column ',' end_time_column ')')? ; start_time_column : column_name ; end_time_column : column_name ; column_definition : column_name ((datatype | type_name) (COLLATE column_collation_name)?)? SORT? ( VISIBLE | INVISIBLE )? (DEFAULT (ON NULL_)? expression | identity_clause)? (ENCRYPT encryption_spec)? ( inline_constraint+ | inline_ref_constraint )? annotations_clause? ; column_collation_name : id_expression ; identity_clause : GENERATED (ALWAYS | BY DEFAULT (ON NULL_)?)? AS IDENTITY identity_options_parentheses? ; //https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/CREATE-TABLE.html#GUID-F9CE0CC3-13AE-4744-A43C-EAC7A71AAAB6 // NOTE to identity options // according to the SQL Reference, identity_options be nested in parentheses. // But statements without parentheses can also be executed successfully on a oracle database. // See this issue for more details: https://github.com/antlr/grammars-v4/issues/3183 identity_options_parentheses : identity_options+ | '(' identity_options+ ')' ; identity_options : START WITH (numeric | LIMIT VALUE) | INCREMENT BY numeric | MAXVALUE numeric | NOMAXVALUE | MINVALUE numeric | NOMINVALUE | CYCLE | NOCYCLE | CACHE numeric | NOCACHE | ORDER | NOORDER | SCALE (EXTEND | NOEXTEND) | NOSCALE | KEEP | NOKEEP ; virtual_column_definition : column_name (datatype (COLLATE column_collation_name)?)? (VISIBLE | INVISIBLE)? virtual_column_expression? VIRTUAL? evaluation_edition_clause? (UNUSABLE BEFORE (CURRENT EDITION | EDITION edition_name))? ( UNUSABLE BEGINNING WITH ((CURRENT | NULL_) EDITION | EDITION edition_name) )? inline_constraint* by_user_for_statistics_clause? ; virtual_column_expression : autogenerated_sequence_definition | (GENERATED ALWAYS?)? AS '(' expression ')' ; autogenerated_sequence_definition : GENERATED (ALWAYS | BY DEFAULT (ON NULL_)?)? AS IDENTITY ( '(' (sequence_start_clause | sequence_spec)* ')' )? ; // Oracle tools and DBMS_METADATA can return this in some use cases // This is used internally by Oracle to mark the virtual column for statistics only by_user_for_statistics_clause : BY USER FOR STATISTICS ; evaluation_edition_clause : EVALUATE USING ((CURRENT | NULL_) EDITION | EDITION edition_name) ; nested_table_col_properties : NESTED TABLE (nested_item | COLUMN_VALUE) substitutable_column_clause? (LOCAL | GLOBAL)? STORE AS tableview_name ( '(' ('(' object_properties ')' | physical_properties | column_properties)+ ')' )? (RETURN AS? (LOCATOR | VALUE))? ; nested_item : regular_id ; substitutable_column_clause : ELEMENT? IS OF TYPE? '(' type_name ')' | NOT? SUBSTITUTABLE AT ALL LEVELS ; partition_name : regular_id | DELIMITED_ID ; supplemental_logging_props : SUPPLEMENTAL LOG (supplemental_log_grp_clause | supplemental_id_key_clause) ; object_type_col_properties : COLUMN column = regular_id substitutable_column_clause ; constraint_clauses : ADD '(' (out_of_line_constraint (',' out_of_line_constraint)* | out_of_line_ref_constraint) ')' | ADD (out_of_line_constraint | out_of_line_ref_constraint) | MODIFY ( CONSTRAINT constraint_name | PRIMARY KEY | UNIQUE '(' column_name (',' column_name)* ')' ) constraint_state CASCADE? | RENAME CONSTRAINT old_constraint_name TO new_constraint_name | drop_constraint_clause+ ; old_constraint_name : constraint_name ; new_constraint_name : constraint_name ; drop_constraint_clause : DROP ( PRIMARY KEY | UNIQUE '(' column_name (',' column_name)* ')' | CONSTRAINT constraint_name ) CASCADE? ((KEY | DROP) INDEX)? ONLINE? ; check_constraint : CHECK '(' condition ')' DISABLE? ; foreign_key_clause : FOREIGN KEY paren_column_list references_clause on_delete_clause? ; references_clause : REFERENCES tableview_name paren_column_list? (ON DELETE (CASCADE | SET NULL_))? ; on_delete_clause : ON DELETE (CASCADE | SET NULL_) ; // Anonymous PL/SQL code block anonymous_block : (DECLARE seq_of_declare_specs?)? BEGIN seq_of_statements (EXCEPTION exception_handler+)? END ; // Common DDL Clauses invoker_rights_clause : AUTHID (CURRENT_USER | DEFINER) ; call_spec : java_spec | c_spec ; // Call Spec Specific Clauses java_spec : LANGUAGE JAVA NAME CHAR_STRING ; c_spec : (LANGUAGE C_LETTER | EXTERNAL) ( NAME id_expression LIBRARY identifier | LIBRARY identifier (NAME id_expression)? ) c_agent_in_clause? (WITH CONTEXT)? c_parameters_clause? ; c_agent_in_clause : AGENT IN '(' expressions_ ')' ; c_parameters_clause : PARAMETERS '(' c_external_parameter (',' c_external_parameter)* ')' ; c_external_parameter : CONTEXT | SELF (TDO | c_property)? | (parameter_name | RETURN) c_property? (BY REFERENCE)? external_datatype = regular_id? ; c_property : INDICATOR (STRUCT | TDO)? | LENGTH | DURATION | MAXLEN | CHARSETID | CHARSETFORM ; parameter : parameter_name (IN | OUT | INOUT | NOCOPY)* type_spec? default_value_part? ; default_value_part : (ASSIGN_OP | DEFAULT) expression ; // Elements Declarations seq_of_declare_specs : declare_spec+ ; declare_spec : pragma_declaration | exception_declaration | procedure_spec | function_spec | variable_declaration | subtype_declaration | cursor_declaration | type_declaration | procedure_body | function_body | selection_directive ; // incorporates constant_declaration variable_declaration : identifier CONSTANT? type_spec (NOT? NULL_)? default_value_part? ';' ; subtype_declaration : SUBTYPE identifier IS type_spec (RANGE expression '..' expression)? (NOT NULL_)? ';' ; // cursor_declaration incorportates curscursor_body and cursor_spec cursor_declaration : CURSOR identifier ('(' parameter_spec (',' parameter_spec)* ')')? (RETURN type_spec)? ( IS select_statement )? ';' ; parameter_spec : parameter_name (IN? type_spec)? default_value_part? ; exception_declaration : identifier EXCEPTION ';' ; pragma_declaration : PRAGMA ( SERIALLY_REUSABLE | AUTONOMOUS_TRANSACTION | EXCEPTION_INIT '(' exception_name ',' numeric_negative ')' | INLINE '(' id1 = identifier ',' expression ')' | RESTRICT_REFERENCES '(' (identifier | DEFAULT) (',' identifier)+ ')' | DEPRECATE '(' identifier ( ',' CHAR_STRING)? ')' | UDF ) ';' ; // Record Declaration Specific Clauses // incorporates ref_cursor_type_definition record_type_def : RECORD '(' field_spec (',' field_spec)* ')' ; field_spec : column_name type_spec? (NOT NULL_)? default_value_part? ; ref_cursor_type_def : REF CURSOR (RETURN type_spec)? ; type_declaration : TYPE identifier IS (table_type_def | varray_type_def | record_type_def | ref_cursor_type_def) ';' ; table_type_def : TABLE OF type_spec (NOT NULL_)? table_indexed_by_part? ; table_indexed_by_part : (idx1 = INDEXED | idx2 = INDEX) BY type_spec ; //https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/collection-variable.html#GUID-89A1863C-65A1-40CF-9392-86E9FDC21BE9 varray_type_def : (VARRAY | VARYING? ARRAY) '(' expression ')' OF type_spec (NOT NULL_)? ; // Statements seq_of_statements : (pragma_declaration* statement (';' | EOF) | label_declaration | selection_directive)+ ; label_declaration : ltp1 = '<' '<' label_name '>' '>' ; statement : body | block | assignment_statement | continue_statement | exit_statement | goto_statement | if_statement | loop_statement | forall_statement | null_statement | raise_statement | return_statement | case_statement | sql_statement | call_statement | pipe_row_statement | grant_statement ; assignment_statement : (general_element | bind_variable) ASSIGN_OP expression ; continue_statement : CONTINUE label_name? (WHEN condition)? ; exit_statement : EXIT label_name? (WHEN condition)? ; goto_statement : GOTO label_name ; if_statement : IF condition THEN seq_of_statements elsif_part* else_part? END IF ; elsif_part : ELSIF condition THEN seq_of_statements ; else_part : ELSE seq_of_statements ; loop_statement : label_declaration? (WHILE condition | FOR cursor_loop_param)? LOOP seq_of_statements END LOOP label_name? ; // Loop Specific Clause cursor_loop_param : index_name IN REVERSE? lower_bound range_separator = '..' upper_bound | record_name IN (cursor_name ('(' expressions_? ')')? | '(' select_statement ')') ; //https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/FORALL-statement.html#GUID-C45B8241-F9DF-4C93-8577-C840A25963DB forall_statement : FORALL index_name IN bounds_clause (SAVE EXCEPTIONS)? (data_manipulation_language_statements | execute_immediate) ; bounds_clause : lower_bound '..' upper_bound | INDICES OF general_element between_bound? | VALUES OF index_name ; between_bound : BETWEEN lower_bound AND upper_bound ; lower_bound : concatenation ; upper_bound : concatenation ; null_statement : NULL_ ; raise_statement : RAISE exception_name? ; return_statement : RETURN expression? ; call_statement : CALL? routine_name function_argument? ('.' routine_name function_argument?)* ( INTO bind_variable )? ; pipe_row_statement : PIPE ROW '(' expression ')' ; selection_directive : DOLLAR_IF condition DOLLAR_THEN selection_directive_body ( DOLLAR_ELSIF selection_directive_body )* (DOLLAR_ELSE selection_directive_body)? DOLLAR_END ; error_directive : DOLLAR_ERROR concatenation DOLLAR_END ; selection_directive_body : ( pragma_declaration? statement ';' | variable_declaration | error_directive | function_body | procedure_body )+ ; body : BEGIN seq_of_statements (EXCEPTION exception_handler+)? END label_name? ; // Body Specific Clause exception_handler : WHEN exception_name (OR exception_name)* THEN seq_of_statements ; trigger_block : (DECLARE declare_spec*)? body ; tps_block : declare_spec* body ; block : (DECLARE declare_spec*)? body ; // SQL Statements sql_statement : execute_immediate | data_manipulation_language_statements | cursor_manipulation_statements | transaction_control_statements | collection_method_call ; execute_immediate : EXECUTE IMMEDIATE expression ( into_clause using_clause? | using_clause dynamic_returning_clause? | dynamic_returning_clause )? ; // Execute Immediate Specific Clause dynamic_returning_clause : (RETURNING | RETURN) into_clause ; // DML Statements data_manipulation_language_statements : merge_statement | lock_table_statement | select_statement | update_statement | delete_statement | insert_statement | explain_statement ; // Cursor Manipulation Statements cursor_manipulation_statements : close_statement | open_statement | fetch_statement | open_for_statement ; close_statement : CLOSE cursor_name ; open_statement : OPEN cursor_name ('(' expressions_? ')')? ; fetch_statement : FETCH cursor_name ( it1 = INTO variable_or_collection (',' variable_or_collection)* | BULK COLLECT INTO variable_or_collection (',' variable_or_collection)* ( LIMIT (numeric | variable_or_collection) )? ) ; variable_or_collection : variable_name | collection_expression ; open_for_statement : OPEN variable_name FOR (select_statement | expression) using_clause? ; // Transaction Control SQL Statements transaction_control_statements : set_transaction_command | set_constraint_command | commit_statement | rollback_statement | savepoint_statement ; set_transaction_command : SET TRANSACTION ( READ (ONLY | WRITE) | ISOLATION LEVEL (SERIALIZABLE | READ COMMITTED) | USE ROLLBACK SEGMENT rollback_segment_name )? (NAME quoted_string)? ; set_constraint_command : SET (CONSTRAINT | CONSTRAINTS) (ALL | constraint_name (',' constraint_name)*) ( IMMEDIATE | DEFERRED ) ; // https://docs.oracle.com/cd/E18283_01/server.112/e17118/statements_4010.htm#SQLRF01110 // https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/COMMIT.html commit_statement : COMMIT WORK? write_clause? ( COMMENT CHAR_STRING write_clause? | FORCE (CHAR_STRING (',' numeric)? | CORRUPT_XID CHAR_STRING | CORRUPT_XID_ALL) )? ; write_clause : WRITE ( (IMMEDIATE | BATCH) | (WAIT | NOWAIT) )* ; rollback_statement : ROLLBACK WORK? (TO SAVEPOINT? savepoint_name | FORCE quoted_string)? ; savepoint_statement : SAVEPOINT savepoint_name ; // https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/collection-method.html#GUID-7AF1A3C4-D04B-4F91-9D7B-C92C75E3A300 collection_method_call // collection methods invocation that could be used as a statement : expression '.' ( (DELETE | EXTEND) ('(' index += expression (',' index += expression)* ')')? | TRIM ('(' index += expression ')')? ) ; // Dml /* TODO //SHOULD BE OVERRIDEN! compilation_unit : seq_of_statements* EOF ; //SHOULD BE OVERRIDEN! seq_of_statements : select_statement | update_statement | delete_statement | insert_statement | lock_table_statement | merge_statement | explain_statement // | case_statement[true] ; */ explain_statement : EXPLAIN PLAN (SET STATEMENT_ID '=' quoted_string)? (INTO tableview_name)? FOR ( select_statement | update_statement | delete_statement | insert_statement | merge_statement ) ; select_only_statement : with_clause? subquery ; select_statement : select_only_statement (for_update_clause | order_by_clause | offset_clause | fetch_clause)* ; // Select Specific Clauses with_clause : WITH (function_body | procedure_body)* with_factoring_clause (',' with_factoring_clause)* | WITH (function_body | procedure_body)+ (with_factoring_clause (',' with_factoring_clause)*)? ; with_factoring_clause : subquery_factoring_clause | subav_factoring_clause ; subquery_factoring_clause : query_name paren_column_list? AS '(' subquery order_by_clause? ')' search_clause? cycle_clause? ; search_clause : SEARCH (DEPTH | BREADTH) FIRST BY column_name ASC? DESC? (NULLS FIRST)? (NULLS LAST)? ( ',' column_name ASC? DESC? (NULLS FIRST)? (NULLS LAST)? )* SET column_name ; cycle_clause : CYCLE column_list SET column_name TO expression DEFAULT expression ; subav_factoring_clause : subav_name = id_expression ANALYTIC VIEW AS '(' subav_clause ')' ; subav_clause : USING subav_name = object_name hierarchies_clause? filter_clauses? add_calcs_clause? ; hierarchies_clause : HIERARCHIES '(' hier_alias += object_name (',' hier_alias += object_name)* ')' ; filter_clauses : FILTER FACT '(' filter_clause (',' filter_clause)* ')' ; filter_clause : (MEASURES | hier_alias = object_name) TO condition ; add_calcs_clause : ADD MEASURES '(' add_calc_meas_clause (',' add_calc_meas_clause)* ')' ; add_calc_meas_clause : meas_name = id_expression AS '(' expression ')' ; subquery : subquery_basic_elements subquery_operation_part* ; subquery_basic_elements : query_block | '(' subquery ')' ; subquery_operation_part : (UNION ALL? | INTERSECT | MINUS) subquery_basic_elements ; query_block : SELECT (DISTINCT | UNIQUE | ALL)? selected_list into_clause? from_clause where_clause? ( hierarchical_query_clause | group_by_clause )* model_clause? order_by_clause? offset_clause? fetch_clause? ; selected_list : '*' | select_list_elements (',' select_list_elements)* ; from_clause : FROM table_ref_list ; select_list_elements : tableview_name '.' ASTERISK | expression column_alias? ; table_ref_list : table_ref (',' table_ref)* ; // NOTE to PIVOT clause // according the SQL reference this should not be possible // according to he reality it is. Here we probably apply pivot/unpivot onto whole join clause // eventhough it is not enclosed in parenthesis. See pivot examples 09,10,11 table_ref : table_ref_aux join_clause* (pivot_clause | unpivot_clause)? ; table_ref_aux : table_ref_aux_internal flashback_query_clause* (/*{isTableAlias()}?*/ table_alias)? ; table_ref_aux_internal : dml_table_expression_clause (pivot_clause | unpivot_clause)? # table_ref_aux_internal_one | '(' table_ref subquery_operation_part* ')' (pivot_clause | unpivot_clause)? # table_ref_aux_internal_two | ONLY '(' dml_table_expression_clause ')' # table_ref_aux_internal_thre ; join_clause : query_partition_clause? (CROSS | NATURAL)? (INNER | outer_join_type)? JOIN table_ref_aux query_partition_clause? ( join_on_part | join_using_part )* | (CROSS | OUTER) APPLY table_ref_aux ; join_on_part : ON condition ; join_using_part : USING paren_column_list ; outer_join_type : (FULL | LEFT | RIGHT) OUTER? ; query_partition_clause : PARTITION BY (('(' (subquery | expressions_)? ')') | expressions_) ; flashback_query_clause : VERSIONS (PERIOD_KEYWORD FOR column_name BETWEEN | BETWEEN (SCN | TIMESTAMP)) expression AND expression | AS OF ((SCN | TIMESTAMP | SNAPSHOT) expression | PERIOD_KEYWORD FOR column_name expression) ; pivot_clause : PIVOT XML? '(' pivot_element (',' pivot_element)* pivot_for_clause pivot_in_clause ')' table_alias? ; pivot_element : (numeric_function | aggregate_function_name '(' expression ')') column_alias? ; pivot_for_clause : FOR (column_name | paren_column_list) ; pivot_in_clause : IN '(' (subquery | ANY (',' ANY)* | pivot_in_clause_element (',' pivot_in_clause_element)*) ')' ; pivot_in_clause_element : pivot_in_clause_elements column_alias? ; pivot_in_clause_elements : expression | '(' expressions_? ')' ; unpivot_clause : UNPIVOT ((INCLUDE | EXCLUDE) NULLS)? '(' (column_name | paren_column_list) pivot_for_clause unpivot_in_clause ')' table_alias? ; unpivot_in_clause : IN '(' unpivot_in_elements (',' unpivot_in_elements)* ')' ; unpivot_in_elements : (column_name | paren_column_list) (AS (constant | '(' constant (',' constant)* ')'))? ; hierarchical_query_clause : CONNECT BY NOCYCLE? condition start_part? | start_part CONNECT BY NOCYCLE? condition ; start_part : START WITH condition ; group_by_clause : GROUP BY group_by_elements (',' group_by_elements)* having_clause? | having_clause (GROUP BY group_by_elements (',' group_by_elements)*)? ; group_by_elements : grouping_sets_clause | rollup_cube_clause | expression ; rollup_cube_clause : (ROLLUP | CUBE) '(' grouping_sets_elements (',' grouping_sets_elements)* ')' ; grouping_sets_clause : GROUPING SETS '(' grouping_sets_elements (',' grouping_sets_elements)* ')' ; grouping_sets_elements : rollup_cube_clause | '(' expressions_? ')' | expression ; having_clause : HAVING condition ; model_clause : MODEL cell_reference_options* return_rows_clause? reference_model* main_model ; cell_reference_options : (IGNORE | KEEP) NAV | UNIQUE (DIMENSION | SINGLE REFERENCE) ; return_rows_clause : RETURN (UPDATED | ALL) ROWS ; reference_model : REFERENCE reference_model_name ON '(' subquery ')' model_column_clauses cell_reference_options* ; main_model : (MAIN main_model_name)? model_column_clauses cell_reference_options* model_rules_clause ; model_column_clauses : model_column_partition_part? DIMENSION BY model_column_list MEASURES model_column_list ; model_column_partition_part : PARTITION BY model_column_list ; model_column_list : '(' model_column (',' model_column)* ')' ; model_column : (expression | query_block) column_alias? ; model_rules_clause : model_rules_part? '(' (model_rules_element (',' model_rules_element)*)? ')' ; model_rules_part : RULES (UPDATE | UPSERT ALL?)? ((AUTOMATIC | SEQUENTIAL) ORDER)? model_iterate_clause? ; model_rules_element : (UPDATE | UPSERT ALL?)? cell_assignment order_by_clause? '=' expression ; cell_assignment : model_expression ; model_iterate_clause : ITERATE '(' expression ')' until_part? ; until_part : UNTIL '(' condition ')' ; order_by_clause : ORDER SIBLINGS? BY order_by_elements (',' order_by_elements)* ; order_by_elements : expression (ASC | DESC)? (NULLS (FIRST | LAST))? ; offset_clause : OFFSET expression (ROW | ROWS) ; fetch_clause : FETCH (FIRST | NEXT) (expression PERCENT_KEYWORD?)? (ROW | ROWS) (ONLY | WITH TIES) ; for_update_clause : FOR UPDATE for_update_of_part? for_update_options? ; for_update_of_part : OF column_list ; for_update_options : SKIP_ LOCKED | NOWAIT | WAIT expression ; update_statement : UPDATE general_table_ref update_set_clause where_clause? static_returning_clause? error_logging_clause? ; // Update Specific Clauses update_set_clause : SET ( column_based_update_set_clause (',' column_based_update_set_clause)* | VALUE '(' identifier ')' '=' expression ) ; column_based_update_set_clause : column_name '=' expression | paren_column_list '=' subquery ; delete_statement : DELETE FROM? general_table_ref where_clause? static_returning_clause? error_logging_clause? ; insert_statement : INSERT (single_table_insert | multi_table_insert) ; // Insert Specific Clauses single_table_insert : insert_into_clause (values_clause static_returning_clause? | select_statement) error_logging_clause? ; multi_table_insert : (ALL multi_table_element+ | conditional_insert_clause) select_statement ; multi_table_element : insert_into_clause values_clause? error_logging_clause? ; conditional_insert_clause : (ALL | FIRST)? conditional_insert_when_part+ conditional_insert_else_part? ; conditional_insert_when_part : WHEN condition THEN multi_table_element+ ; conditional_insert_else_part : ELSE multi_table_element+ ; insert_into_clause : INTO general_table_ref (FIELDS)? paren_column_list? ; values_clause : VALUES (REGULAR_ID | '(' expressions_ ')' | collection_expression) ; merge_statement : MERGE INTO tableview_name table_alias? USING selected_tableview ON '(' condition ')' ( merge_update_clause merge_insert_clause? | merge_insert_clause merge_update_clause? )? error_logging_clause? ; // Merge Specific Clauses merge_update_clause : WHEN MATCHED THEN UPDATE SET merge_element (',' merge_element)* where_clause? merge_update_delete_part? ; merge_element : column_name '=' expression ; merge_update_delete_part : DELETE where_clause ; merge_insert_clause : WHEN NOT MATCHED THEN INSERT paren_column_list? values_clause where_clause? ; selected_tableview : ( tableview_name | '(' select_statement ')' | table_collection_expression | '(' table_collection_expression ')') table_alias? ; lock_table_statement : LOCK TABLE lock_table_element (',' lock_table_element)* IN lock_mode MODE wait_nowait_part? ; wait_nowait_part : WAIT expression | NOWAIT ; // Lock Specific Clauses lock_table_element : tableview_name partition_extension_clause? ; lock_mode : ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE? | SHARE ROW EXCLUSIVE | EXCLUSIVE ; // Common DDL Clauses general_table_ref : (dml_table_expression_clause | ONLY '(' dml_table_expression_clause ')') table_alias? ; static_returning_clause : (RETURNING | RETURN) expressions_ into_clause ; error_logging_clause : LOG ERRORS error_logging_into_part? expression? error_logging_reject_part? ; error_logging_into_part : INTO tableview_name ; error_logging_reject_part : REJECT LIMIT (UNLIMITED | expression) ; dml_table_expression_clause : table_collection_expression | '(' select_statement subquery_restriction_clause? ')' | tableview_name hierarchies_clause? sample_clause? | json_table_clause (AS identifier)? | LATERAL '(' subquery subquery_restriction_clause? ')' // Deprecated Oracle 10/11 RELATIONAL alias for casting object-types to relational tables | {this.isVersion11()}? (RELATIONAL '(' tableview_name NOT XMLTYPE ')') ; table_collection_expression : (TABLE | THE) ('(' subquery ')' | '(' expression ')' outer_join_sign?) ; subquery_restriction_clause : WITH (READ ONLY | CHECK OPTION (CONSTRAINT constraint_name)?) ; sample_clause : SAMPLE BLOCK? '(' expression (',' expression)? ')' seed_part? ; seed_part : SEED '(' expression ')' ; // Expression & Condition condition : expression | JSON_EQUAL '(' expressions_ ')' ; expressions_ : expression (',' expression)* ; expression : cursor_expression | logical_expression ; cursor_expression : CURSOR '(' subquery ')' ; logical_expression : unary_logical_expression | logical_expression AND logical_expression | logical_expression OR logical_expression ; unary_logical_expression : NOT? multiset_expression unary_logical_operation? ; unary_logical_operation : IS NOT? logical_operation ; logical_operation : ( NULL_ | NAN_ | PRESENT | INFINITE | A_LETTER SET | EMPTY_ | OF TYPE? '(' ONLY? type_spec (',' type_spec)* ')' | JSON (FORMAT JSON)? (STRICT | LAX)? ((WITH | WITHOUT) UNIQUE KEYS)? ) ; multiset_expression : relational_expression (multiset_type = NOT? (MEMBER | SUBMULTISET) OF? concatenation)? | multiset_expression MULTISET multiset_operator = (EXCEPT | INTERSECT | UNION) ( ALL | DISTINCT )? relational_expression ; relational_expression : relational_expression relational_operator relational_expression | relational_expression NOT? IN in_elements | compound_expression ; compound_expression : concatenation ( NOT? ( IN in_elements | BETWEEN between_elements | like_type = (LIKE | LIKEC | LIKE2 | LIKE4) concatenation (ESCAPE concatenation)? ) )? ; relational_operator : '=' | (NOT_EQUAL_OP | '<' '>' | '!' '=' | '^' '=') | ('<' | '>') '='? ; in_elements : '(' subquery ')' | '(' concatenation (',' concatenation)* ')' | constant | bind_variable | general_element ; between_elements : concatenation AND concatenation ; concatenation : model_expression (AT (LOCAL | TIME ZONE concatenation) | interval_expression)? ( ON OVERFLOW_ (TRUNCATE | ERROR) )? | concatenation op = DOUBLE_ASTERISK concatenation | concatenation op = (ASTERISK | SOLIDUS | MOD) concatenation | concatenation op = (PLUS_SIGN | MINUS_SIGN) concatenation | concatenation BAR BAR concatenation | concatenation COLLATE column_collation_name ; interval_expression : DAY ('(' concatenation ')')? TO SECOND ('(' concatenation ')')? | YEAR ('(' concatenation ')')? TO MONTH | concatenation (SECOND | DAY | MONTH | YEAR) ; model_expression : unary_expression ('[' model_expression_element ']')? ; model_expression_element : (ANY | expression) (',' (ANY | expression))* | single_column_for_loop (',' single_column_for_loop)* | multi_column_for_loop ; single_column_for_loop : FOR column_name ( IN '(' expressions_? ')' | (LIKE expression)? FROM fromExpr = expression TO toExpr = expression action_type = ( INCREMENT | DECREMENT ) action_expr = expression ) ; multi_column_for_loop : FOR paren_column_list IN '(' (subquery | '(' expressions_? ')') ')' ; unary_expression : ('-' | '+') unary_expression | PRIOR unary_expression | CONNECT_BY_ROOT unary_expression | /*TODO {input.LT(1).getText().equalsIgnoreCase("new") && !input.LT(2).getText().equals(".")}?*/ NEW unary_expression | DISTINCT unary_expression | ALL unary_expression | /*TODO{(input.LA(1) == CASE || input.LA(2) == CASE)}?*/ case_expression | unary_expression '.' ( (COUNT | FIRST | LAST | LIMIT) | (EXISTS | NEXT | PRIOR) '(' index += expression ')' ) | quantified_expression | standard_function | atom | implicit_cursor_expression ; // https://docs.oracle.com/en/database/oracle/oracle-database/21/lnpls/plsql-optimization-and-tuning.html#GUID-DAF46F06-EF3F-4B1A-A518-5238B80C69FA implicit_cursor_expression : SQL ( PERCENT_BULK_ROWCOUNT '(' index = expression ')' | PERCENT_BULK_EXCEPTIONS ('.' COUNT | '(' expression ')' '.' (ERROR_INDEX | ERROR_CODE)) ) ; collection_expression : collation_name '(' expression ')' ('.' general_element_part)* ; // CASE statement case_statement : searched_case_statement | simple_case_statement ; simple_case_statement : label_declaration? ck1 = CASE expression case_when_part_statement+ case_else_part_statement? END CASE? label_name? ; searched_case_statement : label_declaration? ck1 = CASE case_when_part_statement+ case_else_part_statement? END CASE? label_name? ; case_when_part_statement : WHEN expression THEN seq_of_statements ; case_else_part_statement : ELSE seq_of_statements ; // CASE expression case_expression : searched_case_expression | simple_case_expression ; simple_case_expression : ck1 = CASE expression case_when_part_expression+ case_else_part_expression? END CASE? ; searched_case_expression : ck1 = CASE case_when_part_expression+ case_else_part_expression? END CASE? ; case_when_part_expression : WHEN expression THEN expression ; case_else_part_expression : ELSE expression ; atom : bind_variable | constant | inquiry_directive | general_element outer_join_sign? | '(' subquery ')' subquery_operation_part* | '(' expressions_ ')' ; quantified_expression : (SOME | EXISTS | ALL | ANY) ( '(' select_only_statement ')' | '(' expression (',' expression)* ')' ) ; string_function : SUBSTR '(' expression ',' expression (',' expression)? ')' | TO_CHAR '(' (table_element | standard_function | expression) (',' quoted_string)? ( ',' quoted_string )? ')' | DECODE '(' expressions_ ')' | CHR '(' concatenation USING NCHAR_CS ')' | NVL '(' expression ',' expression ')' | TRIM '(' ((LEADING | TRAILING | BOTH)? expression? FROM)? concatenation ')' | TO_DATE '(' (table_element | standard_function | expression) ( DEFAULT concatenation ON CONVERSION ERROR )? (',' quoted_string (',' quoted_string)?)? ')' ; standard_function : string_function | numeric_function_wrapper | json_function | other_function ; //see as https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_ARRAY.html#GUID-46CDB3AF-5795-455B-85A8-764528CEC43B json_function : JSON_ARRAY '(' json_array_element (',' json_array_element)* json_on_null_clause? json_return_clause? STRICT? ')' | JSON_ARRAYAGG '(' expression (FORMAT JSON)? order_by_clause? json_on_null_clause? json_return_clause? STRICT? ')' | JSON_OBJECT '(' json_object_content ')' | JSON_OBJECTAGG '(' KEY? expression VALUE expression ((NULL_ | ABSENT) ON NULL_)? ( RETURNING (VARCHAR2 ('(' UNSIGNED_INTEGER ( BYTE | CHAR)? ')')? | CLOB | BLOB) )? STRICT? (WITH UNIQUE KEYS)? ')' | JSON_QUERY '(' expression (FORMAT JSON)? ',' CHAR_STRING json_query_returning_clause json_query_wrapper_clause? json_query_on_error_clause? json_query_on_empty_clause? ')' | JSON_SERIALIZE '(' CHAR_STRING (RETURNING json_query_return_type)? PRETTY? ASCII? TRUNCATE? ( (NULL_ | ERROR | EMPTY_ (ARRAY | OBJECT)) ON ERROR )? ')' | JSON_TRANSFORM '(' expression ',' json_transform_op (',' json_transform_op)* ')' | JSON_VALUE '(' expression (FORMAT JSON)? ( ',' CHAR_STRING? json_value_return_clause? ((ERROR | NULL_ | DEFAULT literal)? ON ERROR)? ( (ERROR | NULL_ | DEFAULT literal)? ON EMPTY_ )? json_value_on_mismatch_clause? ')' )? ; json_object_content : (json_object_entry (',' json_object_entry)* | '*') json_on_null_clause? json_return_clause? STRICT? ( WITH UNIQUE KEYS )? ; json_object_entry : (KEY? expression (VALUE | IS)? expression | expression ':' expression | identifier) ( FORMAT JSON )? ; json_table_clause : JSON_TABLE '(' expression (FORMAT JSON)? (',' CHAR_STRING)? ((ERROR | NULL_) ON ERROR)? ( (EMPTY_ | NULL_) ON EMPTY_ )? json_column_clause? ')' ; json_array_element : (expression | CHAR_STRING | NULL_ | UNSIGNED_INTEGER | json_function) (FORMAT JSON)? ; json_on_null_clause : (NULL_ | ABSENT) ON NULL_ ; json_return_clause : RETURNING (VARCHAR2 ('(' UNSIGNED_INTEGER ( BYTE | CHAR)? ')')? | CLOB | BLOB) ; json_transform_op : REMOVE CHAR_STRING ((IGNORE | ERROR)? ON MISSING)? | INSERT CHAR_STRING '=' CHAR_STRING ((REPLACE | IGNORE | ERROR) ON EXISTING)? ( (NULL_ | IGNORE | ERROR | REMOVE)? ON NULL_ )? | REPLACE CHAR_STRING '=' CHAR_STRING ((CREATE | IGNORE | ERROR) ON MISSING)? ( (NULL_ | IGNORE | ERROR)? ON NULL_ )? | expression (FORMAT JSON)? | APPEND CHAR_STRING '=' CHAR_STRING ((CREATE | IGNORE | ERROR) ON MISSING)? ( (NULL_ | IGNORE | ERROR)? ON NULL_ )? | SET CHAR_STRING '=' expression (FORMAT JSON)? ((REPLACE | IGNORE | ERROR) ON EXISTING)? ( (CREATE | IGNORE | ERROR) ON MISSING )? ((NULL_ | IGNORE | ERROR)? ON NULL_)? ; json_column_clause : COLUMNS '(' json_column_definition (',' json_column_definition)* ')' ; json_column_definition : expression json_value_return_type? (EXISTS? PATH CHAR_STRING | TRUNCATE (PATH CHAR_STRING)?)? json_query_on_error_clause? json_query_on_empty_clause? | expression json_query_return_type? TRUNCATE? FORMAT JSON json_query_wrapper_clause? PATH CHAR_STRING | NESTED PATH? expression ('[' ASTERISK ']')? json_column_clause | expression FOR ORDINALITY ; json_query_returning_clause : (RETURNING json_query_return_type)? PRETTY? ASCII? ; json_query_return_type : VARCHAR2 ('(' UNSIGNED_INTEGER ( BYTE | CHAR)? ')')? | CLOB | BLOB ; json_query_wrapper_clause : (WITHOUT ARRAY? WRAPPER) | (WITH (UNCONDITIONAL | CONDITIONAL)? ARRAY? WRAPPER) ; json_query_on_error_clause : (ERROR | NULL_ | EMPTY_ | EMPTY_ ARRAY | EMPTY_ OBJECT)? ON ERROR ; json_query_on_empty_clause : (ERROR | NULL_ | EMPTY_ | EMPTY_ ARRAY | EMPTY_ OBJECT)? ON EMPTY_ ; json_value_return_clause : RETURNING json_value_return_type? ASCII? ; json_value_return_type : VARCHAR2 ('(' UNSIGNED_INTEGER ( BYTE | CHAR)? ')')? TRUNCATE? | CLOB | DATE | NUMBER ('(' INTEGER (',' INTEGER)? ')')? | TIMESTAMP (WITH TIMEZONE)? | SDO_GEOMETRY | expression (USING CASESENSITIVE MAPPING)? ; json_value_on_mismatch_clause : (IGNORE | ERROR | NULL_) ON MISMATCH ('(' MISSING DATA | EXTRA DATA | TYPE ERROR ')')? ; literal : CHAR_STRING | string_function | numeric | numeric_negative | MAXVALUE ; numeric_function_wrapper : numeric_function (single_column_for_loop | multi_column_for_loop)? ; numeric_function : SUM '(' (DISTINCT | ALL)? expression ')' | COUNT '(' (ASTERISK | ((DISTINCT | UNIQUE | ALL)? concatenation)?) ')' over_clause? | ROUND '(' expression (',' UNSIGNED_INTEGER)? ')' | AVG '(' (DISTINCT | ALL)? expression ')' | MAX '(' (DISTINCT | ALL)? expression ')' | LEAST '(' expressions_ ')' | GREATEST '(' expressions_ ')' ; listagg_overflow_clause : ON OVERFLOW_ (ERROR | TRUNCATE) CHAR_STRING? ((WITH | WITHOUT) COUNT)? ; other_function : over_clause_keyword function_argument_analytic over_clause? | /*TODO stantard_function_enabling_using*/ regular_id function_argument_modeling using_clause? | COUNT '(' (ASTERISK | (DISTINCT | UNIQUE | ALL)? concatenation) ')' over_clause? | (CAST | XMLCAST) '(' (MULTISET '(' subquery ')' | concatenation) AS type_spec ( DEFAULT concatenation ON CONVERSION ERROR )? (',' quoted_string (',' quoted_string)?)? ')' | COALESCE '(' table_element (',' (numeric | quoted_string))? ')' | COLLECT '(' (DISTINCT | UNIQUE)? concatenation collect_order_by_part? ')' | within_or_over_clause_keyword function_argument within_or_over_part+ // Modified to allow expressions as delimiter to LISTAGG | LISTAGG '(' (ALL | DISTINCT | UNIQUE)? argument (',' expression)? listagg_overflow_clause? ')' ( WITHIN GROUP '(' order_by_clause ')' )? over_clause? | cursor_name (PERCENT_ISOPEN | PERCENT_FOUND | PERCENT_NOTFOUND | PERCENT_ROWCOUNT) | DECOMPOSE '(' concatenation (CANONICAL | COMPATIBILITY)? ')' | EXTRACT '(' regular_id FROM concatenation ')' | (FIRST_VALUE | LAST_VALUE) function_argument_analytic respect_or_ignore_nulls? over_clause | (LEAD | LAG) function_argument_analytic respect_or_ignore_nulls? over_clause | standard_prediction_function_keyword '(' expressions_ cost_matrix_clause? using_clause? ')' | (TO_BINARY_DOUBLE | TO_BINARY_FLOAT | TO_NUMBER | TO_TIMESTAMP | TO_TIMESTAMP_TZ) '(' concatenation ( DEFAULT concatenation ON CONVERSION ERROR )? (',' quoted_string (',' quoted_string)?)? ')' | (TO_DSINTERVAL | TO_YMINTERVAL) '(' concatenation (DEFAULT concatenation ON CONVERSION ERROR)? ')' | TRANSLATE '(' expression (USING (CHAR_CS | NCHAR_CS))? (',' expression)* ')' | TREAT '(' expression AS REF? type_spec ')' ('.' general_element_part)* | TRIM '(' ((LEADING | TRAILING | BOTH)? quoted_string? FROM)? concatenation ')' | VALIDATE_CONVERSION '(' concatenation AS type_spec (',' quoted_string (',' quoted_string)?)? ')' | XMLAGG '(' expression order_by_clause? ')' ('.' general_element_part)* | (XMLCOLATTVAL | XMLFOREST) '(' xml_multiuse_expression_element ( ',' xml_multiuse_expression_element )* ')' ('.' general_element_part)* | XMLELEMENT '(' (ENTITYESCAPING | NOENTITYESCAPING)? (NAME | EVALNAME)? expression ( /*TODO{input.LT(2).getText().equalsIgnoreCase("xmlattributes")}?*/ ',' xml_attributes_clause )? (',' expression column_alias?)* ')' ('.' general_element_part)* | XMLEXISTS '(' expression xml_passing_clause? ')' | XMLPARSE '(' (DOCUMENT | CONTENT) concatenation WELLFORMED? ')' ('.' general_element_part)* | XMLPI '(' (NAME identifier | EVALNAME concatenation) (',' concatenation)? ')' ( '.' general_element_part )* | XMLQUERY '(' concatenation xml_passing_clause? RETURNING CONTENT (NULL_ ON EMPTY_)? ')' ( '.' general_element_part )* | XMLROOT '(' concatenation (',' xmlroot_param_version_part)? ( ',' xmlroot_param_standalone_part )? ')' ('.' general_element_part)* | XMLSERIALIZE '(' (DOCUMENT | CONTENT) concatenation (AS type_spec)? xmlserialize_param_enconding_part? xmlserialize_param_version_part? xmlserialize_param_ident_part? ((HIDE | SHOW) DEFAULTS)? ')' ('.' general_element_part)? | TIME CHAR_STRING | xmltable ; over_clause_keyword : AVG | CORR | LAG_DIFF | LAG_DIFF_PERCENT | MAX | MEDIAN | MIN | NTH_VALUE | NTILE | RATIO_TO_REPORT | ROW_NUMBER | SUM | VARIANCE | REGR_ | STDDEV | VAR_ | VAR_POP | COVAR_ | WM_CONCAT ; within_or_over_clause_keyword : CUME_DIST | DENSE_RANK | PERCENT_RANK | PERCENTILE_CONT | PERCENTILE_DISC | RANK ; standard_prediction_function_keyword : PREDICTION | PREDICTION_BOUNDS | PREDICTION_COST | PREDICTION_DETAILS | PREDICTION_PROBABILITY | PREDICTION_SET ; over_clause : OVER '(' ( query_partition_clause? (order_by_clause windowing_clause?)? | HIERARCHY th = id_expression OFFSET numeric (ACROSS ANCESTOR AT LEVEL id_expression)? ) ')' ; windowing_clause : windowing_type (BETWEEN windowing_elements AND windowing_elements | windowing_elements) ; windowing_type : ROWS | RANGE ; windowing_elements : UNBOUNDED PRECEDING | CURRENT ROW | concatenation (PRECEDING | FOLLOWING) ; using_clause : USING (ASTERISK | using_element (',' using_element)*) ; using_element : IN expression | IN OUT assignable_element | OUT assignable_element | expression ; // Elemento assegnabile: usato per OUT/IN OUT assignable_element : general_element | bind_variable ; collect_order_by_part : ORDER BY concatenation (',' concatenation)* ; within_or_over_part : WITHIN GROUP '(' order_by_clause ')' | over_clause ; string_delimiter : CHAR_STRING | string_function | string_delimiter BAR BAR string_delimiter | '(' string_delimiter ')' | id_expression ; cost_matrix_clause : COST ( MODEL AUTO? | '(' cost_class_name (',' cost_class_name)* ')' VALUES '(' expressions_? ')' ) ; xml_passing_clause : PASSING (BY VALUE)? expression column_alias? (',' expression column_alias?)* ; xml_attributes_clause : XMLATTRIBUTES '(' (ENTITYESCAPING | NOENTITYESCAPING)? (SCHEMACHECK | NOSCHEMACHECK)? xml_multiuse_expression_element ( ',' xml_multiuse_expression_element )* ')' ; xml_namespaces_clause : XMLNAMESPACES '(' (concatenation column_alias)? (',' concatenation column_alias)* xml_general_default_part? ')' ; xml_table_column : xml_column_name (FOR ORDINALITY | type_spec (PATH concatenation)? xml_general_default_part?) ; xml_general_default_part : DEFAULT concatenation ; xml_multiuse_expression_element : expression ( (AS? id_expression) | (AS EVALNAME expression) )? ; xmlroot_param_version_part : VERSION (NO VALUE | expression) ; xmlroot_param_standalone_part : STANDALONE (YES | NO VALUE?) ; xmlserialize_param_enconding_part : ENCODING concatenation ; xmlserialize_param_version_part : VERSION concatenation ; xmlserialize_param_ident_part : NO INDENT | INDENT (SIZE '=' concatenation)? ; // Annotations annotations_clause : ANNOTATIONS '(' annotations_list ')' ; annotations_list : ( ADD (IF NOT EXISTS | OR REPLACE)? | DROP (IF EXISTS)? | REPLACE )? annotation (',' annotations_list)* ; annotation : identifier CHAR_STRING? ; // SqlPlus sql_plus_command : EXIT | PROMPT_MESSAGE | SHOW (ERR | ERRORS) | whenever_command | timing_command | start_command | set_command | clear_command ; start_command : START_CMD id_expression PERIOD (SQL | FILE_EXT) ; whenever_command : WHENEVER (SQLERROR | OSERROR) ( EXIT (SUCCESS | FAILURE | WARNING | variable_name | numeric) (COMMIT | ROLLBACK)? | CONTINUE (COMMIT | ROLLBACK | NONE)? ) ; set_command : SET ( (regular_id (ON | OFF))+ | (regular_id (CHAR_STRING | ON | OFF | /*EXACT_NUM_LIT*/ numeric | regular_id)) ) ; timing_command : TIMING (START timing_text = id_expression* | SHOW | STOP)? ; clear_command : CLEAR (COLUMN? regular_id) | ALL ; // Common partition_extension_clause : (SUBPARTITION | PARTITION) FOR? '(' expressions_? ')' ; column_alias : AS? (identifier | quoted_string) | AS ; table_alias : identifier | quoted_string ; where_clause : WHERE (CURRENT OF cursor_name | condition) ; into_clause : (BULK COLLECT)? INTO (general_element | bind_variable) ( ',' (general_element | bind_variable) )* ; // Common Named Elements xml_column_name : identifier | quoted_string ; cost_class_name : identifier ; attribute_name : identifier ; savepoint_name : identifier ; rollback_segment_name : identifier ; schema_name : identifier ; routine_name : identifier ('.' id_expression)* ('@' link_name)? ; package_name : identifier ; implementation_type_name : identifier ('.' id_expression)? ; parameter_name : identifier ; reference_model_name : identifier ; main_model_name : identifier ; container_tableview_name : identifier ('.' id_expression)? ; aggregate_function_name : identifier ('.' id_expression)* ; query_name : identifier ; grantee_name : id_expression identified_by? ; role_name : id_expression | CONNECT ; constraint_name : identifier ('.' id_expression)* ('@' link_name)? ; label_name : id_expression ; type_name : id_expression ('.' id_expression)* ; sequence_name : id_expression ('.' id_expression)* ; exception_name : identifier ('.' id_expression)* ; function_name : identifier ('.' id_expression)? ; procedure_name : identifier ('.' id_expression)? ; trigger_name : identifier ('.' id_expression)? ; variable_name : (INTRODUCER char_set_name)? id_expression ('.' id_expression)? | bind_variable ; index_name : identifier ('.' id_expression)? ; cursor_name : general_element | bind_variable ; record_name : identifier | bind_variable ; link_name : database ('.' domain)* (AT_SIGN connection_qualifier)? ; local_link_name : identifier ; connection_qualifier : identifier ; column_name : identifier ('.' id_expression)* ; tableview_name : identifier ('.' id_expression)? ( AT_SIGN link_name | /*TODO{!(input.LA(2) == BY)}?*/ partition_extension_clause )? | xmltable outer_join_sign? ; xmltable : XMLTABLE '(' (xml_namespaces_clause ',')? concatenation xml_passing_clause? ( COLUMNS xml_table_column (',' xml_table_column)* )? ')' ('.' general_element_part)? ; char_set_name : id_expression ('.' id_expression)* ; synonym_name : identifier ; // Represents a valid DB object name in DDL commands which are valid for several DB (or schema) objects. // For instance, create synonym ... for , or rename to . // Both are valid for sequences, tables, views, etc. schema_object_name : id_expression ; dir_object_name : id_expression ; user_object_name : id_expression ; grant_object_name : tableview_name | USER user_object_name (',' user_object_name)* | DIRECTORY dir_object_name | EDITION schema_object_name | MINING MODEL schema_object_name | JAVA (SOURCE | RESOURCE) schema_object_name | SQL TRANSLATION PROFILE schema_object_name ; column_list : column_name (',' column_name)* ; paren_column_list : LEFT_PAREN column_list RIGHT_PAREN ; // PL/SQL Specs // NOTE: In reality this applies to aggregate functions only keep_clause : KEEP '(' DENSE_RANK (FIRST | LAST) (query_partition_clause | order_by_clause) ')' over_clause? ; function_argument : '(' (argument (',' argument)*)? ')' keep_clause? ; function_argument_analytic : '(' (argument respect_or_ignore_nulls? (',' argument respect_or_ignore_nulls?)*)? ')' keep_clause? ; function_argument_modeling : '(' column_name (',' (numeric | NULL_) (',' (numeric | NULL_))?)? USING ( tableview_name '.' ASTERISK | ASTERISK | expression column_alias? (',' expression column_alias?)* ) ')' keep_clause? ; respect_or_ignore_nulls : (RESPECT | IGNORE) NULLS ; argument : (identifier '=' '>')? expression ; type_spec : datatype | REF? type_name (PERCENT_ROWTYPE | PERCENT_TYPE)? ; datatype : native_datatype_element precision_part? (WITH LOCAL? TIME ZONE | CHARACTER SET char_set_name)? | INTERVAL (YEAR | DAY) ('(' expression ')')? TO (MONTH | SECOND) ('(' expression ')')? ; precision_part : '(' (numeric | ASTERISK) (',' (numeric | numeric_negative))? (CHAR | BYTE)? ')' ; native_datatype_element : BINARY_INTEGER | PLS_INTEGER | NATURAL | BINARY_FLOAT | BINARY_DOUBLE | NATURALN | POSITIVE | POSITIVEN | SIGNTYPE | SIMPLE_INTEGER | NVARCHAR2 | DEC | INTEGER | INT | NUMERIC | SMALLINT | NUMBER | DECIMAL | DOUBLE PRECISION? | FLOAT | REAL | NCHAR | LONG RAW? | CHAR | CHARACTER VARYING? | VARCHAR2 | VARCHAR | STRING | RAW | BOOLEAN | DATE | ROWID | UROWID | YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | SDO_GEOMETRY | TIMEZONE_HOUR | TIMEZONE_MINUTE | TIMEZONE_REGION | TIMEZONE_ABBR | TIMESTAMP | TIMESTAMP_UNCONSTRAINED | TIMESTAMP_TZ_UNCONSTRAINED | TIMESTAMP_LTZ_UNCONSTRAINED | YMINTERVAL_UNCONSTRAINED | DSINTERVAL_UNCONSTRAINED | BFILE | BLOB | CLOB | NCLOB | MLSLABEL | XMLTYPE ; bind_variable : (BINDVAR | ':' UNSIGNED_INTEGER) // Pro*C/C++ indicator variables (INDICATOR? (BINDVAR | ':' UNSIGNED_INTEGER))? ('.' general_element_part)* ; general_element : general_element_part | general_element ('.' general_element_part)+ | '(' general_element ')' ; general_element_part : (INTRODUCER char_set_name)? id_expression ('@' link_name)? function_argument* ; table_element : (INTRODUCER char_set_name)? id_expression ('.' id_expression)* ; object_privilege : ALL PRIVILEGES? | ALTER | DEBUG | DELETE | EXECUTE | FLASHBACK | FLASHBACK ARCHIVE | INDEX | INHERIT PRIVILEGES | INHERIT REMOTE PRIVILEGES | INSERT | KEEP SEQUENCE | MERGE VIEW | ON COMMIT REFRESH | QUERY REWRITE | READ | REFERENCES | SELECT | TRANSLATE SQL | UNDER | UPDATE | USE | WRITE ; //Ordered by type rather than alphabetically system_privilege : ALL PRIVILEGES | ADVISOR | ADMINISTER ANY? SQL TUNING SET | (ALTER | CREATE | DROP) ANY SQL PROFILE | ADMINISTER SQL MANAGEMENT OBJECT | CREATE ANY? CLUSTER | (ALTER | DROP) ANY CLUSTER | (CREATE | DROP) ANY CONTEXT | EXEMPT REDACTION POLICY | ALTER DATABASE | (ALTER | CREATE) PUBLIC? DATABASE LINK | DROP PUBLIC DATABASE LINK | DEBUG CONNECT SESSION | DEBUG ANY PROCEDURE | ANALYZE ANY DICTIONARY | CREATE ANY? DIMENSION | (ALTER | DROP) ANY DIMENSION | (CREATE | DROP) ANY DIRECTORY | (CREATE | DROP) ANY EDITION | FLASHBACK (ARCHIVE ADMINISTER | ANY TABLE) | (ALTER | CREATE | DROP) ANY INDEX | CREATE ANY? INDEXTYPE | (ALTER | DROP | EXECUTE) ANY INDEXTYPE | CREATE (ANY | EXTERNAL)? JOB | EXECUTE ANY (CLASS | PROGRAM) | MANAGE SCHEDULER | ADMINISTER KEY MANAGEMENT | CREATE ANY? LIBRARY | (ALTER | DROP | EXECUTE) ANY LIBRARY | LOGMINING | CREATE ANY? MATERIALIZED VIEW | (ALTER | DROP) ANY MATERIALIZED VIEW | GLOBAL? QUERY REWRITE | ON COMMIT REFRESH | CREATE ANY? MINING MODEL | (ALTER | DROP | SELECT | COMMENT) ANY MINING MODEL | CREATE ANY? CUBE | (ALTER | DROP | SELECT | UPDATE) ANY CUBE | CREATE ANY? MEASURE FOLDER | (DELETE | DROP | INSERT) ANY MEASURE FOLDER | CREATE ANY? CUBE DIMENSION | (ALTER | DELETE | DROP | INSERT | SELECT | UPDATE) ANY CUBE DIMENSION | CREATE ANY? CUBE BUILD PROCESS | (DROP | UPDATE) ANY CUBE BUILD PROCESS | CREATE ANY? OPERATOR | (ALTER | DROP | EXECUTE) ANY OPERATOR | (CREATE | ALTER | DROP) ANY OUTLINE | CREATE PLUGGABLE DATABASE | SET CONTAINER | CREATE ANY? PROCEDURE | (ALTER | DROP | EXECUTE) ANY PROCEDURE | (CREATE | ALTER | DROP) PROFILE | CREATE ROLE | (ALTER | DROP | GRANT) ANY ROLE | (CREATE | ALTER | DROP) ROLLBACK SEGMENT | CREATE ANY? SEQUENCE | (ALTER | DROP | SELECT) ANY SEQUENCE | (ALTER | CREATE | RESTRICTED) SESSION | ALTER RESOURCE COST | CREATE ANY? SQL TRANSLATION PROFILE | (ALTER | DROP | USE) ANY SQL TRANSLATION PROFILE | TRANSLATE ANY SQL | CREATE ANY? SYNONYM | DROP ANY SYNONYM | (CREATE | DROP) PUBLIC SYNONYM | CREATE ANY? TABLE | (ALTER | BACKUP | COMMENT | DELETE | DROP | INSERT | LOCK | READ | SELECT | UPDATE) ANY TABLE | (CREATE | ALTER | DROP | MANAGE | UNLIMITED) TABLESPACE | CREATE ANY? TRIGGER | (ALTER | DROP) ANY TRIGGER | ADMINISTER DATABASE TRIGGER | CREATE ANY? TYPE | (ALTER | DROP | EXECUTE | UNDER) ANY TYPE | (CREATE | ALTER | DROP) USER | CREATE ANY? VIEW | (DROP | UNDER | MERGE) ANY VIEW | (ANALYZE | AUDIT) ANY | BECOME USER | CHANGE NOTIFICATION | EXEMPT ACCESS POLICY | FORCE ANY? TRANSACTION | GRANT ANY OBJECT? PRIVILEGE | INHERIT ANY PRIVILEGES | KEEP DATE TIME | KEEP SYSGUID | PURGE DBA_RECYCLEBIN | RESUMABLE | SELECT ANY (DICTIONARY | TRANSACTION) | SYSBACKUP | SYSDBA | SYSDG | SYSKM | SYSOPER ; // $> // $(AntlrCaches(OracleParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: OracleParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(OracleParser._ATN)) } } ================================================ FILE: superior-oracle-parser/src/main/kotlin/io/github/melin/superior/parser/oracle/OracleSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.oracle import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.AlterTable import io.github.melin.superior.common.relational.alter.AlterTableAction import io.github.melin.superior.common.relational.common.CallProcedure import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropFunction import io.github.melin.superior.common.relational.drop.DropProcedure import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.parser.oracle.antlr4.OracleParser import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Cursor_declarationContext import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Function_nameContext import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Multi_table_elementContext import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Procedure_nameContext import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Select_list_elementsContext import io.github.melin.superior.parser.oracle.antlr4.OracleParser.Seq_of_statementsContext import io.github.melin.superior.parser.oracle.antlr4.OracleParserBaseVisitor import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:57 上午 */ class OracleSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : OracleParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var queryStmt: QueryStmt? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() // 多语句解析结果 private var statements: ArrayList = arrayListOf() // 存储过程和函数中包含的子语句 private var childStatements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { if (currentResult != null) { if (node is Cursor_declarationContext || node is Seq_of_statementsContext) { childStatements.add(currentResult) clean() } } if (node is OracleParser.Unit_statementContext) { clean() } return true } override fun visitSql_script(ctx: OracleParser.Sql_scriptContext): Statement? { ctx.sql_plus_command().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSql_plus_command(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) currentOptType = StatementType.UNKOWN } } ctx.unit_statement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitUnit_statement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) currentOptType = StatementType.UNKOWN } } return null } private fun clean() { limit = null offset = null queryStmt = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() } private fun addOutputTableId(tableId: TableId) { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } override fun visitCreate_database(ctx: OracleParser.Create_databaseContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.database_name().text) return CreateDatabase(databaseName) } override fun visitCreate_table(ctx: OracleParser.Create_tableContext): Statement { currentOptType = StatementType.CREATE_TABLE val schemaName = if (ctx.schema_name() != null) ctx.schema_name().text else null val tableName = ctx.table_name().text val tableId = TableId(schemaName, tableName) val pks: ArrayList = arrayListOf() val columnRels = ctx.relational_table() .relational_property() .filter { val constraint = it.out_of_line_constraint() if (constraint != null && constraint.PRIMARY() != null) { constraint.column_name().forEach { pks.add(it.text) } } it.column_definition() != null } .map { val colDef = it.column_definition() val columnName = colDef.column_name().text val dataType = colDef.datatype().text val defaultExpr: String? = if (colDef.expression() != null) colDef.expression().text else null var isPk = if (pks.contains(columnName)) true else false var nullable = true if (colDef.inline_constraint() != null) { colDef.inline_constraint().forEach { constraint -> if (constraint.NOT() != null) { nullable = false } if (constraint.PRIMARY() != null) { isPk = true } } } ColumnRel(columnName, dataType, defaultExpr = defaultExpr, nullable = nullable, primaryKey = isPk) } return CreateTable(tableId, TableType.ORACLE, columnRels = columnRels) } override fun visitCreate_view(ctx: OracleParser.Create_viewContext): Statement { currentOptType = StatementType.CREATE_VIEW val schemaName = if (ctx.schema_name() != null) ctx.schema_name().text else null val tableName = ctx.v.text val tableId = TableId(schemaName, tableName) val replace = if (ctx.REPLACE() != null) true else false val queryStmt = this.parseSelect_only_statement(ctx.select_only_statement()) as QueryStmt val createView = CreateView(tableId, queryStmt) createView.replace = replace return createView } override fun visitCreate_materialized_view(ctx: OracleParser.Create_materialized_viewContext): Statement { currentOptType = StatementType.CREATE_MATERIALIZED_VIEW val tableId = parseTableViewName(ctx.tableview_name()) // val ifNotExists = if (ctx.IF_P() != null) true else false val queryStmt = this.parseSelect_only_statement(ctx.select_only_statement()) as QueryStmt val createView = CreateMaterializedView(tableId, queryStmt) super.visitSelect_only_statement(ctx.select_only_statement()) return createView } override fun visitCreate_procedure_body(ctx: OracleParser.Create_procedure_bodyContext): Statement { childStatements = arrayListOf() super.visitCreate_procedure_body(ctx) val procedureName = ctx.procedure_name() val procedureId = parseProcedureName(procedureName) return CreateProcedure(procedureId, childStatements) } override fun visitCreate_function_body(ctx: OracleParser.Create_function_bodyContext): Statement { childStatements = arrayListOf() super.visitCreate_function_body(ctx) val funcName = ctx.function_name() val functionId = parseFunctionName(funcName) val function = CreateFunction(functionId, childStatements) return function } override fun visitDrop_database(ctx: OracleParser.Drop_databaseContext): Statement? { return DropDatabase("") } override fun visitDrop_table(ctx: OracleParser.Drop_tableContext): Statement? { val tableId = parseTableViewName(ctx.tableview_name().get(0)) val ifExists = ctx.EXISTS() != null val purge = ctx.PURGE() != null val dropTable = DropTable(tableId, ifExists) dropTable.purge = purge return dropTable } override fun visitDrop_function(ctx: OracleParser.Drop_functionContext): Statement { val funcName = ctx.function_name() val functionId = parseFunctionName(funcName) return DropFunction(functionId) } override fun visitDrop_procedure(ctx: OracleParser.Drop_procedureContext): Statement { val procedureName = ctx.procedure_name() val procedureId = parseProcedureName(procedureName) return DropProcedure(procedureId) } override fun visitAnonymous_block(ctx: OracleParser.Anonymous_blockContext?): Statement { childStatements = arrayListOf() super.visitAnonymous_block(ctx) return CreateProcedure(childStatements) } override fun visitCall_statement(ctx: OracleParser.Call_statementContext): Statement { val procedureId = ProcedureId(ctx.routine_name().get(0).text) val callProcedure = CallProcedure(procedureId) callProcedure.setSql(source(ctx)) return callProcedure } override fun visitAlter_table(ctx: OracleParser.Alter_tableContext): Statement { val tableId = parseTableViewName(ctx.tableview_name()) return AlterTable(tableId) } override fun visitAlter_view(ctx: OracleParser.Alter_viewContext): Statement { val tableId = parseTableViewName(ctx.tableview_name()) val action = AlterTableAction(AlterActionType.ALTER_VIEW_QUERY) return AlterTable(tableId, action) } override fun visitSelect_statement(ctx: OracleParser.Select_statementContext): Statement? { currentOptType = StatementType.SELECT super.visitSelect_statement(ctx) if (queryStmt == null) { queryStmt = QueryStmt(inputTables, limit, offset) } queryStmt?.setSql(source(ctx)) return queryStmt } private fun parseSelect_only_statement(ctx: OracleParser.Select_only_statementContext): Statement? { currentOptType = StatementType.SELECT super.visitSelect_only_statement(ctx) if (queryStmt == null) { queryStmt = QueryStmt(inputTables, limit, offset) } return queryStmt } override fun visitDelete_statement(ctx: OracleParser.Delete_statementContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableViewName(ctx.general_table_ref().dml_table_expression_clause().tableview_name()) addOutputTableId(tableId) super.visitWhere_clause(ctx.where_clause()) return DeleteTable(tableId, inputTables) } override fun visitUpdate_statement(ctx: OracleParser.Update_statementContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableViewName(ctx.general_table_ref().dml_table_expression_clause().tableview_name()) addOutputTableId(tableId) super.visitWhere_clause(ctx.where_clause()) return UpdateTable(tableId, inputTables) } override fun visitInsert_statement(ctx: OracleParser.Insert_statementContext): Statement { currentOptType = StatementType.INSERT val insertTable = if (ctx.single_table_insert() != null) { val tableInsert = ctx.single_table_insert() val tableId = parseTableViewName( tableInsert .insert_into_clause() .general_table_ref() .dml_table_expression_clause() .tableview_name() ) addOutputTableId(tableId) if (tableInsert.select_statement() != null) { val queryStmt = this.visitSelect_statement(tableInsert.select_statement()) as QueryStmt InsertTable(InsertMode.INTO, queryStmt, tableId) } else { InsertTable(InsertMode.INTO, QueryStmt(), tableId) } } else { if (ctx.multi_table_insert().conditional_insert_clause() == null) { val tableInserts = ctx.multi_table_insert().multi_table_element() addOutputTableId(tableInserts) } else { ctx.multi_table_insert().conditional_insert_clause().conditional_insert_when_part().map { addOutputTableId(it.multi_table_element()) } val elseElem = ctx.multi_table_insert().conditional_insert_clause().conditional_insert_else_part() if (elseElem != null) { addOutputTableId(elseElem.multi_table_element()) } } if (ctx.multi_table_insert().select_statement() != null) { val queryStmt = this.visitSelect_statement(ctx.multi_table_insert().select_statement()) as QueryStmt InsertTable(InsertMode.INTO, queryStmt, outputTables.first()) } else { InsertTable(InsertMode.INTO, QueryStmt(), outputTables.first()) } } insertTable.outputTables.addAll(outputTables.subList(1, outputTables.size)) //insertTable?.setSql(CommonUtils.subsql(command, ctx)) insertTable?.setSql(source(ctx)) return insertTable } override fun visitExecute_immediate(ctx: OracleParser.Execute_immediateContext): Statement? { var execSql = CommonUtils.cleanQuote(ctx.expression().text) execSql = StringUtils.replace(execSql, "''", "'") val statements = OracleSqlHelper.parseMultiStatement(execSql) childStatements.addAll(statements) return null } private fun parseFunctionName(funcName: Function_nameContext): FunctionId { return if (funcName.id_expression() != null) { FunctionId(funcName.identifier().text, funcName.id_expression().text) } else { FunctionId(funcName.identifier().text) } } private fun parseProcedureName(procedureName: Procedure_nameContext): ProcedureId { return if (procedureName.id_expression() != null) { ProcedureId(procedureName.identifier().text, procedureName.id_expression().text) } else { ProcedureId(procedureName.identifier().text) } } private fun addOutputTableId(list: List) { list.forEach { val tableId = parseTableViewName( it.insert_into_clause().general_table_ref().dml_table_expression_clause().tableview_name() ) addOutputTableId(tableId) } } override fun visitMerge_statement(ctx: OracleParser.Merge_statementContext): Statement { currentOptType = StatementType.MERGE val mergeTableId = parseTableViewName(ctx.tableview_name()) cteTempTables.add(mergeTableId) val mergeTable = MergeTable(mergeTableId) mergeTable.inputTables = inputTables super.visitMerge_statement(ctx) return mergeTable } override fun visitComment_on_column(ctx: OracleParser.Comment_on_columnContext): Statement { val objValue = ctx.column_name().text val isNull = false val text: String = CommonUtils.cleanQuote(ctx.quoted_string().text) return CommentStatement(text, isNull, "COLUMN", objValue) } override fun visitComment_on_table(ctx: OracleParser.Comment_on_tableContext): Statement { val objValue = ctx.tableview_name().text val isNull = false val text: String = CommonUtils.cleanQuote(ctx.quoted_string().text) return CommentStatement(text, isNull, "TABLE", objValue) } override fun visitComment_on_materialized(ctx: OracleParser.Comment_on_materializedContext): Statement { val objValue = ctx.tableview_name().text val isNull = false val text: String = CommonUtils.cleanQuote(ctx.quoted_string().text) return CommentStatement(text, isNull, "MATERIALIZED VIEW", objValue) } override fun visitSubquery_factoring_clause(ctx: OracleParser.Subquery_factoring_clauseContext): Statement? { cteTempTables.add(TableId(ctx.query_name().text)) return super.visitSubquery_factoring_clause(ctx) } override fun visitOffset_clause(ctx: OracleParser.Offset_clauseContext): Statement? { try { offset = ctx.expression().text.toInt() } catch (e: Exception) {} return super.visitOffset_clause(ctx) } override fun visitFetch_clause(ctx: OracleParser.Fetch_clauseContext): Statement? { try { limit = ctx.expression().text.toInt() } catch (e: Exception) {} return super.visitFetch_clause(ctx) } override fun visitCursor_declaration(ctx: OracleParser.Cursor_declarationContext): Statement? { super.visitCursor_declaration(ctx) return null } override fun visitTableview_name(ctx: OracleParser.Tableview_nameContext): Statement? { if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.CREATE_MATERIALIZED_VIEW || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.MERGE || currentOptType == StatementType.INSERT || currentOptType == StatementType.CREATE_FUNCTION || currentOptType == StatementType.CREATE_PROCEDURE ) { if (ctx.parent is Select_list_elementsContext) { return null } val tableId = parseTableViewName(ctx) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } private fun parseTableViewName(ctx: OracleParser.Tableview_nameContext): TableId { if (ctx.childCount == 1) { return TableId(null, null, ctx.getChild(0).text) } else if (ctx.childCount == 3) { return TableId(null, ctx.getChild(0).text, ctx.getChild(2).text) } else { throw SQLParserException("not suuport tablename") } } } ================================================ FILE: superior-oracle-parser/src/main/kotlin/io/github/melin/superior/parser/oracle/OracleSqlHelper.kt ================================================ package io.github.melin.superior.parser.oracle import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.oracle.antlr4.OracleLexer import io.github.melin.superior.parser.oracle.antlr4.OracleParser import io.github.melin.superior.parser.oracle.antlr4.OracleParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:58 上午 */ object OracleSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until OracleLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = OracleLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { var sql = StringUtils.trim(command) if (!StringUtils.endsWith(sql, ";")) { sql += ";" } val statements = this.parseMultiStatement(sql) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = OracleSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { var trimCmd = StringUtils.trim(command) if (!StringUtils.endsWith(trimCmd, ";")) { trimCmd += ";" } val sqlVisitor = OracleSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { var trimCmd = StringUtils.trim(command) if (!StringUtils.endsWith(trimCmd, ";")) { trimCmd += ";" } val sqlVisitor = OracleParserBaseVisitor() innerParseStatement(trimCmd, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: OracleParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = OracleLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = OracleParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) // parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sql_script()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.sql_script()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-oracle-parser/src/test/java/io/github/melin/superior/parser/oracle/OracleProcessParserTest.kt ================================================ package io.github.melin.superior.parser.oracle import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.CallProcedure import io.github.melin.superior.common.relational.create.CreateFunction import io.github.melin.superior.common.relational.create.CreateProcedure import io.github.melin.superior.common.relational.drop.DropFunction import io.github.melin.superior.common.relational.drop.DropProcedure import org.junit.Assert import org.junit.Test class OracleProcessParserTest { @Test fun processTest0() { val sql = """ DECLARE CURSOR C_ORDERS IS SELECT CUSTOMER_NAME, PRICE FROM ORDERS; BEGIN FOR ORD IN C_ORDERS LOOP SELECT CUSTOMER_NAME, PRICE FROM ORDERS_TEST; SELECT CUSTOMER_NAME, PRICE FROM ORDERS_TEST_1; dbms_output.put_line(ORD.CUSTOMER_NAME || ORD.PRICE); END LOOP; END; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(4, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest() { val sql = """ CREATE FUNCTION test.get_bal(acc_no IN NUMBER) RETURN NUMBER IS acc_bal NUMBER(11,2); BEGIN SELECT order_total INTO acc_bal FROM orders WHERE customer_id = acc_no; RETURN(acc_bal); END; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("test", "get_bal"), statement.functionId) Assert.assertEquals(1, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest1() { val sql = """ CREATE FUNCTION get_bal(acc_no IN NUMBER) RETURN NUMBER IS acc_bal NUMBER(11,2); BEGIN SELECT order_total INTO acc_bal FROM orders WHERE customer_id = acc_no; RETURN(acc_bal); END; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId( "get_bal"), statement.functionId) Assert.assertEquals(1, statement.childStatements.size) } else { Assert.fail() } } @Test fun createProcedureTest0() { val sql = """ CREATE OR REPLACE Procedure UpdateCourse( name_in IN varchar2 ) IS cnumber number; cursor c1 is SELECT course_number FROM courses_tbl WHERE course_name = name_in; BEGIN open c1; fetch c1 into cnumber; if c1%notfound then cnumber := 9999; end if; INSERT INTO student_courses( course_name,course_number ) VALUES ( name_in, cnumber ); commit; close c1; EXCEPTION WHEN OTHERS THEN raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM); END; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId("UpdateCourse"), statement.procedureId) Assert.assertEquals(3, statement.childStatements.size) } else { Assert.fail() } } @Test fun dropTest() { val sql = """ DROP FUNCTION get_bal; DROP PROCEDURE demos.UpdateCourse; """.trimIndent() val statements = OracleSqlHelper.parseMultiStatement(sql) val dropFunction = statements.get(0) val dropProcess = statements.get(1) if (dropFunction is DropFunction) { Assert.assertEquals("get_bal", dropFunction.functionId.functionName) } else { Assert.fail() } if (dropProcess is DropProcedure) { Assert.assertEquals("demos", dropProcess.procedureId.schemaName) Assert.assertEquals("UpdateCourse", dropProcess.procedureId.procedureName) } else { Assert.fail() } } @Test fun callProcessTest() { val sql = """ Call UpdateCourse('tes'); begin UpdateCourse('tes'); end; """.trimIndent() val statements = OracleSqlHelper.parseMultiStatement(sql) val procedure1 = statements.get(0) val procedure2 = statements.get(1) if (procedure1 is CallProcedure) { Assert.assertEquals("UpdateCourse", procedure1.procedureIds.first().procedureName) } else { Assert.fail() } if (procedure2 is CreateProcedure) { Assert.assertEquals(1, procedure2.childStatements.size) } else { Assert.fail() } } @Test fun processTest4() { val sql = """ DECLARE CURSOR C_ORDERS IS SELECT CUSTOMER_NAME, PRICE FROM ORDERS; BEGIN FOR ORD IN C_ORDERS LOOP SELECT CUSTOMER_NAME, PRICE FROM ORDERS_TEST; SELECT CUSTOMER_NAME, PRICE FROM ORDERS_TEST_1; dbms_output.put_line(ORD.CUSTOMER_NAME || ORD.PRICE); END LOOP; END; CREATE FUNCTION test.get_bal(acc_no IN NUMBER) RETURN NUMBER IS acc_bal NUMBER(11,2); BEGIN SELECT order_total INTO acc_bal FROM orders WHERE customer_id = acc_no; RETURN(acc_bal); END; """.trimIndent() val statements = OracleSqlHelper.parseMultiStatement(sql) Assert.assertEquals(2, statements.size) var statement = statements.get(0) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(4, statement.childStatements.size) } else { Assert.fail() } statement = statements.get(1) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(1, statement.childStatements.size) Assert.assertEquals("SELECT order_total \n" + " INTO acc_bal \n" + " FROM orders \n" + " WHERE customer_id = acc_no", statement.childStatements.get(0).getSql()) } else { Assert.fail() } } @Test fun processTest5() { val sql = """ CREATE OR REPLACE PROCEDURE create_and_manipulate_tables AS BEGIN EXECUTE IMMEDIATE ' CREATE TABLE schema1.test_table_s1 ( id NUMBER PRIMARY KEY, name VARCHAR2(100) ) '; EXECUTE IMMEDIATE 'INSERT INTO schema1.test_table_s1 (id, name) VALUES (1, ''Alice'')'; END; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId("create_and_manipulate_tables"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) Assert.assertEquals(StatementType.CREATE_TABLE, statement.childStatements.get(0).statementType) Assert.assertEquals(StatementType.INSERT, statement.childStatements.get(1).statementType) Assert.assertEquals("INSERT INTO schema1.test_table_s1 (id, name) VALUES (1, 'Alice')", statement.childStatements.get(1).getSql()) } else { Assert.fail() } } } ================================================ FILE: superior-oracle-parser/src/test/java/io/github/melin/superior/parser/oracle/OracleSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.oracle import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.create.CreateDatabase import io.github.melin.superior.common.relational.create.CreateMaterializedView import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropTable import org.junit.Assert import org.junit.Test class OracleSqlParserDdlTest { @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE bigdata1 USER SYSTEM IDENTIFIED BY 123213; DROP DATABASE INCLUDING BACKUPS NOPROMPT """.trimIndent() val statements = OracleSqlHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("bigdata1", createDatabse.databaseName) } else { Assert.fail() } if (dropDatabase is DropDatabase) { Assert.assertTrue(true) Assert.assertEquals(StatementType.DROP_DATABASE, dropDatabase.statementType) } else { Assert.fail() } } @Test fun createTableTest0() { val sql = """ CREATE TABLE employees( employee_id number(10) NOT NULL, employee_name varchar2(50) NOT NULL, city varchar2(50), CONSTRAINT employees_pk PRIMARY KEY (employee_id) ) """.trimIndent() OracleSqlHelper.splitSql(sql) val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertEquals(3, statement.columnRels?.size) Assert.assertTrue(statement.columnRels?.get(0)?.primaryKey!!) Assert.assertFalse(statement.columnRels?.get(1)?.primaryKey!!) } else { Assert.fail() } } @Test fun createView0() { val sql = """ CREATE OR REPLACE VIEW comedies AS SELECT f.*, country_code_to_name(f.country_code) AS country, (SELECT avg(r.rating) FROM user_ratings r WHERE r.film_id = f.id) AS avg_rating FROM films f WHERE f.kind = 'Comedy' """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("comedies", statement.tableId.tableName) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun createMatView0() { val sql = """ CREATE MATERIALIZED VIEW sales_summary AS SELECT seller_no, invoice_date, sum(invoice_amt) as sales_amt FROM invoice WHERE invoice_date < CURRENT_DATE GROUP BY seller_no, invoice_date; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is CreateMaterializedView) { Assert.assertEquals(StatementType.CREATE_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals("sales_summary", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun commentTest0() { val sql = """ COMMENT ON COLUMN employees.job_id IS 'abbreviated job title'; COMMENT ON COLUMN employees1.job_id IS 'abbreviated job title' """.trimIndent() val statement = OracleSqlHelper.parseMultiStatement(sql) val st1 = statement.get(0) val st2 = statement.get(1) if (st1 is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, st1.statementType) Assert.assertEquals("employees.job_id", st1.objValue) Assert.assertEquals("abbreviated job title", st1.comment) Assert.assertFalse(st1.isNull) } if (st2 is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, st2.statementType) Assert.assertEquals("employees1.job_id", st2.objValue) Assert.assertEquals("abbreviated job title", st2.comment) Assert.assertFalse(st2.isNull) } } @Test fun dropTableTest() { val sql = """ drop table employees purge; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertTrue(statement.purge) } else { Assert.fail() } } } ================================================ FILE: superior-oracle-parser/src/test/java/io/github/melin/superior/parser/oracle/OracleSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.oracle import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.dml.* import org.apache.commons.io.FileUtils import org.junit.Assert import org.junit.Test import java.io.File class OracleSqlParserDmlTest { @Test fun querySqlTest0() { val sql1 = FileUtils.readFileToString(File("./src/test/resources/insert.sql"), "UTF-8") val statement = OracleSqlHelper.parseStatement(sql1) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(27, statement.queryStmt.inputTables.size) Assert.assertEquals(TableId("dwd", "dwd_d03_contract_det_s"), statement.outputTables.get(0)) } else { Assert.fail() } } @Test fun querySqlTest1() { val sql = """ select 1; """.trimIndent() try { OracleSqlHelper.parseStatement(sql) Assert.fail() } catch (e: Exception) { Assert.assertTrue(true) } } @Test fun cteSqlTest0() { val sql = """ WITH cte1 AS (SELECT a, b FROM table1), cte2 AS (SELECT c, d FROM table2) SELECT b, d FROM cte1 JOIN cte2 WHERE cte1.a = cte2.c """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(TableId("table1"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun deleteTest() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun insertTest0() { val sql = """ INSERT ALL INTO pivot_dest (id, day, val) VALUES (id, 'mon', mon_val) INTO pivot_dest (id, day, val) VALUES (id, 'tue', tue_val) INTO pivot_dest (id, day, val) VALUES (id, 'wed', wed_val) INTO pivot_dest (id, day, val) VALUES (id, 'thu', thu_val) INTO pivot_dest (id, day, val) VALUES (id, 'fri', fri_val) SELECT * FROM pivot_source; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("pivot_dest", statement.outputTables.get(0).tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest1() { val sql = """ INSERT ALL INTO dest_tab1 (id, description) VALUES (id, description) INTO dest_tab2 (id, description) VALUES (id, description) INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest2() { val sql = """ INSERT ALL WHEN id <= 3 THEN INTO dest_tab1 (id, description) VALUES (id, description) WHEN id BETWEEN 4 AND 7 THEN INTO dest_tab2 (id, description) VALUES (id, description) WHEN id >= 8 THEN INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest3() { val sql = """ INSERT FIRST WHEN id <= 3 THEN INTO dest_tab1 (id, description) VALUES (id, description) WHEN id <= 5 THEN INTO dest_tab2 (id, description) VALUES (id, description) ELSE INTO dest_tab3 (id, description) VALUES (id, description) SELECT id, description FROM source_tab; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("dest_tab1", statement.outputTables.get(0).tableName) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest4() { val sql = """ INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest() { val sql = """ MERGE INTO bonuses D USING (SELECT employee_id, salary, department_id FROM hr.employees WHERE department_id = 80) S ON (D.employee_id = S.employee_id) WHEN MATCHED THEN UPDATE SET D.bonus = D.bonus + S.salary*.01 DELETE WHERE (S.salary > 8000) WHEN NOT MATCHED THEN INSERT (D.employee_id, D.bonus) VALUES (S.employee_id, S.salary*.01) WHERE (S.salary <= 8000); """.trimIndent() val statement = OracleSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("bonuses", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-oracle-parser/src/test/resources/insert.sql ================================================ insert into dwd.dwd_d03_contract_det_s select to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') stt_date ,to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') end_date ,'01' cont_source_cd -- 合同来源编码: 01-通用核心; 02-商用车 ,'通用核心' cont_source_nm -- 合同来源:通用核心/商用车 ,cc.pk_contract -- 合同主键 ,cc.cont_code -- 合同编码 ,cc.cont_name -- 合同名称 ,cc.cont_type cont_type_cd -- 合同类型编码 ,pt2.param_name cont_type_nm -- 合同类型名称 ,cc.cont_status cont_status_cd -- 合同状态编码 ,pt1.param_name cont_status_nm -- 合同状态名称 ,pt3.param_value economic_style_cd -- 控股类型编码 ,replace(replace(pt3.param_name ,'绝对',''),'相对','') economic_style_nm -- 控股类型 ,cc.cont_amount -- 合同金额 ,cc.lease_date_fact -- 起租日 ,cc.cont_end_date -- 到期日 ,lc.lease_times lease_times -- 租赁期(月数) ,round(lc.lease_times/12,2) lease_year -- 租赁期(年数) ,case when cc.cont_amount >= 100000000 then '大型' when cc.cont_amount >= 10000000 and cc.cont_amount < 100000000 then '中型' else '小型' end cont_scala -- 合同规模 ,case when cc.if_adjust = 0 then '是' when cc.if_adjust = 1 then '否' else null end if_adjust -- 是否调息 ,sjtf.fact_cash_loan -- 已投放金额 ,sjtf.pay_date -- 首次投放日期 ,ba1.name pay_province -- 投放地区省 ,ba2.name pay_city -- 投放地区市 ,ba3.name pay_area -- 客户所属区 ,coalesce(nn.assets_classify, cc.assets_classify, 0) assets_classify_cd -- 五级分类代码 ,case coalesce(nn.assets_classify, cc.assets_classify, 0) when 0 then '正常' when 1 then '关注' when 2 then '次级' when 3 then '可疑' when 4 then '损失' else '正常' end assets_classify_nm -- 五级分类名称 ,pi.pk_project_info -- 项目编号 ,pi.project_name -- 项目名称 ,pi.lease_categry lease_categry_cd -- 租赁类型代码 ,case when pi.lease_categry = 0 then '融资租赁' when pi.lease_categry = 1 then '经营性租赁' else null end lease_categry_nm -- 租赁类型名称 ,case when pbl.if_group_company = 0 then '是' else '否' end if_group_company -- 是否集团客户 ,pbl.vesting_group -- 集团客户名称 ,lc.lease_method lease_method_cd -- 业务类型代码 ,case when lc.lease_method = 0 then '直租' when lc.lease_method = 1 then '回租' when lc.lease_method = 4 then '转租赁' else null end lease_method_nm -- 业务类型名称 ,main_thing.fixed_assets -- 固定资产门类 ,main_thing.fixed_assets_lag -- 固定资产门类-大类 ,main_thing.fixed_assets_mid -- 固定资产门类--中类 ,main_thing.fixed_assets_sml -- 固定资产门类--小类 ,main_thing.thing_name -- 租赁物名称 -- 主办人相关信息 ,su.user_code main_user_code -- 主办项目经理编号 ,su.user_name main_user_name -- 主办项目经理 ,su.dept_code main_dept_code -- 主办业务部门编号 ,su.dept_name main_dept_name -- 主办业务部门名称 -- 协办人相关信息 ,su2.user_code help_user_code -- 协办项目经理编号 ,su2.user_name help_user_name -- 协办项目经理 ,su2.dept_code help_dept_code -- 协办业务部门编号 ,su2.dept_name help_dept_name -- 协办业务部门名称 ,coalesce(pa.sponsor_performance, pa.sponsor_performance_sh * 100) sponsor_performance -- 主办分成比例(两位整数) ,coalesce(pa.help_performance, pa.help_performance_one * 100) help_performance -- 协办分成比例(两位整数) ,pn.investment investment_cd -- 城建类分类 ,case when coalesce(pn.investment, cu.investment) = 0 then '是' else '否' end investment_nm -- 是否城建类 ,vc.customer_name -- 承租人名称 ,case when vc.identity_type = 4 then vc.identity_no else null end identity_no -- 统一社会信用代码 ,vc.risk_level risk_level_cd -- 客户洗钱风险评级代码 ,case when vc.risk_level = '1001' then '低风险' when vc.risk_level = '1002' then '较低风险' when vc.risk_level = '1003' then '中风险' when vc.risk_level = '1004' then '较高风险' when vc.risk_level = '1005' then '高风险' when vc.risk_level = '1006' then '无结果' when vc.risk_level = '1007' then '查询失败' else null end risk_level_nm -- 客户洗钱风险评级名称 ,cu.organization_code organization_code -- 组织机构代码 ,hy.param_name industry -- 国标行业门类 ,hy1.param_name industry_lag -- 国标行业大类 ,hy2.param_name industry_mid -- 国标行业中类 ,hy3.param_name industry_sml -- 国标行业小类 ,coalesce(cc.business_module, dm1.business_mode_nm, '其他') industry_mod -- 业务板块——9大分类 ,case when cc.cont_status = 8 or (cc.cont_status = 2 and '${yyyy-mm-dd}' <= cc.lease_date_fact) or (cc.cont_status = 2 and '${yyyy-mm-dd}' >= cc.lease_date_fact and coalesce(sjtf.fact_cash_loan,0) < coalesce(ipc.lease_corpus,0) and planc.plan_count >= 2 ) then coalesce(sjtf.fact_cash_loan,0) - coalesce(gather.gather_corpus,0) - coalesce(sfk.inner_deduct_cash,0) else coalesce(ipc.lease_corpus,0) - coalesce(gather.gather_corpus,0) - coalesce(sfk.inner_deduct_cash,0) end corpus_balance -- 剩余本金 ,coalesce(history.lease_interest,ipc.lease_interest) - coalesce(gather.gather_interest,0) interest_balance -- 剩余利息 ,case when yoc.pk_contract is not null then coalesce(lpb.deposit_balance,0) else 0 end deposit_balance -- 剩余保证金 -- 调整剩余保证金逻辑, 保持和源端取值一样 11.22(剩余风险抵押金 按照逻辑把字段衍生出来) -- ,coalesce(lpb.deposit_balance,0) deposit_balance -- 剩余保证金 ,case when yoc.pk_contract is null then coalesce(lpb.deposit_balance,0) else 0 end mortgage_balance -- 剩余风险抵押金 ,COALESCE(adj.INTERRATE_FACT_AFTER,lc.FINAL_RATE, 0) contract_rate -- 合同利率 ,COALESCE(adj.PROJECT_IRR,lc.PROJECT_IRR, 0) * 100.0 PROJECT_IRR -- IRR(现行) ,COALESCE(adj.CONTRACT_XIRR,lc.CONTRACT_XIRR, 0) * 100.0 CONTRACT_XIRR -- XIRR(含税) -- 增加字段 ,case when yoc.pk_contract is null then '是' else '否' end is_mortgage -- 是否风险抵押金 ,case when cc.cont_status = 8 and coalesce(ipo.overdue_days_zqx, 0) >= 1 then '是' when cc.cont_status <> 8 and coalesce(ipo.overdue_days, 0) >= 1 then '是' else '否' end if_overdue -- 是否逾期 ,yq.OVERDUE_DATE overdue_days -- 最大逾期天数(含历史) ,magum.param_name pledge_name -- 担保方式 ,case when lc.interrate_type = 0 then '浮动利率' else '固定利率' end interrate_type -- 利率类型 ,ipc.lease_cash1 handling_fee -- 手续费/咨询费 ,ipc.lease_cash11 fixed_rent -- 固定租金 ,ipc.lease_cash2 deposit_amt -- 保证金金额 ,ipc.lease_cash22 margin_bal -- 保证金余额 ,ipc.lease_cash3 margin_off_amt -- 保证金冲抵金额 ,ipc.lease_cash33 refund_deposit -- 退还保证金 ,nn.accrue_cash -- 拨备余额 ,vc.customer_code -- 承租人编号 from dwd.dg1_yls_contract_c_c cc -- 合同表 -- 补全9大分类 left join dim.dim_d99_business_mode_cd dm1 on cc.industry3 = dm1.pk_parameter and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between dm1.stt_date and dm1.end_date -- 合同状态 left join dwd.dg1_yls_parameter_c pt1 on cc.cont_status = pt1.param_value and pt1.pk_param_type = upper('0001AA1000000001RC3C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt1.stt_date and pt1.end_date -- 合同类型 left join dwd.dg1_yls_parameter_c pt2 on cc.cont_type = pt2.param_value and pt2.pk_param_type = upper('0001AA1000000001VJBS') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt2.stt_date and pt2.end_date -- 控股类型 left join dwd.dg1_yls_parameter_c pt3 on cc.economic_style1 = pt3.pk_parameter and pt3.pk_param_type = upper('0001AA10000000041633') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt3.stt_date and pt3.end_date -- 担保方式 left join dwd.dg1_yls_parameter_c magum on cc.major_guarantee_method = magum.pk_parameter and magum.pk_param_type = upper('0001AA1000000002K3MQ') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pt3.stt_date and pt3.end_date -- 逾期情况 left join ( select ipc.pk_contract ,coalesce(max(case when ipc.trans_type = upper('0001AA100000000AUBPA') and ipc.charge_off_status = 2 and gab.check_date > '${yyyy-mm-dd}' then to_date(gab.check_date, 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') when ipc.trans_type = upper('0001AA100000000AUBPA') and ipc.charge_off_status <> 2 and ipc.plan_date <= '${yyyy-mm-dd}' then to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') end), 0) as overdue_days_zqx ,coalesce(max(case when ipc.charge_off_status = 2 and gab.check_date > '${yyyy-mm-dd}' then to_date(gab.check_date, 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') when ipc.charge_off_status <> 2 and ipc.plan_date <= '${yyyy-mm-dd}' then to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') - to_date(ipc.plan_date, 'yyyy-mm-dd') end), 0) as overdue_days /*租金逾期天数*/ from dwd.dg1_yls_inout_plan_c_c ipc left join (select gab.pk_inout_plan ,coalesce(max(gap.trade_date), '${yyyy-mm-dd}') as check_date from dwd.dg1_yls_gather_account_b_c gab inner join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date inner join dwd.dg1_yls_gather_audit_plan_c gap on gap.pk_gather_account_b = gab.pk_gather_account_b and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gap.stt_date and gap.end_date where ga.billstatus = 9 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date group by gab.pk_inout_plan) gab on gab.pk_inout_plan = ipc.pk_inout_plan where ipc.trans_type in (upper('0001AA10000000007NGV'), upper('0001AA100000000AUBPA'), upper('0001AA10000000007NH3')) /* 现金流类型 租金 收租(租前息) 首付款*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and ipc.plan_date <= '${yyyy-mm-dd}' and ipc.lease_cash >= 0.01 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) ipo on cc.pk_contract = ipo.pk_contract left join ( select plan.PK_CONTRACT,max(rec.OVERDUE_DATE) OVERDUE_DATE from dwd.dg1_yls_overdue_record_c rec join dwd.dg1_yls_inout_plan_c_c plan on plan.PK_INOUT_PLAN = rec.PK_INOUT_PLAN and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between plan.stt_date and plan.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between rec.stt_date and rec.end_date group by plan.PK_CONTRACT ) yq on yq.PK_CONTRACT = cc.PK_CONTRACT -- 实际投放金额 left join ( select ipc.pk_contract -- 主键 ,sum(coalesce(lp.real_pay_cash, 0.00)) fact_cash_loan -- 已投放金额 ,min(coalesce(ld.real_pay_date, '${yyyy-mm-dd}')) pay_date -- 首次投放日 from dwd.dg1_yls_inout_plan_c_c ipc left join dwd.dg1_yls_loan_plan_c lp on ipc.pk_inout_plan = lp.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date left join dwd.dg1_yls_loan_deal_c ld on lp.pk_loan_deal = ld.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date and ipc.trans_type in (upper('0001AA10000000005GRC'), upper('0001AA10000000007NGO'), upper('0001AA1000000005AB31'), upper('0001AA1000000005AB32')) and ipc.rent_type = 1 -- 租金表类型-会计表 and lp.if_account = 0 -- 是否核销为是 and lp.if_approve_cancel = 1 -- 是否审核撤销为否时 and lp.if_cancel = 1 -- 是否核销撤销为否时 and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' group by ipc.pk_contract ) sjtf on cc.pk_contract = sjtf.pk_contract -- 首付款 left join ( select ipc.pk_contract ,sum(coalesce(ipc.lease_cash, 0.00)) as inner_deduct_cash ,min(coalesce(ld.real_pay_date, '${yyyy-mm-dd}')) as pay_date from dwd.dg1_yls_inout_plan_c_c ipc left join dwd.dg1_yls_loan_plan_c lp on lp.pk_inout_plan = ipc.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date left join dwd.dg1_yls_loan_deal_c ld on ld.pk_loan_deal = lp.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where ipc.trans_type = '0001AA10000000007NH3' /* 现金流类型 设备款*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and lp.if_inner_deduct = 2 /* 是否内扣为是 */ and lp.if_cancel = 1 /* 是否核销撤销为否时 */ and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) sfk on cc.pk_contract = sfk.pk_contract -- 五级分类 left join ( select i1.pk_contract -- 合同PK ,i1.assets_classify -- 五级分类 ,i1.accrue_cash from dwd.dg1_assets_classify_history_c i1 -- yls_assets_classify_history join ( select ic.pk_contract ,max(ic.pk_assets_classify_history) pk_assets_classify_history from dwd.dg1_assets_classify_history_c ic where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ic.stt_date and ic.end_date and ( case when ic.if_new = 0 then ic.period else coalesce(substr(replace(ic.change_date, '-', ''), 1, 6), ic.period) end ) <= substr(replace('${yyyy-mm-dd}', '-', ''), 1, 6) group by ic.pk_contract ) i2 on i1.pk_assets_classify_history = i2.pk_assets_classify_history where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between i1.stt_date and i1.end_date ) nn on cc.pk_contract = nn.pk_contract -- 项目信息 left join dwd.dg1_yls_project_info_c pi on cc.pk_project = pi.pk_project_info and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pi.stt_date and pi.end_date -- 集团客户 left join ( select distinct source_bill, if_group_company, vesting_group from dwd.dg1_yls_project_both_lessee_c where lessee_type = 0 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between stt_date and end_date ) pbl on pi.pk_project_info = pbl.source_bill -- 主办/协办信息 left join dwd.dg1_yls_project_approval_c pa on pi.pk_project_approval = pa.pk_project_approval and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between pa.stt_date and pa.end_date -- 城建类 left join ( select row_number() over(partition by pk_project_info order by ts) rcnt ,i3.pk_project_info ,i3.investment -- 城建类判断 from dwd.dg1_yls_prj_nodecollect_c i3 where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between i3.stt_date and i3.end_date ) pn on pi.pk_project_info = pn.pk_project_info and pn.rcnt = 1 -- 用户信息相关 left join dwd.dg1_yls_customer_c vc on cc.pk_customer_lessee = vc.pk_customer and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between vc.stt_date and vc.end_date -- 企业客户基本信息 left join dwd.dg1_yls_customer_corp_c cu on vc.pk_customer = cu.pk_customer and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between cu.stt_date and cu.end_date -- 投放地区 left join dwd.dg1_bd_areacl_c ba1 on ba1.pk_areacl = cu.PROVINCE and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba1.stt_date and ba1.end_date left join dwd.dg1_bd_areacl_c ba2 on ba2.pk_areacl = cu.CITY and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba2.stt_date and ba2.end_date left join dwd.dg1_bd_areacl_c ba3 on ba3.pk_areacl = cu.DISTRICT and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ba3.stt_date and ba3.end_date -- 行业分类 left join dwd.dg1_yls_parameter_c hy on cc.industry = hy.pk_parameter and hy.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy.stt_date and hy.end_date left join dwd.dg1_yls_parameter_c hy1 on cc.industry1 = hy1.pk_parameter and hy1.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy1.stt_date and hy1.end_date left join dwd.dg1_yls_parameter_c hy2 on cc.industry2 = hy2.pk_parameter and hy2.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy2.stt_date and hy2.end_date left join dwd.dg1_yls_parameter_c hy3 on cc.industry3 = hy3.pk_parameter and hy3.pk_param_type = upper('0001AA1000000000OY5C') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between hy3.stt_date and hy3.end_date -- 剩余保证金计算 left join ( select ipc.pk_contract ,sum(case when ipc.trans_type = '0001AA10000000007NHR' then (case when lp.pay_cash > ipc.lease_cash then coalesce(ipc.lease_cash, 0.00) else coalesce(lp.pay_cash, 0.00) end) + coalesce(gac.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NHT' then -coalesce(gab.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NI5' then coalesce(gac.gather_cash, 0) when ipc.trans_type = '0001AA10000000007NHX' then -coalesce(lp.pay_cash, 0) else 0 end) as deposit_balance from dwd.dg1_yls_inout_plan_c_c ipc left join (select ipc.pk_inout_plan ,coalesce(ga.charge_off_cash, 0) as gather_cash from dwd.dg1_yls_inout_plan_c_c ipc inner join dwd.dg1_yls_gather_account_c ga on ipc.pk_inout_plan = ga.pk_account_bill and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date where ga.billstatus = 9 /*单据状态 审核通过*/ and ga.check_date <= '${yyyy-mm-dd}' and ipc.trans_type = '0001AA10000000007NHT' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date ) gab on gab.pk_inout_plan = ipc.pk_inout_plan left join (select ipc.pk_inout_plan ,coalesce(gab.gather_cash, 0) as gather_cash from dwd.dg1_yls_inout_plan_c_c ipc inner join dwd.dg1_yls_gather_account_b_c gab on ipc.pk_inout_plan = gab.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date inner join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date where ga.billstatus = 9 /*单据状态 审核通过*/ and ga.check_date <= '${yyyy-mm-dd}' and ipc.trans_type in ('0001AA10000000007NHR', '0001AA10000000007NI5') and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date ) gac on gac.pk_inout_plan = ipc.pk_inout_plan left join (select lp.pk_inout_plan ,(case when coalesce(ld.real_pay_cash, 0.00) = 0 then coalesce(ld.inner_deduct_cash, 0.00) else coalesce(ld.real_pay_cash, 0.00) end) as pay_cash from dwd.dg1_yls_loan_plan_c lp inner join dwd.dg1_yls_loan_deal_c ld on ld.pk_loan_deal = lp.pk_loan_deal and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ld.stt_date and ld.end_date where lp.if_approve_cancel = 1 /* 是否审核撤销为否时 */ and lp.if_cancel = 1 /* 是否核销撤销为否时 */ and ld.billstatus = 9 and ld.real_pay_date <= '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lp.stt_date and lp.end_date ) lp on lp.pk_inout_plan = ipc.pk_inout_plan where ipc.trans_type in ('0001AA10000000007NHR', '0001AA10000000007NHT', '0001AA10000000007NI5', '0001AA10000000007NHX') /* 现金流类型 收取保证金,保证金冲抵,补足保证金,退还保证金*/ and ipc.rent_type = 1 /* 租金表类型 会计表*/ and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.pk_contract ) lpb on cc.pk_contract = lpb.pk_contract left join dwd.dg1_yls_old_contract_c yoc on cc.pk_contract = yoc.pk_contract and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between yoc.stt_date and yoc.end_date -- 实收数据 left join ( select sum(case when et.event_code in ('10201', '10203', '10216') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_cash, 0) else 0 end) gather_cash ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_corpus, 0) else 0 end) gather_corpus ,sum(case when et.event_code in ('10201', '10216') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_interest, 0) else 0 end) gather_interest ,sum(case when et.event_code in ('10213') and gab.trade_date <= '${yyyy-mm-dd}' then coalesce(gab.gather_cash, 0) else 0 end) gather_penal_cash ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_cash, 0) else 0 end) gather_cash1 ,sum(case when et.event_code in ('10201', '10203') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_corpus, 0) else 0 end) gather_corpus1 ,sum(case when et.event_code in ('10201', '10203', '10216') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_interest, 0) else 0 end) gather_interest1 ,sum(case when et.event_code in ('10213') and gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then coalesce(gab.gather_cash, 0) else 0 end) gather_penal_cash1 ,sum(case when gab.trade_date >= concat(substr('${yyyy-mm-dd}', 1, 4), '-01-01') and gab.trade_date <= concat(substr('${yyyy-mm-dd}', 1, 4), '-12-31') then 1 else 0 end) cur_year_time ,sum(case when gab.trade_date >= '${yyyy-mm-dd}' and gab.trade_date <= to_char(add_months(date'${yyyy-mm-dd}', 12), 'yyyy-mm-dd') then 1 else 0 end) future_time ,ipc.pk_contract from dwd.dg1_yls_gather_account_b_c gab join dwd.dg1_yls_gather_account_c ga on ga.pk_gather_account = gab.pk_gather_account and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ga.stt_date and ga.end_date join dwd.dg1_yls_inout_plan_c_c ipc on ipc.pk_inout_plan = gab.pk_inout_plan and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date join dwd.dg1_yls_event_type_c et on et.pk_event_type = ipc.trans_type and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date where ga.billstatus = 9 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between gab.stt_date and gab.end_date group by ipc.pk_contract ) gather on cc.pk_contract = gather.pk_contract left join dwd.dg1_yls_lease_calculator_c_c lc on cc.pk_lease_calculator = lc.pk_lease_calculator and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between lc.stt_date and lc.end_date -- 实时数据 left join ( select sum(case when et.event_code in ('10201','10202','10203','10216') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash, /* 总租金 */ sum(case when et.event_code in ('10401'/*,'10402','10403'*/,'10606') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash1,/* 手续费/咨询费 */ sum(case when et.event_code in ('10405') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash11,/* 固定租金 */ sum(case when et.event_code in ('10301') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash2, /* 保证金收取 */ sum(case when et.event_code in ('10308') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash22, /* 补住保证金 */ sum(case when et.event_code in ('10302') then coalesce(ipc.fact_cash,0) else 0 end) lease_cash3, /* 保证金冲抵 */ sum(case when et.event_code in ('10304') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash33, /* 退还保证金 */ sum(case when et.event_code in ('10201','10203') then coalesce(ipc.lease_cash,0) else 0 end) lease_cash4, /* 收取总租金 */ sum(case when et.event_code in ('10201','10202','10216') then coalesce(ipc.lease_interest,0) else 0 end) lease_interest, /* 收取总利息 */ sum(case when et.event_code in ('10101','10102') and ycc.cont_status = 8 then coalesce(ipc.fact_cash,0) when et.event_code in ('10201','10203') and ycc.cont_status != 8 then coalesce(ipc.lease_corpus,0) else 0 end) lease_corpus, /* 总本金 */ sum(case when et.event_code in ('10301','10308') then coalesce(ipc.fact_cash,0) else 0 end) fact_cash2, /* 实收:保证金收取、补足 */ sum(case when et.event_code in ('10302','10304') then coalesce(ipc.fact_cash,0) else 0 end) fact_cash3, /* 实际:保证金冲抵、退还保证金 */ ipc.source_bill from dwd.dg1_yls_inout_plan_c_c ipc join dwd.dg1_yls_event_type_c et on et.pk_event_type = ipc.trans_type and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date join dwd.dg1_yls_contract_c_c ycc on ycc.pk_contract = ipc.pk_contract and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ycc.stt_date and ycc.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ipc.stt_date and ipc.end_date group by ipc.source_bill ) ipc on lc.pk_lease_calculator = ipc.source_bill -- 历史数据 left join ( select ch.CONT_CODE,rc.interrate,rc.new_final_rate ,rc.NEW_PROJECT_IRR,rc.NEW_CONTRACT_XIRR,h.lease_cash,h.lease_cash1,h.lease_cash2, h.lease_cash3,lease_cash22,h.lease_cash33,h.LEASE_INTEREST, h.fact_cash2,h.fact_cash3 from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.PK_CONTRACT = ch.PK_CONTRACT and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between rc.stt_date and rc.end_date join ( select iph.SOURCE_BILL, sum(case when et.EVENT_CODE in ('10201','10202','10203','10216') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash, /* 收租总租金 */ sum(case when et.EVENT_CODE in ('10401'/*,'10402','10403'*/,'10405','10606') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash1, /* 手续费/咨询费/固定租金 */ sum(case when et.EVENT_CODE in ('10201','10202','10216') then coalesce(iph.LEASE_INTEREST,0) else 0 end) LEASE_INTEREST, /* 收租总租息 */ sum(case when et.EVENT_CODE in ('10301') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash2, /* 保证金收取 */ sum(case when et.EVENT_CODE in ('10308') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash22, /* 保证金补住 */ sum(case when et.EVENT_CODE in ('10302') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash3, /* 保证金冲抵*/ sum(case when et.EVENT_CODE in ('10304') then coalesce(iph.LEASE_CASH,0) else 0 end) lease_cash33, /* 保证金退还 */ sum(case when et.EVENT_CODE in ('10301','10308') then coalesce(iph.FACT_CASH,0) else 0 end) fact_cash2, /* 实收:保证金收取、补足 */ sum(case when et.EVENT_CODE in ('10302','10304') then coalesce(iph.FACT_CASH,0) else 0 end) fact_cash3 /* 实际:保证金冲抵、退还保证金 */ from dwd.dg1_yls_inout_plan_h_c iph join dwd.dg1_yls_event_type_c et on et.PK_EVENT_TYPE = iph.TRANS_TYPE and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between et.stt_date and et.end_date where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between iph.stt_date and iph.end_date group by iph.SOURCE_BILL ) h on h.SOURCE_BILL = rc.PK_RENT_CALCULATOR where ch.SOURCE_BILL_VERSIONPK in ( select chh.PK_CONTRACT from dwd.dg1_yls_contract_h_c chh join ( select max(CHECK_DATE)CHECK_DATE,ch.cont_code from dwd.dg1_yls_contract_h_c ch where upper(ch.SOURCE_BILLTYPE) = upper('lease/ContractChange') and ch.SOURCE_BILL_VERSIONPK is null and ch.CHECK_DATE > '${yyyy-mm-dd}' and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ch.stt_date and ch.end_date group by ch.CONT_CODE )zj_change on zj_change.CHECK_DATE = chh.check_date and zj_change.cont_code = chh.cont_code and upper(chh.SOURCE_BILLTYPE) = upper('lease/ContractChange') and chh.SOURCE_BILL_VERSIONPK is null where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between chh.stt_date and chh.end_date ) and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ch.stt_date and ch.end_date ) history on history.cont_code = cc.cont_code -- 计划投放数量 left join ( select i5.pk_contract ,count(*) plan_count from dwd.dg1_yls_inout_plan_c_c i5 where i5.trans_type in ('0001AA10000000005GRC','0001AA10000000007NGO','0001AA1000000005AB31', '0001AA1000000005AB32') and i5.rent_type = 1 group by i5.pk_contract ) planc on cc.pk_contract = planc.pk_contract -- 租赁物信息 left join ( select ypfa1.param_name fixed_assets ,ypfa2.param_name fixed_assets_lag ,ypfa3.param_name fixed_assets_mid ,ypfa4.param_name fixed_assets_sml ,prtc.thing_name ,prtc.source_bill from dwd.dg1_yls_project_rent_thing_c_c prtc left join dwd.dg1_yls_parameter_c ypfa1 on ypfa1.pk_parameter = prtc.fixed_assets and ypfa1.is_enable = upper('Y') and ypfa1.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa1.stt_date and ypfa1.end_date left join dwd.dg1_yls_parameter_c ypfa2 on ypfa2.pk_parameter = prtc.fixed_assets_large and ypfa2.is_enable = upper('Y') and ypfa2.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa2.stt_date and ypfa2.end_date left join dwd.dg1_yls_parameter_c ypfa3 on ypfa3.pk_parameter = prtc.fixed_assets_middle and ypfa3.is_enable = upper('Y') and ypfa3.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa3.stt_date and ypfa3.end_date left join dwd.dg1_yls_parameter_c ypfa4 on ypfa4.pk_parameter = prtc.fixed_assets_small and ypfa4.is_enable = upper('Y') and ypfa4.param_type = 293 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between ypfa4.stt_date and ypfa4.end_date where prtc.is_ref_main = 0 and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between prtc.stt_date and prtc.end_date ) main_thing on cc.pk_contract = main_thing.source_bill -- 主办 left join dwd.dwd_d01_party_c su on cc.pk_prj_manager = su.cuserid and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between su.stt_date and su.end_date -- 协办 left join dwd.dwd_d01_party_c su2 on cc.pk_cust_help = su2.cuserid and to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between su2.stt_date and su2.end_date left join ( select adj3.cont_code, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.interrate_after end) as interrate_after, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.interrate_fact_after end) as interrate_fact_after, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.project_irr end) as project_irr, max(case when (adj3.response_day <= '${yyyy-mm-dd}' and '${yyyy-mm-dd}' < adj3.response_day_end) or '${yyyy-mm-dd}' <= adj3.response_day then adj3.contract_xirr end) as contract_xirr from( select adj.cont_code, adj.response_day, coalesce(min(case when adj.response_day < adj2.response_day then adj2.response_day end),'${yyyy-mm-dd}') response_day_end, min(adj.interrate_after) interrate_after, -- /*调息后基准利率*/ min(adj.interrate_fact_after) interrate_fact_after, -- /*调息后实际利率*/ min(adj.project_irr) project_irr, -- /*调息后合同irr*/ min(adj.contract_xirr) contract_xirr -- /*合同收益xirr*/ from (select ch.cont_code, ch.check_date as response_day, rc.interrate as interrate_after, rc.new_final_rate as interrate_fact_after, rc.new_project_irr as project_irr, rc.new_contract_xirr as contract_xirr from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.pk_contract = ch.pk_contract where upper(ch.source_billtype) = upper('lease/contractchange') and ch.source_bill_versionpk is null and ch.billstatus = 9 and date'${yyyy-mm-dd}' between ch.stt_date and ch.end_date and date'${yyyy-mm-dd}' between rc.stt_date and rc.end_date union all -- /*实际调息*/ select distinct cc.cont_code,aa.response_day, aa.interrate_after, -- /*调息后基准利率*/ aa.interrate_fact_after, -- /*调息后实际利率*/ aa.project_irr, -- /*调息后合同irr*/ aa.contract_xirr -- /*合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date where aa.billstatus = 9 and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date union all -- /*首次调息时,调息前信息*/ select distinct cc.cont_code,to_char(to_date(aa.response_day, 'yyyy-mm-dd') - 1, 'yyyy-mm-dd') as response_day, aa.interrate_before as interrate_after, -- /*调息前基准利率*/ aa.interrate_fact_before as interrate_fact_after, -- /*调息前实际利率*/ aa.cont_irr_befor as project_irr, -- /*调息前合同irr*/ aa.contract_xirr_before as contract_xirr -- /*调息前合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa join (select min(a.response_day) as response_day,a.pk_contract from dwd.dg1_yls_adjust_apply_c a where a.billstatus = 9 and date'${yyyy-mm-dd}' between a.stt_date and a.end_date group by a.pk_contract) minday on minday.pk_contract = aa.pk_contract and minday.response_day = aa.response_day and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date) adj left join ( select ch.cont_code, ch.check_date as response_day, rc.interrate as interrate_after, rc.new_final_rate as interrate_fact_after, rc.new_project_irr as project_irr, rc.new_contract_xirr as contract_xirr from dwd.dg1_yls_contract_h_c ch join dwd.dg1_yls_rent_calculator_c rc on rc.pk_contract = ch.pk_contract where upper(ch.source_billtype) = upper('lease/contractchange') and ch.source_bill_versionpk is null and ch.billstatus = 9 and date'${yyyy-mm-dd}' between ch.stt_date and ch.end_date and date'${yyyy-mm-dd}' between rc.stt_date and rc.end_date union all select distinct cc.cont_code,aa.response_day, aa.interrate_after, -- /*调息后基准利率*/ aa.interrate_fact_after, -- /*调息后实际利率*/ aa.project_irr, -- /*调息后合同irr*/ aa.contract_xirr -- /*合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract where aa.billstatus = 9 and date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date union all select distinct cc.cont_code,to_char(to_date(aa.response_day, 'yyyy-mm-dd') - 1, 'yyyy-mm-dd') as response_day, aa.interrate_before as interrate_after, -- /*调息前基准利率*/ aa.interrate_fact_before as interrate_fact_after, -- /*调息前实际利率*/ aa.cont_irr_befor as project_irr, -- /*调息前合同irr*/ aa.contract_xirr_before as contract_xirr -- /*调息前合同收益xirr*/ from dwd.dg1_yls_adjust_apply_c aa join (select min(a.response_day) as response_day,a.pk_contract from dwd.dg1_yls_adjust_apply_c a where a.billstatus = 9 and date'${yyyy-mm-dd}' between a.stt_date and a.end_date group by a.pk_contract) minday on minday.pk_contract = aa.pk_contract and minday.response_day = aa.response_day left join dwd.dg1_yls_contract_c_c cc on cc.pk_contract = aa.pk_contract and date'${yyyy-mm-dd}' between cc.stt_date and cc.end_date where date'${yyyy-mm-dd}' between aa.stt_date and aa.end_date ) adj2 on adj2.cont_code = adj.cont_code group by adj.cont_code,adj.response_day ) adj3 group by adj3.cont_code ) adj on adj.cont_code = cc.cont_code where to_date('${yyyy-mm-dd}', 'yyyy-mm-dd') between cc.stt_date and cc.end_date -- PK_PARAM_TYPE = '0001AA1000000001RC3C' 合同状态 and cc.cont_status > '1' and cc.cont_status not in ('5' ,'7') ================================================ FILE: superior-oracle-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-postgres-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-postgres-parser superior-postgres-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-postgres-parser/src/main/antlr4/io/github/melin/superior/parser/postgre/antlr4/PostgreSqlLexer.g4 ================================================ /* based on https://github.com/tunnelvisionlabs/antlr4-grammar-postgresql/blob/master/src/com/tunnelvisionlabs/postgresql/PostgreSqlLexer.g4 */ /* * [The "MIT license"] * Copyright (C) 2014 Sam Harwell, Tunnel Vision Laboratories, LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * 1. The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * 2. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * 3. Except as contained in this notice, the name of Tunnel Vision * Laboratories, LLC. shall not be used in advertising or otherwise to * promote the sale, use or other dealings in this Software without prior * written authorization from Tunnel Vision Laboratories, LLC. */ lexer grammar PostgreSqlLexer; /* Reference: * http://www.postgresql.org/docs/9.3/static/sql-syntax-lexical.html */ options { superClass = PostgreSqlLexerBase; } @ header { } @ members { /* This field stores the tags which are used to detect the end of a dollar-quoted string literal. */ } // // SPECIAL CHARACTERS (4.1.4) // // Note that Asterisk is a valid operator, but does not have the type Operator due to its syntactic use in locations // that are not expressions. Dollar : '$' ; OPEN_PAREN : '(' ; CLOSE_PAREN : ')' ; OPEN_BRACKET : '[' ; CLOSE_BRACKET : ']' ; COMMA : ',' ; SEMI : ';' ; COLON : ':' ; STAR : '*' ; EQUAL : '=' ; DOT : '.' ; //NamedArgument : ':='; PLUS : '+' ; MINUS : '-' ; SLASH : '/' ; CARET : '^' ; LT : '<' ; GT : '>' ; LESS_LESS : '<<' ; GREATER_GREATER : '>>' ; COLON_EQUALS : ':=' ; LESS_EQUALS : '<=' ; EQUALS_GREATER : '=>' ; GREATER_EQUALS : '>=' ; DOT_DOT : '..' ; NOT_EQUALS : '<>' ; TYPECAST : '::' ; PERCENT : '%' ; PARAM : '$' ([0-9])+ ; // // OPERATORS (4.1.3) // // this rule does not allow + or - at the end of a multi-character operator Operator : ((OperatorCharacter | ('+' | '-' {checkLA('-')}?)+ (OperatorCharacter | '/' {checkLA('*')}?) | '/' {checkLA('*')}?)+ | // special handling for the single-character operators + and - [+-]) //TODO somehow rewrite this part without using Actions { HandleLessLessGreaterGreater(); } ; /* This rule handles operators which end with + or -, and sets the token type to Operator. It is comprised of four * parts, in order: * * 1. A prefix, which does not contain a character from the required set which allows + or - to appear at the end of * the operator. * 2. A character from the required set which allows + or - to appear at the end of the operator. * 3. An optional sub-token which takes the form of an operator which does not include a + or - at the end of the * sub-token. * 4. A suffix sequence of + and - characters. */ OperatorEndingWithPlusMinus : (OperatorCharacterNotAllowPlusMinusAtEnd | '-' {checkLA('-')}? | '/' {checkLA('*')}?)* OperatorCharacterAllowPlusMinusAtEnd Operator? ('+' | '-' {checkLA('-')}?)+ -> type (Operator) ; // Each of the following fragment rules omits the +, -, and / characters, which must always be handled in a special way // by the operator rules above. fragment OperatorCharacter : [*<>=~!@%^&|`?#] ; // these are the operator characters that don't count towards one ending with + or - fragment OperatorCharacterNotAllowPlusMinusAtEnd : [*<>=+] ; // an operator may end with + or - if it contains one of these characters fragment OperatorCharacterAllowPlusMinusAtEnd : [~!@%^&|`?#] ; // // KEYWORDS (Appendix C) // // // reserved keywords // ALL : 'ALL' ; ANALYSE : 'ANALYSE' ; ANALYZE : 'ANALYZE' ; AND : 'AND' ; ANY : 'ANY' ; ARRAY : 'ARRAY' ; AS : 'AS' ; ASC : 'ASC' ; ASYMMETRIC : 'ASYMMETRIC' ; BOTH : 'BOTH' ; CASE : 'CASE' ; CAST : 'CAST' ; CHECK : 'CHECK' ; COLLATE : 'COLLATE' ; COLUMN : 'COLUMN' ; CONSTRAINT : 'CONSTRAINT' ; CREATE : 'CREATE' ; CURRENT_CATALOG : 'CURRENT_CATALOG' ; CURRENT_DATE : 'CURRENT_DATE' ; CURRENT_ROLE : 'CURRENT_ROLE' ; CURRENT_TIME : 'CURRENT_TIME' ; CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP' ; CURRENT_USER : 'CURRENT_USER' ; DEFAULT : 'DEFAULT' ; DEFERRABLE : 'DEFERRABLE' ; DESC : 'DESC' ; DISTINCT : 'DISTINCT' ; DO : 'DO' ; ELSE : 'ELSE' ; EXCEPT : 'EXCEPT' ; FALSE_P : 'FALSE' ; FETCH : 'FETCH' ; FOR : 'FOR' ; FOREIGN : 'FOREIGN' ; FROM : 'FROM' ; GRANT : 'GRANT' ; GROUP_P : 'GROUP' ; HAVING : 'HAVING' ; IN_P : 'IN' ; INITIALLY : 'INITIALLY' ; INTERSECT : 'INTERSECT' ; INTO : 'INTO' ; LATERAL_P : 'LATERAL' ; LEADING : 'LEADING' ; LIMIT : 'LIMIT' ; LOCALTIME : 'LOCALTIME' ; LOCALTIMESTAMP : 'LOCALTIMESTAMP' ; NOT : 'NOT' ; NULL_P : 'NULL' ; OFFSET : 'OFFSET' ; ON : 'ON' ; ONLY : 'ONLY' ; OR : 'OR' ; ORDER : 'ORDER' ; PLACING : 'PLACING' ; PRIMARY : 'PRIMARY' ; REFERENCES : 'REFERENCES' ; RETURNING : 'RETURNING' ; SELECT : 'SELECT' ; SESSION_USER : 'SESSION_USER' ; SOME : 'SOME' ; SYMMETRIC : 'SYMMETRIC' ; TABLE : 'TABLE' ; THEN : 'THEN' ; TO : 'TO' ; TRAILING : 'TRAILING' ; TRUE_P : 'TRUE' ; UNION : 'UNION' ; UNIQUE : 'UNIQUE' ; USER : 'USER' ; USING : 'USING' ; VARIADIC : 'VARIADIC' ; WHEN : 'WHEN' ; WHERE : 'WHERE' ; WINDOW : 'WINDOW' ; WITH : 'WITH' ; // // reserved keywords (can be function or type) // AUTHORIZATION : 'AUTHORIZATION' ; BINARY : 'BINARY' ; COLLATION : 'COLLATION' ; CONCURRENTLY : 'CONCURRENTLY' ; CROSS : 'CROSS' ; CURRENT_SCHEMA : 'CURRENT_SCHEMA' ; FREEZE : 'FREEZE' ; FULL : 'FULL' ; ILIKE : 'ILIKE' ; INNER_P : 'INNER' ; IS : 'IS' ; ISNULL : 'ISNULL' ; JOIN : 'JOIN' ; LEFT : 'LEFT' ; LIKE : 'LIKE' ; NATURAL : 'NATURAL' ; NOTNULL : 'NOTNULL' ; OUTER_P : 'OUTER' ; OVER : 'OVER' ; OVERLAPS : 'OVERLAPS' ; RIGHT : 'RIGHT' ; SIMILAR : 'SIMILAR' ; VERBOSE : 'VERBOSE' ; // // non-reserved keywords // ABORT_P : 'ABORT' ; ABSOLUTE_P : 'ABSOLUTE' ; ACCESS : 'ACCESS' ; ACTION : 'ACTION' ; ADD_P : 'ADD' ; ADMIN : 'ADMIN' ; AFTER : 'AFTER' ; AGGREGATE : 'AGGREGATE' ; ALSO : 'ALSO' ; ALTER : 'ALTER' ; ALWAYS : 'ALWAYS' ; ASSERTION : 'ASSERTION' ; ASSIGNMENT : 'ASSIGNMENT' ; AT : 'AT' ; ATTRIBUTE : 'ATTRIBUTE' ; BACKWARD : 'BACKWARD' ; BEFORE : 'BEFORE' ; BEGIN_P : 'BEGIN' ; BY : 'BY' ; CACHE : 'CACHE' ; CALLED : 'CALLED' ; CASCADE : 'CASCADE' ; CASCADED : 'CASCADED' ; CATALOG : 'CATALOG' ; CHAIN : 'CHAIN' ; CHARACTERISTICS : 'CHARACTERISTICS' ; CHECKPOINT : 'CHECKPOINT' ; CLASS : 'CLASS' ; CLOSE : 'CLOSE' ; CLUSTER : 'CLUSTER' ; COMMENT : 'COMMENT' ; COMMENTS : 'COMMENTS' ; COMMIT : 'COMMIT' ; COMMITTED : 'COMMITTED' ; CONFIGURATION : 'CONFIGURATION' ; CONNECTION : 'CONNECTION' ; CONSTRAINTS : 'CONSTRAINTS' ; CONTENT_P : 'CONTENT' ; CONTINUE_P : 'CONTINUE' ; CONVERSION_P : 'CONVERSION' ; COPY : 'COPY' ; COST : 'COST' ; CSV : 'CSV' ; CURSOR : 'CURSOR' ; CYCLE : 'CYCLE' ; DATA_P : 'DATA' ; DATABASE : 'DATABASE' ; DAY_P : 'DAY' ; DEALLOCATE : 'DEALLOCATE' ; DECLARE : 'DECLARE' ; DEFAULTS : 'DEFAULTS' ; DEFERRED : 'DEFERRED' ; DEFINER : 'DEFINER' ; DELETE_P : 'DELETE' ; DELIMITER : 'DELIMITER' ; DELIMITERS : 'DELIMITERS' ; DICTIONARY : 'DICTIONARY' ; DISABLE_P : 'DISABLE' ; DISCARD : 'DISCARD' ; DOCUMENT_P : 'DOCUMENT' ; DOMAIN_P : 'DOMAIN' ; DOUBLE_P : 'DOUBLE' ; DROP : 'DROP' ; EACH : 'EACH' ; ENABLE_P : 'ENABLE' ; ENCODING : 'ENCODING' ; ENCRYPTED : 'ENCRYPTED' ; ENUM_P : 'ENUM' ; ESCAPE : 'ESCAPE' ; EVENT : 'EVENT' ; EXCLUDE : 'EXCLUDE' ; EXCLUDING : 'EXCLUDING' ; EXCLUSIVE : 'EXCLUSIVE' ; EXECUTE : 'EXECUTE' ; EXPLAIN : 'EXPLAIN' ; EXTENSION : 'EXTENSION' ; EXTERNAL : 'EXTERNAL' ; FAMILY : 'FAMILY' ; FIRST_P : 'FIRST' ; FOLLOWING : 'FOLLOWING' ; FORCE : 'FORCE' ; FORWARD : 'FORWARD' ; FUNCTION : 'FUNCTION' ; FUNCTIONS : 'FUNCTIONS' ; GLOBAL : 'GLOBAL' ; GRANTED : 'GRANTED' ; HANDLER : 'HANDLER' ; HEADER_P : 'HEADER' ; HOLD : 'HOLD' ; HOUR_P : 'HOUR' ; IDENTITY_P : 'IDENTITY' ; IF_P : 'IF' ; IMMEDIATE : 'IMMEDIATE' ; IMMUTABLE : 'IMMUTABLE' ; IMPLICIT_P : 'IMPLICIT' ; INCLUDING : 'INCLUDING' ; INCREMENT : 'INCREMENT' ; INDEX : 'INDEX' ; INDEXES : 'INDEXES' ; INHERIT : 'INHERIT' ; INHERITS : 'INHERITS' ; INLINE_P : 'INLINE' ; INSENSITIVE : 'INSENSITIVE' ; INSERT : 'INSERT' ; INSTEAD : 'INSTEAD' ; INVOKER : 'INVOKER' ; ISOLATION : 'ISOLATION' ; KEY : 'KEY' ; LABEL : 'LABEL' ; LANGUAGE : 'LANGUAGE' ; LARGE_P : 'LARGE' ; LAST_P : 'LAST' ; //LC_COLLATE : 'LC'_'COLLATE; //LC_CTYPE : 'LC'_'CTYPE; LEAKPROOF : 'LEAKPROOF' ; SHIPPABLE : 'SHIPPABLE' ; FENCED : 'FENCED' ; PACKAGE : 'PACKAGE' ; LEVEL : 'LEVEL' ; LISTEN : 'LISTEN' ; LOAD : 'LOAD' ; LOCAL : 'LOCAL' ; LOCATION : 'LOCATION' ; LOCK_P : 'LOCK' ; MAPPING : 'MAPPING' ; MATCH : 'MATCH' ; MATCHED : 'MATCHED' ; MATERIALIZED : 'MATERIALIZED' ; MAXVALUE : 'MAXVALUE' ; MERGE : 'MERGE' ; MINUTE_P : 'MINUTE' ; MINVALUE : 'MINVALUE' ; MODE : 'MODE' ; MONTH_P : 'MONTH' ; MOVE : 'MOVE' ; NAME_P : 'NAME' ; NAMES : 'NAMES' ; NEXT : 'NEXT' ; NO : 'NO' ; NOTHING : 'NOTHING' ; NOTIFY : 'NOTIFY' ; NOWAIT : 'NOWAIT' ; NULLS_P : 'NULLS' ; OBJECT_P : 'OBJECT' ; OF : 'OF' ; OFF : 'OFF' ; OIDS : 'OIDS' ; OPERATOR : 'OPERATOR' ; OPTION : 'OPTION' ; OPTIONS : 'OPTIONS' ; OWNED : 'OWNED' ; OWNER : 'OWNER' ; PARSER : 'PARSER' ; PARTIAL : 'PARTIAL' ; PARTITION : 'PARTITION' ; PASSING : 'PASSING' ; PASSWORD : 'PASSWORD' ; PLANS : 'PLANS' ; PRECEDING : 'PRECEDING' ; PREPARE : 'PREPARE' ; PREPARED : 'PREPARED' ; PRESERVE : 'PRESERVE' ; PRIOR : 'PRIOR' ; PRIVILEGES : 'PRIVILEGES' ; PROCEDURAL : 'PROCEDURAL' ; PROCEDURE : 'PROCEDURE' ; PROGRAM : 'PROGRAM' ; QUOTE : 'QUOTE' ; RANGE : 'RANGE' ; READ : 'READ' ; REASSIGN : 'REASSIGN' ; RECHECK : 'RECHECK' ; RECURSIVE : 'RECURSIVE' ; REF : 'REF' ; REFRESH : 'REFRESH' ; REINDEX : 'REINDEX' ; RELATIVE_P : 'RELATIVE' ; RELEASE : 'RELEASE' ; RENAME : 'RENAME' ; REPEATABLE : 'REPEATABLE' ; REPLACE : 'REPLACE' ; REPLICA : 'REPLICA' ; RESET : 'RESET' ; RESTART : 'RESTART' ; RESTRICT : 'RESTRICT' ; RETURNS : 'RETURNS' ; REVOKE : 'REVOKE' ; ROLE : 'ROLE' ; ROLLBACK : 'ROLLBACK' ; ROWS : 'ROWS' ; RULE : 'RULE' ; SAVEPOINT : 'SAVEPOINT' ; SCHEMA : 'SCHEMA' ; SCROLL : 'SCROLL' ; SEARCH : 'SEARCH' ; SECOND_P : 'SECOND' ; SECURITY : 'SECURITY' ; SEQUENCE : 'SEQUENCE' ; SEQUENCES : 'SEQUENCES' ; SERIALIZABLE : 'SERIALIZABLE' ; SERVER : 'SERVER' ; SESSION : 'SESSION' ; SET : 'SET' ; SHARE : 'SHARE' ; SHOW : 'SHOW' ; SIMPLE : 'SIMPLE' ; SNAPSHOT : 'SNAPSHOT' ; STABLE : 'STABLE' ; STANDALONE_P : 'STANDALONE' ; START : 'START' ; STATEMENT : 'STATEMENT' ; STATISTICS : 'STATISTICS' ; STDIN : 'STDIN' ; STDOUT : 'STDOUT' ; STORAGE : 'STORAGE' ; STRICT_P : 'STRICT' ; STRIP_P : 'STRIP' ; SYSID : 'SYSID' ; SYSTEM_P : 'SYSTEM' ; TABLES : 'TABLES' ; TABLESPACE : 'TABLESPACE' ; TEMP : 'TEMP' ; TEMPLATE : 'TEMPLATE' ; TEMPORARY : 'TEMPORARY' ; TEXT_P : 'TEXT' ; TRANSACTION : 'TRANSACTION' ; TRIGGER : 'TRIGGER' ; TRUNCATE : 'TRUNCATE' ; TRUSTED : 'TRUSTED' ; TYPE_P : 'TYPE' ; TYPES_P : 'TYPES' ; UNBOUNDED : 'UNBOUNDED' ; UNCOMMITTED : 'UNCOMMITTED' ; UNENCRYPTED : 'UNENCRYPTED' ; UNKNOWN : 'UNKNOWN' ; UNLISTEN : 'UNLISTEN' ; UNLOGGED : 'UNLOGGED' ; UNTIL : 'UNTIL' ; UPDATE : 'UPDATE' ; VACUUM : 'VACUUM' ; VALID : 'VALID' ; VALIDATE : 'VALIDATE' ; VALIDATOR : 'VALIDATOR' ; //VALUE : 'VALUE; VARYING : 'VARYING' ; VERSION_P : 'VERSION' ; VIEW : 'VIEW' ; VOLATILE : 'VOLATILE' ; WHITESPACE_P : 'WHITESPACE' ; WITHOUT : 'WITHOUT' ; WORK : 'WORK' ; WRAPPER : 'WRAPPER' ; WRITE : 'WRITE' ; XML_P : 'XML' ; YEAR_P : 'YEAR' ; YES_P : 'YES' ; ZONE : 'ZONE' ; // // non-reserved keywords (can not be function or type) // BETWEEN : 'BETWEEN' ; BIGINT : 'BIGINT' ; BIT : 'BIT' ; BOOLEAN_P : 'BOOLEAN' ; CHAR_P : 'CHAR' ; CHARACTER : 'CHARACTER' ; COALESCE : 'COALESCE' ; DEC : 'DEC' ; DECIMAL_P : 'DECIMAL' ; EXISTS : 'EXISTS' ; EXTRACT : 'EXTRACT' ; FLOAT_P : 'FLOAT' ; GREATEST : 'GREATEST' ; INOUT : 'INOUT' ; INT_P : 'INT' ; INTEGER : 'INTEGER' ; INTERVAL : 'INTERVAL' ; LEAST : 'LEAST' ; NATIONAL : 'NATIONAL' ; NCHAR : 'NCHAR' ; NONE : 'NONE' ; NULLIF : 'NULLIF' ; NUMERIC : 'NUMERIC' ; OVERLAY : 'OVERLAY' ; POSITION : 'POSITION' ; PRECISION : 'PRECISION' ; REAL : 'REAL' ; ROW : 'ROW' ; SETOF : 'SETOF' ; SMALLINT : 'SMALLINT' ; SUBSTRING : 'SUBSTRING' ; TIME : 'TIME' ; TIMESTAMP : 'TIMESTAMP' ; TREAT : 'TREAT' ; TRIM : 'TRIM' ; VALUES : 'VALUES' ; VARCHAR : 'VARCHAR' ; XMLATTRIBUTES : 'XMLATTRIBUTES' ; XMLCOMMENT : 'XMLCOMMENT' ; XMLAGG : 'XMLAGG' ; XML_IS_WELL_FORMED : 'XML_IS_WELL_FORMED' ; XML_IS_WELL_FORMED_DOCUMENT : 'XML_IS_WELL_FORMED_DOCUMENT' ; XML_IS_WELL_FORMED_CONTENT : 'XML_IS_WELL_FORMED_CONTENT' ; XPATH : 'XPATH' ; XPATH_EXISTS : 'XPATH_EXISTS' ; XMLCONCAT : 'XMLCONCAT' ; XMLELEMENT : 'XMLELEMENT' ; XMLEXISTS : 'XMLEXISTS' ; XMLFOREST : 'XMLFOREST' ; XMLPARSE : 'XMLPARSE' ; XMLPI : 'XMLPI' ; XMLROOT : 'XMLROOT' ; XMLSERIALIZE : 'XMLSERIALIZE' ; //MISSED CALL : 'CALL' ; CURRENT_P : 'CURRENT' ; ATTACH : 'ATTACH' ; DETACH : 'DETACH' ; EXPRESSION : 'EXPRESSION' ; GENERATED : 'GENERATED' ; LOGGED : 'LOGGED' ; STORED : 'STORED' ; INCLUDE : 'INCLUDE' ; ROUTINE : 'ROUTINE' ; TRANSFORM : 'TRANSFORM' ; IMPORT_P : 'IMPORT' ; POLICY : 'POLICY' ; METHOD : 'METHOD' ; REFERENCING : 'REFERENCING' ; NEW : 'NEW' ; OLD : 'OLD' ; VALUE_P : 'VALUE' ; SUBSCRIPTION : 'SUBSCRIPTION' ; PUBLICATION : 'PUBLICATION' ; OUT_P : 'OUT' ; END_P : 'END' ; ROUTINES : 'ROUTINES' ; SCHEMAS : 'SCHEMAS' ; PROCEDURES : 'PROCEDURES' ; INPUT_P : 'INPUT' ; SUPPORT : 'SUPPORT' ; PARALLEL : 'PARALLEL' ; SQL_P : 'SQL' ; DEPENDS : 'DEPENDS' ; OVERRIDING : 'OVERRIDING' ; // support gauss start-------------------------------- AUTOMAPPED : 'AUTOMAPPED' ; SAMPLE : 'SAMPLE' ; PERCENT_P : 'PERCENT' ; STAT : 'STAT' ; COLLECT : 'COLLECT' ; MULTISET : 'MULTISET' ; MINUS_P : 'MINUS' ; GROUPCONCAT : 'GROUP_CONCAT' ; SEPARATOR : 'SEPARATOR' ; IGNORE : 'IGNORE' ; OPEN_BRACE : '{' ; CLOSE_BRACE : '}' ; OVERWRITE : 'OVERWRITE' ; DISTRIBUTE : 'DISTRIBUTE' ; DISTRIBUTED : 'DISTRIBUTED' ; DISTRIBUTION : 'DISTRIBUTION' ; REPLICATION : 'REPLICATION' ; ROUNDROBIN : 'ROUNDROBIN' ; HASH : 'HASH' ; RANDOMLY : 'RANDOMLY' ; NODE_P : 'NODE' ; LIST_P : 'LIST' ; LESS : 'LESS' ; THAN : 'THAN' ; EVERY : 'EVERY' ; MOVEMENT : 'MOVEMENT' ; TSTag : 'TSTag' ; TSTime : 'TSTime' ; TSField : 'TSField' ; REPLICATED : 'REPLICATED' ; // support gauss end -------------------------------- CONFLICT : 'CONFLICT' ; SKIP_P : 'SKIP' ; LOCKED : 'LOCKED' ; TIES : 'TIES' ; ROLLUP : 'ROLLUP' ; CUBE : 'CUBE' ; GROUPING : 'GROUPING' ; SETS : 'SETS' ; TABLESAMPLE : 'TABLESAMPLE' ; ORDINALITY : 'ORDINALITY' ; XMLTABLE : 'XMLTABLE' ; COLUMNS : 'COLUMNS' ; XMLNAMESPACES : 'XMLNAMESPACES' ; ROWTYPE : 'ROWTYPE' ; NORMALIZED : 'NORMALIZED' ; WITHIN : 'WITHIN' ; FILTER : 'FILTER' ; GROUPS : 'GROUPS' ; OTHERS : 'OTHERS' ; NFC : 'NFC' ; NFD : 'NFD' ; NFKC : 'NFKC' ; NFKD : 'NFKD' ; UESCAPE : 'UESCAPE' ; VIEWS : 'VIEWS' ; NORMALIZE : 'NORMALIZE' ; DUMP : 'DUMP' ; PRINT_STRICT_PARAMS : 'PRINT_STRICT_PARAMS' ; VARIABLE_CONFLICT : 'VARIABLE_CONFLICT' ; ERROR : 'ERROR' ; USE_VARIABLE : 'USE_VARIABLE' ; USE_COLUMN : 'USE_COLUMN' ; ALIAS : 'ALIAS' ; CONSTANT : 'CONSTANT' ; PERFORM : 'PERFORM' ; GET : 'GET' ; DIAGNOSTICS : 'DIAGNOSTICS' ; STACKED : 'STACKED' ; ELSIF : 'ELSIF' ; WHILE : 'WHILE' ; REVERSE : 'REVERSE' ; FOREACH : 'FOREACH' ; SLICE : 'SLICE' ; EXIT : 'EXIT' ; RETURN : 'RETURN' ; QUERY : 'QUERY' ; RAISE : 'RAISE' ; SQLSTATE : 'SQLSTATE' ; DEBUG : 'DEBUG' ; LOG : 'LOG' ; INFO : 'INFO' ; NOTICE : 'NOTICE' ; WARNING : 'WARNING' ; EXCEPTION : 'EXCEPTION' ; ASSERT : 'ASSERT' ; LOOP : 'LOOP' ; OPEN : 'OPEN' ; // // IDENTIFIERS (4.1.1) // ABS : 'ABS' ; CBRT : 'CBRT' ; CEIL : 'CEIL' ; CEILING : 'CEILING' ; DEGREES : 'DEGREES' ; DIV : 'DIV' ; EXP : 'EXP' ; FACTORIAL : 'FACTORIAL' ; FLOOR : 'FLOOR' ; GCD : 'GCD' ; LCM : 'LCM' ; LN : 'LN' ; LOG10 : 'LOG10' ; MIN_SCALE : 'MIN_SCALE' ; MOD : 'MOD' ; PI : 'PI' ; POWER : 'POWER' ; RADIANS : 'RADIANS' ; ROUND : 'ROUND' ; SCALE : 'SCALE' ; SIGN : 'SIGN' ; SQRT : 'SQRT' ; TRIM_SCALE : 'TRIM_SCALE' ; TRUNC : 'TRUNC' ; WIDTH_BUCKET : 'WIDTH_BUCKET' ; RANDOM : 'RANDOM' ; SETSEED : 'SETSEED' ; ACOS : 'ACOS' ; ACOSD : 'ACOSD' ; ASIN : 'ASIN' ; ASIND : 'ASIND' ; ATAN : 'ATAN' ; ATAND : 'ATAND' ; ATAN2 : 'ATAN2' ; ATAN2D : 'ATAN2D' ; COS : 'COS' ; COSD : 'COSD' ; COT : 'COT' ; COTD : 'COTD' ; SIN : 'SIN' ; SIND : 'SIND' ; TAN : 'TAN' ; TAND : 'TAND' ; SINH : 'SINH' ; COSH : 'COSH' ; TANH : 'TANH' ; ASINH : 'ASINH' ; ACOSH : 'ACOSH' ; ATANH : 'ATANH' ; BIT_LENGTH : 'BIT_LENGTH' ; CHAR_LENGTH : 'CHAR_LENGTH' ; CHARACTER_LENGTH : 'CHARACTER_LENGTH' ; LOWER : 'LOWER' ; OCTET_LENGTH : 'OCTET_LENGTH' ; UPPER : 'UPPER' ; ASCII : 'ASCII' ; BTRIM : 'BTRIM' ; CHR : 'CHR' ; CONCAT : 'CONCAT' ; CONCAT_WS : 'CONCAT_WS' ; FORMAT : 'FORMAT' ; INITCAP : 'INITCAP' ; LENGTH : 'LENGTH' ; LPAD : 'LPAD' ; LTRIM : 'LTRIM' ; MD5 : 'MD5' ; PARSE_IDENT : 'PARSE_IDENT' ; PG_CLIENT_ENCODING : 'PG_CLIENT_ENCODING' ; QUOTE_IDENT : 'QUOTE_IDENT' ; QUOTE_LITERAL : 'QUOTE_LITERAL' ; QUOTE_NULLABLE : 'QUOTE_NULLABLE' ; REGEXP_COUNT : 'REGEXP_COUNT' ; REGEXP_INSTR : 'REGEXP_INSTR' ; REGEXP_LIKE : 'REGEXP_LIKE' ; REGEXP_MATCH : 'REGEXP_MATCH' ; REGEXP_MATCHES : 'REGEXP_MATCHES' ; REGEXP_REPLACE : 'REGEXP_REPLACE' ; REGEXP_SPLIT_TO_ARRAY : 'REGEXP_SPLIT_TO_ARRAY' ; REGEXP_SPLIT_TO_TABLE : 'REGEXP_SPLIT_TO_TABLE' ; REGEXP_SUBSTR : 'REGEXP_SUBSTR' ; REPEAT : 'REPEAT' ; RPAD : 'RPAD' ; RTRIM : 'RTRIM' ; SPLIT_PART : 'SPLIT_PART' ; STARTS_WITH : 'STARTS_WITH' ; STRING_TO_ARRAY : 'STRING_TO_ARRAY' ; STRING_TO_TABLE : 'STRING_TO_TABLE' ; STRPOS : 'STRPOS' ; SUBSTR : 'SUBSTR' ; TO_ASCII : 'TO_ASCII' ; TO_HEX : 'TO_HEX' ; TRANSLATE : 'TRANSLATE' ; UNISTR : 'UNISTR' ; AGE : 'AGE' ; CLOCK_TIMESTAMP : 'CLOCK_TIMESTAMP' ; DATE_BIN : 'DATE_BIN' ; DATE_PART : 'DATE_PART' ; DATE_TRUNC : 'DATE_TRUNC' ; ISFINITE : 'ISFINITE' ; JUSTIFY_DAYS : 'JUSTIFY_DAYS' ; JUSTIFY_HOURS : 'JUSTIFY_HOURS' ; JUSTIFY_INTERVAL : 'JUSTIFY_INTERVAL' ; MAKE_DATE : 'MAKE_DATE' ; MAKE_INTERVAL : 'MAKE_INTERVAL' ; MAKE_TIME : 'MAKE_TIME' ; MAKE_TIMESTAMP : 'MAKE_TIMESTAMP' ; MAKE_TIMESTAMPTZ : 'MAKE_TIMESTAMPTZ' ; NOW : 'NOW' ; STATEMENT_TIMESTAMP : 'STATEMENT_TIMESTAMP' ; TIMEOFDAY : 'TIMEOFDAY' ; TRANSACTION_TIMESTAMP : 'TRANSACTION_TIMESTAMP' ; TO_TIMESTAMP : 'TO_TIMESTAMP' ; TO_CHAR : 'TO_CHAR' ; TO_DATE : 'TO_DATE' ; TO_NUMBER : 'TO_NUMBER' ; Identifier : IdentifierStartChar IdentifierChar* ; fragment IdentifierStartChar : // these are the valid identifier start characters below 0x7F [a-zA-Z_] | // these are the valid characters from 0x80 to 0xFF [\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF] | // these are the letters above 0xFF which only need a single UTF-16 code unit [\u0100-\uD7FF\uE000-\uFFFF] {charIsLetter()}? | // letters which require multiple UTF-16 code units [\uD800-\uDBFF] [\uDC00-\uDFFF] { CheckIfUtf32Letter() }? ; fragment IdentifierChar : StrictIdentifierChar | '$' ; fragment StrictIdentifierChar : IdentifierStartChar | [0-9] ; /* Quoted Identifiers * * These are divided into four separate tokens, allowing distinction of valid quoted identifiers from invalid quoted * identifiers without sacrificing the ability of the lexer to reliably recover from lexical errors in the input. */ QuotedIdentifier : UnterminatedQuotedIdentifier '"' ; // This is a quoted identifier which only contains valid characters but is not terminated UnterminatedQuotedIdentifier : '"' ('""' | ~ [\u0000"])* ; // This is a quoted identifier which is terminated but contains a \u0000 character InvalidQuotedIdentifier : InvalidUnterminatedQuotedIdentifier '"' ; // This is a quoted identifier which is unterminated and contains a \u0000 character InvalidUnterminatedQuotedIdentifier : '"' ('""' | ~ '"')* ; /* Unicode Quoted Identifiers * * These are divided into four separate tokens, allowing distinction of valid Unicode quoted identifiers from invalid * Unicode quoted identifiers without sacrificing the ability of the lexer to reliably recover from lexical errors in * the input. Note that escape sequences are never checked as part of this determination due to the ability of users * to change the escape character with a UESCAPE clause following the Unicode quoted identifier. * * TODO: these rules assume "" is still a valid escape sequence within a Unicode quoted identifier. */ UnicodeQuotedIdentifier : 'U' '&' QuotedIdentifier ; // This is a Unicode quoted identifier which only contains valid characters but is not terminated UnterminatedUnicodeQuotedIdentifier : 'U' '&' UnterminatedQuotedIdentifier ; // This is a Unicode quoted identifier which is terminated but contains a \u0000 character InvalidUnicodeQuotedIdentifier : 'U' '&' InvalidQuotedIdentifier ; // This is a Unicode quoted identifier which is unterminated and contains a \u0000 character InvalidUnterminatedUnicodeQuotedIdentifier : 'U' '&' InvalidUnterminatedQuotedIdentifier ; // // CONSTANTS (4.1.2) // // String Constants (4.1.2.1) StringConstant : UnterminatedStringConstant '\'' ; UnterminatedStringConstant : '\'' ('\'\'' | ~ '\'')* ; // String Constants with C-style Escapes (4.1.2.2) BeginEscapeStringConstant : 'E' '\'' -> more , pushMode (EscapeStringConstantMode) ; // String Constants with Unicode Escapes (4.1.2.3) // // Note that escape sequences are never checked as part of this token due to the ability of users to change the escape // character with a UESCAPE clause following the Unicode string constant. // // TODO: these rules assume '' is still a valid escape sequence within a Unicode string constant. UnicodeEscapeStringConstant : UnterminatedUnicodeEscapeStringConstant '\'' ; UnterminatedUnicodeEscapeStringConstant : 'U' '&' UnterminatedStringConstant ; // Dollar-quoted String Constants (4.1.2.4) BeginDollarStringConstant : '$' Tag? '$' {pushTag();} -> pushMode (DollarQuotedStringMode) ; /* "The tag, if any, of a dollar-quoted string follows the same rules as an * unquoted identifier, except that it cannot contain a dollar sign." */ fragment Tag : IdentifierStartChar StrictIdentifierChar* ; // Bit-strings Constants (4.1.2.5) BinaryStringConstant : UnterminatedBinaryStringConstant '\'' ; UnterminatedBinaryStringConstant : 'B' '\'' [01]* ; InvalidBinaryStringConstant : InvalidUnterminatedBinaryStringConstant '\'' ; InvalidUnterminatedBinaryStringConstant : 'B' UnterminatedStringConstant ; HexadecimalStringConstant : UnterminatedHexadecimalStringConstant '\'' ; UnterminatedHexadecimalStringConstant : 'X' '\'' [0-9A-F]* ; InvalidHexadecimalStringConstant : InvalidUnterminatedHexadecimalStringConstant '\'' ; InvalidUnterminatedHexadecimalStringConstant : 'X' UnterminatedStringConstant ; // Numeric Constants (4.1.2.6) Integral : Digits ; NumericFail : Digits '..' {HandleNumericFail();} ; Numeric : Digits '.' Digits? /*? replaced with + to solve problem with DOT_DOT .. but this surely must be rewriten */ ('E' [+-]? Digits)? | '.' Digits ('E' [+-]? Digits)? | Digits 'E' [+-]? Digits ; fragment Digits : [0-9]+ ; PLSQLVARIABLENAME : ':' [A-Z_] [A-Z_0-9$]* ; PLSQLIDENTIFIER : ':"' ('\\' . | '""' | ~ ('"' | '\\'))* '"' ; // // WHITESPACE (4.1) // Whitespace : [ \t]+ -> channel (HIDDEN) ; Newline : ('\r' '\n'? | '\n') -> channel (HIDDEN) ; // // COMMENTS (4.1.5) // LineComment : '--' ~ [\r\n]* -> channel (HIDDEN) ; BlockComment : ('/*' ('/'* BlockComment | ~ [/*] | '/'+ ~ [/*] | '*'+ ~ [/*])* '*'* '*/') -> channel (HIDDEN) ; UnterminatedBlockComment : '/*' ('/'* BlockComment | // these characters are not part of special sequences in a block comment ~ [/*] | // handle / or * characters which are not part of /* or */ and do not appear at the end of the file ('/'+ ~ [/*] | '*'+ ~ [/*]))* // Handle the case of / or * characters at the end of the file, or a nested unterminated block comment ('/'+ | '*'+ | '/'* UnterminatedBlockComment)? // Optional assertion to make sure this rule is working as intended { UnterminatedBlockCommentDebugAssert(); } ; // // META-COMMANDS // // http://www.postgresql.org/docs/9.3/static/app-psql.html MetaCommand : '\\' (~ [\r\n\\"] | '"' ~ [\r\n"]* '"')* ('"' ~ [\r\n"]*)? ; EndMetaCommand : '\\\\' ; // // ERROR // // Any character which does not match one of the above rules will appear in the token stream as an ErrorCharacter token. // This ensures the lexer itself will never encounter a syntax error, so all error handling may be performed by the // parser. ErrorCharacter : . ; mode EscapeStringConstantMode; EscapeStringConstant : EscapeStringText '\'' -> mode (AfterEscapeStringConstantMode) ; UnterminatedEscapeStringConstant : EscapeStringText // Handle a final unmatched \ character appearing at the end of the file '\\'? EOF ; fragment EscapeStringText : ('\'\'' | '\\' ( // two-digit hex escapes are still valid when treated as single-digit escapes 'x' [0-9a-fA-F] | 'u' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] | 'U' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] | // Any character other than the Unicode escapes can follow a backslash. Some have special meaning, // but that doesn't affect the syntax. ~ [xuU]) | ~ ['\\])* ; InvalidEscapeStringConstant : InvalidEscapeStringText '\'' -> mode (AfterEscapeStringConstantMode) ; InvalidUnterminatedEscapeStringConstant : InvalidEscapeStringText // Handle a final unmatched \ character appearing at the end of the file '\\'? EOF ; fragment InvalidEscapeStringText : ('\'\'' | '\\' . | ~ ['\\])* ; mode AfterEscapeStringConstantMode; AfterEscapeStringConstantMode_Whitespace : Whitespace -> type (Whitespace) , channel (HIDDEN) ; AfterEscapeStringConstantMode_Newline : Newline -> type (Newline) , channel (HIDDEN) , mode (AfterEscapeStringConstantWithNewlineMode) ; AfterEscapeStringConstantMode_NotContinued : {} // intentionally empty -> skip , popMode ; mode AfterEscapeStringConstantWithNewlineMode; AfterEscapeStringConstantWithNewlineMode_Whitespace : Whitespace -> type (Whitespace) , channel (HIDDEN) ; AfterEscapeStringConstantWithNewlineMode_Newline : Newline -> type (Newline) , channel (HIDDEN) ; AfterEscapeStringConstantWithNewlineMode_Continued : '\'' -> more , mode (EscapeStringConstantMode) ; AfterEscapeStringConstantWithNewlineMode_NotContinued : {} // intentionally empty -> skip , popMode ; mode DollarQuotedStringMode; DollarText : ~ '$'+ //| '$'([0-9])+ | // this alternative improves the efficiency of handling $ characters within a dollar-quoted string which are // not part of the ending tag. '$' ~ '$'* ; EndDollarStringConstant : ('$' Tag? '$') {isTag()}? {popTag();} -> popMode ; ================================================ FILE: superior-postgres-parser/src/main/antlr4/io/github/melin/superior/parser/postgre/antlr4/PostgreSqlParser.g4 ================================================ parser grammar PostgreSqlParser; options { tokenVocab = PostgreSqlLexer; superClass = PostgreSqlParserBase; } @header { } @members { } root : stmtblock EOF ; plsqlroot : pl_function ; stmtblock : stmtmulti ; stmtmulti : (stmt SEMI?)* ; stmt : altereventtrigstmt | altercollationstmt | alterdatabasestmt | alterdatabasesetstmt | alterdefaultprivilegesstmt | alterdomainstmt | alterenumstmt | alterextensionstmt | alterextensioncontentsstmt | alterfdwstmt | alterforeignserverstmt | alterfunctionstmt | altergroupstmt | alterobjectdependsstmt | alterobjectschemastmt | alterownerstmt | alteroperatorstmt | altertypestmt | alterpolicystmt | alterseqstmt | altersystemstmt | altertablestmt | altertblspcstmt | altercompositetypestmt | alterpublicationstmt | alterrolesetstmt | alterrolestmt | altersubscriptionstmt | alterstatsstmt | altertsconfigurationstmt | altertsdictionarystmt | alterusermappingstmt | analyzestmt | callstmt | checkpointstmt | closeportalstmt | clusterstmt | commentstmt | constraintssetstmt | copystmt | createamstmt | createasstmt | createassertionstmt | createcaststmt | createconversionstmt | createdomainstmt | createextensionstmt | createfdwstmt | createforeignserverstmt | createforeigntablestmt | createfunctionstmt | creategroupstmt | creatematviewstmt | createopclassstmt | createopfamilystmt | createpublicationstmt | alteropfamilystmt | createpolicystmt | createplangstmt | createschemastmt | createseqstmt | createstmt | createsubscriptionstmt | createstatsstmt | createtablespacestmt | createtransformstmt | createtrigstmt | createeventtrigstmt | createrolestmt | createuserstmt | createusermappingstmt | createdbstmt | deallocatestmt | declarecursorstmt | definestmt | deletestmt | discardstmt | dostmt | dropcaststmt | dropopclassstmt | dropopfamilystmt | dropownedstmt | dropstmt | dropsubscriptionstmt | droptablespacestmt | droptransformstmt | droprolestmt | dropusermappingstmt | dropdbstmt | executestmt | explainstmt | fetchstmt | grantstmt | grantrolestmt | importforeignschemastmt | indexstmt | insertstmt | mergestmt | listenstmt | refreshmatviewstmt | loadstmt | lockstmt | notifystmt | preparestmt | reassignownedstmt | reindexstmt | removeaggrstmt | removefuncstmt | removeoperstmt | renamestmt | revokerolestmt | rulestmt | seclabelstmt | selectstmt | transactionstmt | truncatestmt | unlistenstmt | updatestmt | vacuumstmt | variableresetstmt | variablesetstmt | variableshowstmt | viewstmt | plsqlconsolecommand ; plsqlconsolecommand : MetaCommand EndMetaCommand? ; callstmt : CALL func_application ; createrolestmt : CREATE ROLE roleid opt_with optrolelist ; opt_with : WITH //| WITH_LA | ; optrolelist : createoptroleelem* ; alteroptrolelist : alteroptroleelem* ; alteroptroleelem : PASSWORD (sconst | NULL_P) | (ENCRYPTED | UNENCRYPTED) PASSWORD sconst | INHERIT | CONNECTION LIMIT signediconst | VALID UNTIL sconst | USER role_list | identifier ; createoptroleelem : alteroptroleelem | SYSID iconst | ADMIN role_list | ROLE role_list | IN_P (ROLE | GROUP_P) role_list ; createuserstmt : CREATE USER roleid opt_with optrolelist ; alterrolestmt : ALTER (ROLE | USER) rolespec opt_with alteroptrolelist ; opt_in_database : | IN_P DATABASE name ; alterrolesetstmt : ALTER (ROLE | USER) ALL? rolespec opt_in_database setresetclause ; droprolestmt : DROP (ROLE | USER | GROUP_P) (IF_P EXISTS)? role_list ; creategroupstmt : CREATE GROUP_P roleid opt_with optrolelist ; altergroupstmt : ALTER GROUP_P rolespec add_drop USER role_list ; add_drop : ADD_P | DROP ; createschemastmt : CREATE SCHEMA (IF_P NOT EXISTS)? (optschemaname AUTHORIZATION rolespec | colid) optschemaeltlist ; optschemaname : colid | ; optschemaeltlist : schema_stmt* ; schema_stmt : createstmt | indexstmt | createseqstmt | createtrigstmt | grantstmt | viewstmt ; variablesetstmt : SET (LOCAL | SESSION)? set_rest ; set_rest : TRANSACTION transaction_mode_list | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list | set_rest_more ; generic_set : var_name (TO | EQUAL) var_list ; set_rest_more : generic_set | var_name FROM CURRENT_P | TIME ZONE zone_value | CATALOG sconst | SCHEMA sconst | NAMES opt_encoding | ROLE nonreservedword_or_sconst | SESSION AUTHORIZATION nonreservedword_or_sconst | XML_P OPTION document_or_content | TRANSACTION SNAPSHOT sconst ; var_name : colid (DOT colid)* ; var_list : var_value (COMMA var_value)* ; var_value : opt_boolean_or_string | numericonly ; iso_level : READ (UNCOMMITTED | COMMITTED) | REPEATABLE READ | SERIALIZABLE ; opt_boolean_or_string : TRUE_P | FALSE_P | ON | nonreservedword_or_sconst ; zone_value : sconst | identifier | constinterval sconst opt_interval | constinterval OPEN_PAREN iconst CLOSE_PAREN sconst | numericonly | DEFAULT | LOCAL ; opt_encoding : sconst | DEFAULT | ; nonreservedword_or_sconst : nonreservedword | sconst ; variableresetstmt : RESET reset_rest ; reset_rest : generic_reset | TIME ZONE | TRANSACTION ISOLATION LEVEL | SESSION AUTHORIZATION ; generic_reset : var_name | ALL ; setresetclause : SET set_rest | variableresetstmt ; functionsetresetclause : SET set_rest_more | variableresetstmt ; variableshowstmt : SHOW (var_name | TIME ZONE | TRANSACTION ISOLATION LEVEL | SESSION AUTHORIZATION | ALL) ; constraintssetstmt : SET CONSTRAINTS constraints_set_list constraints_set_mode ; constraints_set_list : ALL | qualified_name_list ; constraints_set_mode : DEFERRED | IMMEDIATE ; checkpointstmt : CHECKPOINT ; discardstmt : DISCARD (ALL | TEMP | TEMPORARY | PLANS | SEQUENCES) ; altertablestmt : ALTER TABLE (IF_P EXISTS)? relation_expr (alter_table_cmds | partition_cmd) | ALTER TABLE ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER INDEX (IF_P EXISTS)? qualified_name (alter_table_cmds | index_partition_cmd) | ALTER INDEX ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER SEQUENCE (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER VIEW (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER MATERIALIZED VIEW (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER FOREIGN TABLE (IF_P EXISTS)? relation_expr alter_table_cmds ; alter_table_cmds : alter_table_cmd (COMMA alter_table_cmd)* ; partition_cmd : ATTACH PARTITION qualified_name partitionboundspec | DETACH PARTITION qualified_name ; index_partition_cmd : ATTACH PARTITION qualified_name ; alter_table_cmd : ADD_P columnDef | ADD_P IF_P NOT EXISTS columnDef | ADD_P COLUMN columnDef | ADD_P COLUMN IF_P NOT EXISTS columnDef | ALTER opt_column colid alter_column_default | ALTER opt_column colid DROP NOT NULL_P | ALTER opt_column colid SET NOT NULL_P | ALTER opt_column colid DROP EXPRESSION | ALTER opt_column colid DROP EXPRESSION IF_P EXISTS | ALTER opt_column colid SET STATISTICS signediconst | ALTER opt_column iconst SET STATISTICS signediconst | ALTER opt_column colid SET reloptions | ALTER opt_column colid RESET reloptions | ALTER opt_column colid SET STORAGE colid | ALTER opt_column colid ADD_P GENERATED generated_when AS IDENTITY_P optparenthesizedseqoptlist | ALTER opt_column colid alter_identity_column_option_list | ALTER opt_column colid DROP IDENTITY_P | ALTER opt_column colid DROP IDENTITY_P IF_P EXISTS | DROP opt_column IF_P EXISTS colid opt_drop_behavior | DROP opt_column colid opt_drop_behavior | ALTER opt_column colid opt_set_data TYPE_P typename opt_collate_clause alter_using | ALTER opt_column colid alter_generic_options | ADD_P tableconstraint | ALTER CONSTRAINT name constraintattributespec | VALIDATE CONSTRAINT name | DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior | DROP CONSTRAINT name opt_drop_behavior | SET WITHOUT OIDS | CLUSTER ON name | SET WITHOUT CLUSTER | SET LOGGED | SET UNLOGGED | ENABLE_P TRIGGER name | ENABLE_P ALWAYS TRIGGER name | ENABLE_P REPLICA TRIGGER name | ENABLE_P TRIGGER ALL | ENABLE_P TRIGGER USER | DISABLE_P TRIGGER name | DISABLE_P TRIGGER ALL | DISABLE_P TRIGGER USER | ENABLE_P RULE name | ENABLE_P ALWAYS RULE name | ENABLE_P REPLICA RULE name | DISABLE_P RULE name | INHERIT qualified_name | NO INHERIT qualified_name | OF any_name | NOT OF | OWNER TO rolespec | SET TABLESPACE name | SET reloptions | RESET reloptions | REPLICA IDENTITY_P replica_identity | ENABLE_P ROW LEVEL SECURITY | DISABLE_P ROW LEVEL SECURITY | FORCE ROW LEVEL SECURITY | NO FORCE ROW LEVEL SECURITY | alter_generic_options ; alter_column_default : SET DEFAULT a_expr | DROP DEFAULT ; opt_drop_behavior : CASCADE | RESTRICT | ; opt_collate_clause : COLLATE any_name | ; alter_using : USING a_expr | ; replica_identity : NOTHING | FULL | DEFAULT | USING INDEX name ; reloptions : OPEN_PAREN reloption_list CLOSE_PAREN ; opt_reloptions : WITH reloptions | ; reloption_list : reloption_elem (COMMA reloption_elem)* ; reloption_elem : collabel (EQUAL def_arg | DOT collabel (EQUAL def_arg)?)? ; alter_identity_column_option_list : alter_identity_column_option+ ; alter_identity_column_option : RESTART (opt_with numericonly)? | SET (seqoptelem | GENERATED generated_when) ; partitionboundspec : FOR VALUES WITH OPEN_PAREN hash_partbound CLOSE_PAREN | FOR VALUES IN_P OPEN_PAREN expr_list CLOSE_PAREN | FOR VALUES FROM OPEN_PAREN expr_list CLOSE_PAREN TO OPEN_PAREN expr_list CLOSE_PAREN | DEFAULT ; hash_partbound_elem : nonreservedword iconst ; hash_partbound : hash_partbound_elem (COMMA hash_partbound_elem)* ; altercompositetypestmt : ALTER TYPE_P any_name alter_type_cmds ; alter_type_cmds : alter_type_cmd (COMMA alter_type_cmd)* ; alter_type_cmd : ADD_P ATTRIBUTE tablefuncelement opt_drop_behavior | DROP ATTRIBUTE (IF_P EXISTS)? colid opt_drop_behavior | ALTER ATTRIBUTE colid opt_set_data TYPE_P typename opt_collate_clause opt_drop_behavior ; closeportalstmt : CLOSE (cursor_name | ALL) ; copystmt : COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause | COPY OPEN_PAREN preparablestmt CLOSE_PAREN TO opt_program copy_file_name opt_with copy_options ; copy_from : FROM | TO ; opt_program : PROGRAM | ; copy_file_name : sconst | STDIN | STDOUT ; copy_options : copy_opt_list | OPEN_PAREN copy_generic_opt_list CLOSE_PAREN ; copy_opt_list : copy_opt_item* ; copy_opt_item : BINARY | FREEZE | DELIMITER opt_as sconst | NULL_P opt_as sconst | CSV | HEADER_P | QUOTE opt_as sconst | ESCAPE opt_as sconst | FORCE QUOTE columnlist | FORCE QUOTE STAR | FORCE NOT NULL_P columnlist | FORCE NULL_P columnlist | ENCODING sconst ; opt_binary : BINARY | ; copy_delimiter : opt_using DELIMITERS sconst | ; opt_using : USING | ; copy_generic_opt_list : copy_generic_opt_elem (COMMA copy_generic_opt_elem)* ; copy_generic_opt_elem : collabel copy_generic_opt_arg ; copy_generic_opt_arg : opt_boolean_or_string | numericonly | STAR | OPEN_PAREN copy_generic_opt_arg_list CLOSE_PAREN | ; copy_generic_opt_arg_list : copy_generic_opt_arg_list_item (COMMA copy_generic_opt_arg_list_item)* ; copy_generic_opt_arg_list_item : opt_boolean_or_string ; createstmt : CREATE opttemp TABLE (IF_P NOT EXISTS)? qualified_name ( OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit optpartitionspec table_access_method_clause gaussprimayindex optwith oncommitoption opttablespace gaussextension | OF any_name opttypedtableelementlist optpartitionspec table_access_method_clause optwith oncommitoption opttablespace | PARTITION OF qualified_name opttypedtableelementlist partitionboundspec optpartitionspec table_access_method_clause optwith oncommitoption opttablespace ) ; // -------- support gauss gaussprimayindex : PRIMARY INDEX OPEN_PAREN colid CLOSE_PAREN | ; gaussextension : distributeby toGroupOrNode tablePartition? | ; distributeby : DISTRIBUTE BY (REPLICATION | ROUNDROBIN | HASH OPEN_PAREN distributebyhashlist CLOSE_PAREN) | DISTRIBUTED BY OPEN_PAREN distributebyhashlist CLOSE_PAREN | DISTRIBUTED (RANDOMLY | REPLICATED) | ; distributebyhashlist : distributebyhashitem (COMMA distributebyhashitem)* ; distributebyhashitem : collabel ; toGroupOrNode : TO GROUP_P collabel | TO NODE_P OPEN_PAREN collabel (COMMA collabel)* CLOSE_PAREN | ; tablePartition : PARTITION BY partition_list ((ENABLE_P | DISABLE_P) ROW MOVEMENT)? ; partition_list : value_partition_stmt | range_partition_stmt | list_partition_stmt | normal_partition_stmt ; normal_partition_stmt : OPEN_PAREN list_partition_value CLOSE_PAREN AUTOMAPPED? ; list_partition_stmt : LIST_P OPEN_PAREN partition_key CLOSE_PAREN OPEN_PAREN list_partition_items CLOSE_PAREN ; list_partition_items : list_partition_item (COMMA list_partition_item)* ; list_partition_item : PARTITION partition_name VALUES LESS THAN OPEN_PAREN list_partition_value CLOSE_PAREN table_space_item? ; list_partition_value : partition_name (COMMA partition_name)* | DEFAULT ; value_partition_stmt : VALUES OPEN_PAREN partition_key CLOSE_PAREN ; range_partition_stmt : RANGE OPEN_PAREN partition_key CLOSE_PAREN OPEN_PAREN (partition_less_than_items | partition_start_end_items) CLOSE_PAREN ; partition_less_than_items : partition_less_than_item (COMMA partition_less_than_item)* ; partition_start_end_items : partition_start_end_item (COMMA partition_start_end_item)* ; partition_less_than_item : PARTITION partition_name VALUES LESS THAN OPEN_PAREN (partition_value | MAXVALUE) CLOSE_PAREN table_space_item? ; partition_start_end_item : PARTITION partition_name start_end_item table_space_item? ; start_end_item : start_item | end_item | start_item end_item (EVERY OPEN_PAREN aexprconst CLOSE_PAREN)? ; start_item : START OPEN_PAREN partition_value CLOSE_PAREN ; end_item : END_P OPEN_PAREN (partition_value | MAXVALUE) CLOSE_PAREN ; partition_key : colid ; partition_name : colid ; partition_value : a_expr ; table_space_item : TABLESPACE table_space_name ; table_space_name : qualified_name ; // -------- support gauss opttemp : TEMPORARY | TEMP | LOCAL (TEMPORARY | TEMP) | GLOBAL (TEMPORARY | TEMP) | UNLOGGED | ; opttableelementlist : tableelementlist | ; opttypedtableelementlist : OPEN_PAREN typedtableelementlist CLOSE_PAREN | ; tableelementlist : tableelement (COMMA tableelement)* ; typedtableelementlist : typedtableelement (COMMA typedtableelement)* ; tableelement : tableconstraint | tablelikeclause | columnDef ; typedtableelement : columnOptions | tableconstraint ; columnDef : colid typename create_generic_options colquallist ; columnOptions : colid (WITH OPTIONS)? colquallist ; colquallist : colconstraint* ; colconstraint : CONSTRAINT name colconstraintelem | colconstraintelem | constraintattr | COLLATE any_name ; colconstraintelem : NOT NULL_P | NULL_P | UNIQUE opt_definition optconstablespace | PRIMARY KEY opt_definition optconstablespace | CHECK OPEN_PAREN a_expr CLOSE_PAREN opt_no_inherit | DEFAULT b_expr | GENERATED generated_when AS (IDENTITY_P optparenthesizedseqoptlist | OPEN_PAREN a_expr CLOSE_PAREN STORED) | REFERENCES qualified_name opt_column_list key_match key_actions ; generated_when : ALWAYS | BY DEFAULT ; constraintattr : DEFERRABLE | NOT DEFERRABLE | INITIALLY (DEFERRED | IMMEDIATE) ; tablelikeclause : LIKE qualified_name tablelikeoptionlist ; tablelikeoptionlist : ((INCLUDING | EXCLUDING) tablelikeoption)* ; tablelikeoption : COMMENTS | CONSTRAINTS | DEFAULTS | IDENTITY_P | GENERATED | INDEXES | STATISTICS | STORAGE | ALL ; tableconstraint : CONSTRAINT name constraintelem | constraintelem ; constraintelem : CHECK OPEN_PAREN a_expr CLOSE_PAREN constraintattributespec | UNIQUE (OPEN_PAREN columnlist CLOSE_PAREN opt_c_include opt_definition optconstablespace constraintattributespec | existingindex constraintattributespec) | PRIMARY KEY (OPEN_PAREN columnlist CLOSE_PAREN opt_c_include opt_definition optconstablespace constraintattributespec | existingindex constraintattributespec) | EXCLUDE access_method_clause OPEN_PAREN exclusionconstraintlist CLOSE_PAREN opt_c_include opt_definition optconstablespace exclusionwhereclause constraintattributespec | FOREIGN KEY OPEN_PAREN columnlist CLOSE_PAREN REFERENCES qualified_name opt_column_list key_match key_actions constraintattributespec ; opt_no_inherit : NO INHERIT | ; opt_column_list : OPEN_PAREN columnlist CLOSE_PAREN | ; columnlist : columnElem (COMMA columnElem)* ; columnElem : colid ; opt_c_include : INCLUDE OPEN_PAREN columnlist CLOSE_PAREN | ; key_match : MATCH (FULL | PARTIAL | SIMPLE) | ; exclusionconstraintlist : exclusionconstraintelem (COMMA exclusionconstraintelem)* ; exclusionconstraintelem : index_elem WITH (any_operator | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN) ; exclusionwhereclause : WHERE OPEN_PAREN a_expr CLOSE_PAREN | ; key_actions : key_update | key_delete | key_update key_delete | key_delete key_update | ; key_update : ON UPDATE key_action ; key_delete : ON DELETE_P key_action ; key_action : NO ACTION | RESTRICT | CASCADE | SET (NULL_P | DEFAULT) ; optinherit : INHERITS OPEN_PAREN qualified_name_list CLOSE_PAREN | ; optpartitionspec : partitionspec | ; partitionspec : PARTITION BY colid OPEN_PAREN part_params CLOSE_PAREN ; part_params : part_elem (COMMA part_elem)* ; part_elem : colid opt_collate opt_class | func_expr_windowless opt_collate opt_class | OPEN_PAREN a_expr CLOSE_PAREN opt_collate opt_class ; table_access_method_clause : USING name | ; optwith : WITH reloptions | WITHOUT OIDS | ; oncommitoption : ON COMMIT (DROP | DELETE_P ROWS | PRESERVE ROWS) | ; opttablespace : TABLESPACE name | ; optconstablespace : USING INDEX TABLESPACE name | ; existingindex : USING INDEX name ; createstatsstmt : CREATE STATISTICS (IF_P NOT EXISTS)? any_name opt_name_list ON expr_list FROM from_list ; alterstatsstmt : ALTER STATISTICS (IF_P EXISTS)? any_name SET STATISTICS signediconst ; createasstmt : CREATE opttemp TABLE (IF_P NOT EXISTS)? create_as_target AS selectstmt opt_with_data ; create_as_target : qualified_name opt_column_list table_access_method_clause optwith oncommitoption opttablespace gaussextension ; opt_with_data : WITH (DATA_P | NO DATA_P) | ; creatematviewstmt : CREATE optnolog MATERIALIZED VIEW (IF_P NOT EXISTS)? create_mv_target AS selectstmt opt_with_data ; create_mv_target : qualified_name opt_column_list table_access_method_clause opt_reloptions opttablespace ; optnolog : UNLOGGED | ; refreshmatviewstmt : REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data ; createseqstmt : CREATE opttemp SEQUENCE (IF_P NOT EXISTS)? qualified_name optseqoptlist ; alterseqstmt : ALTER SEQUENCE (IF_P EXISTS)? qualified_name seqoptlist ; optseqoptlist : seqoptlist | ; optparenthesizedseqoptlist : OPEN_PAREN seqoptlist CLOSE_PAREN | ; seqoptlist : seqoptelem+ ; seqoptelem : AS simpletypename | CACHE numericonly | CYCLE | INCREMENT opt_by numericonly | MAXVALUE numericonly | MINVALUE numericonly | NO (MAXVALUE | MINVALUE | CYCLE) | OWNED BY any_name | SEQUENCE NAME_P any_name | START opt_with numericonly | RESTART opt_with numericonly? ; opt_by : BY | ; numericonly : fconst | PLUS fconst | MINUS fconst | signediconst ; numericonly_list : numericonly (COMMA numericonly)* ; createplangstmt : CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name (HANDLER handler_name opt_inline_handler opt_validator)? ; opt_trusted : TRUSTED | ; handler_name : name attrs? ; opt_inline_handler : INLINE_P handler_name | ; validator_clause : VALIDATOR handler_name | NO VALIDATOR ; opt_validator : validator_clause | ; opt_procedural : PROCEDURAL | ; createtablespacestmt : CREATE TABLESPACE name opttablespaceowner LOCATION sconst opt_reloptions ; opttablespaceowner : OWNER rolespec | ; droptablespacestmt : DROP TABLESPACE (IF_P EXISTS)? name ; createextensionstmt : CREATE EXTENSION (IF_P NOT EXISTS)? name opt_with create_extension_opt_list ; create_extension_opt_list : create_extension_opt_item* ; create_extension_opt_item : SCHEMA name | VERSION_P nonreservedword_or_sconst | FROM nonreservedword_or_sconst | CASCADE ; alterextensionstmt : ALTER EXTENSION name UPDATE alter_extension_opt_list ; alter_extension_opt_list : alter_extension_opt_item* ; alter_extension_opt_item : TO nonreservedword_or_sconst ; alterextensioncontentsstmt : ALTER EXTENSION name add_drop object_type_name name | ALTER EXTENSION name add_drop object_type_any_name any_name | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes | ALTER EXTENSION name add_drop CAST OPEN_PAREN typename AS typename CLOSE_PAREN | ALTER EXTENSION name add_drop DOMAIN_P typename | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes | ALTER EXTENSION name add_drop OPERATOR operator_with_argtypes | ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING name | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING name | ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes | ALTER EXTENSION name add_drop ROUTINE function_with_argtypes | ALTER EXTENSION name add_drop TRANSFORM FOR typename LANGUAGE name | ALTER EXTENSION name add_drop TYPE_P typename ; createfdwstmt : CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options ; fdw_option : HANDLER handler_name | NO HANDLER | VALIDATOR handler_name | NO VALIDATOR ; fdw_options : fdw_option+ ; opt_fdw_options : fdw_options | ; alterfdwstmt : ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options | ALTER FOREIGN DATA_P WRAPPER name fdw_options ; create_generic_options : OPTIONS OPEN_PAREN generic_option_list CLOSE_PAREN | ; generic_option_list : generic_option_elem (COMMA generic_option_elem)* ; alter_generic_options : OPTIONS OPEN_PAREN alter_generic_option_list CLOSE_PAREN ; alter_generic_option_list : alter_generic_option_elem (COMMA alter_generic_option_elem)* ; alter_generic_option_elem : generic_option_elem | SET generic_option_elem | ADD_P generic_option_elem | DROP generic_option_name ; generic_option_elem : generic_option_name generic_option_arg ; generic_option_name : collabel ; generic_option_arg : sconst ; createforeignserverstmt : CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options | CREATE SERVER IF_P NOT EXISTS name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options ; opt_type : TYPE_P sconst | ; foreign_server_version : VERSION_P (sconst | NULL_P) ; opt_foreign_server_version : foreign_server_version | ; alterforeignserverstmt : ALTER SERVER name (alter_generic_options | foreign_server_version alter_generic_options?) ; createforeigntablestmt : CREATE FOREIGN TABLE qualified_name OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit SERVER name create_generic_options | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit SERVER name create_generic_options | CREATE FOREIGN TABLE qualified_name PARTITION OF qualified_name opttypedtableelementlist partitionboundspec SERVER name create_generic_options | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name opttypedtableelementlist partitionboundspec SERVER name create_generic_options ; importforeignschemastmt : IMPORT_P FOREIGN SCHEMA name import_qualification FROM SERVER name INTO name create_generic_options ; import_qualification_type : LIMIT TO | EXCEPT ; import_qualification : import_qualification_type OPEN_PAREN relation_expr_list CLOSE_PAREN | ; createusermappingstmt : CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options | CREATE USER MAPPING IF_P NOT EXISTS FOR auth_ident SERVER name create_generic_options ; auth_ident : rolespec | USER ; dropusermappingstmt : DROP USER MAPPING FOR auth_ident SERVER name | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name ; alterusermappingstmt : ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options ; createpolicystmt : CREATE POLICY name ON qualified_name rowsecuritydefaultpermissive rowsecuritydefaultforcmd rowsecuritydefaulttorole rowsecurityoptionalexpr rowsecurityoptionalwithcheck ; alterpolicystmt : ALTER POLICY name ON qualified_name rowsecurityoptionaltorole rowsecurityoptionalexpr rowsecurityoptionalwithcheck ; rowsecurityoptionalexpr : USING OPEN_PAREN a_expr CLOSE_PAREN | ; rowsecurityoptionalwithcheck : WITH CHECK OPEN_PAREN a_expr CLOSE_PAREN | ; rowsecuritydefaulttorole : TO role_list | ; rowsecurityoptionaltorole : TO role_list | ; rowsecuritydefaultpermissive : AS identifier | ; rowsecuritydefaultforcmd : FOR row_security_cmd | ; row_security_cmd : ALL | SELECT | INSERT | UPDATE | DELETE_P ; createamstmt : CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name ; am_type : INDEX | TABLE ; createtrigstmt : CREATE TRIGGER name triggeractiontime triggerevents ON qualified_name triggerreferencing triggerforspec triggerwhen EXECUTE function_or_procedure func_name OPEN_PAREN triggerfuncargs CLOSE_PAREN | CREATE CONSTRAINT TRIGGER name AFTER triggerevents ON qualified_name optconstrfromtable constraintattributespec FOR EACH ROW triggerwhen EXECUTE function_or_procedure func_name OPEN_PAREN triggerfuncargs CLOSE_PAREN ; triggeractiontime : BEFORE | AFTER | INSTEAD OF ; triggerevents : triggeroneevent (OR triggeroneevent)* ; triggeroneevent : INSERT | DELETE_P | UPDATE | UPDATE OF columnlist | TRUNCATE ; triggerreferencing : REFERENCING triggertransitions | ; triggertransitions : triggertransition+ ; triggertransition : transitionoldornew transitionrowortable opt_as transitionrelname ; transitionoldornew : NEW | OLD ; transitionrowortable : TABLE | ROW ; transitionrelname : colid ; triggerforspec : FOR triggerforopteach triggerfortype | ; triggerforopteach : EACH | ; triggerfortype : ROW | STATEMENT ; triggerwhen : WHEN OPEN_PAREN a_expr CLOSE_PAREN | ; function_or_procedure : FUNCTION | PROCEDURE ; triggerfuncargs : (triggerfuncarg |) (COMMA triggerfuncarg)* ; triggerfuncarg : iconst | fconst | sconst | collabel ; optconstrfromtable : FROM qualified_name | ; constraintattributespec : constraintattributeElem* ; constraintattributeElem : NOT DEFERRABLE | DEFERRABLE | INITIALLY IMMEDIATE | INITIALLY DEFERRED | NOT VALID | NO INHERIT ; createeventtrigstmt : CREATE EVENT TRIGGER name ON collabel EXECUTE function_or_procedure func_name OPEN_PAREN CLOSE_PAREN | CREATE EVENT TRIGGER name ON collabel WHEN event_trigger_when_list EXECUTE function_or_procedure func_name OPEN_PAREN CLOSE_PAREN ; event_trigger_when_list : event_trigger_when_item (AND event_trigger_when_item)* ; event_trigger_when_item : colid IN_P OPEN_PAREN event_trigger_value_list CLOSE_PAREN ; event_trigger_value_list : sconst (COMMA sconst)* ; altereventtrigstmt : ALTER EVENT TRIGGER name enable_trigger ; enable_trigger : ENABLE_P | ENABLE_P REPLICA | ENABLE_P ALWAYS | DISABLE_P ; createassertionstmt : CREATE ASSERTION any_name CHECK OPEN_PAREN a_expr CLOSE_PAREN constraintattributespec ; definestmt : CREATE opt_or_replace AGGREGATE func_name aggr_args definition | CREATE opt_or_replace AGGREGATE func_name old_aggr_definition | CREATE OPERATOR any_operator definition | CREATE TYPE_P any_name definition | CREATE TYPE_P any_name | CREATE TYPE_P any_name AS OPEN_PAREN opttablefuncelementlist CLOSE_PAREN | CREATE TYPE_P any_name AS ENUM_P OPEN_PAREN opt_enum_val_list CLOSE_PAREN | CREATE TYPE_P any_name AS RANGE definition | CREATE TEXT_P SEARCH PARSER any_name definition | CREATE TEXT_P SEARCH DICTIONARY any_name definition | CREATE TEXT_P SEARCH TEMPLATE any_name definition | CREATE TEXT_P SEARCH CONFIGURATION any_name definition | CREATE COLLATION any_name definition | CREATE COLLATION IF_P NOT EXISTS any_name definition | CREATE COLLATION any_name FROM any_name | CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name ; definition : OPEN_PAREN def_list CLOSE_PAREN ; def_list : def_elem (COMMA def_elem)* ; def_elem : collabel (EQUAL def_arg)? ; def_arg : func_type | reserved_keyword | qual_all_op | numericonly | sconst | NONE ; old_aggr_definition : OPEN_PAREN old_aggr_list CLOSE_PAREN ; old_aggr_list : old_aggr_elem (COMMA old_aggr_elem)* ; old_aggr_elem : identifier EQUAL def_arg ; opt_enum_val_list : enum_val_list | ; enum_val_list : sconst (COMMA sconst)* ; alterenumstmt : ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst BEFORE sconst | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst AFTER sconst | ALTER TYPE_P any_name RENAME VALUE_P sconst TO sconst ; opt_if_not_exists : IF_P NOT EXISTS | ; createopclassstmt : CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P typename USING name opt_opfamily AS opclass_item_list ; opclass_item_list : opclass_item (COMMA opclass_item)* ; opclass_item : OPERATOR iconst any_operator opclass_purpose opt_recheck | OPERATOR iconst operator_with_argtypes opclass_purpose opt_recheck | FUNCTION iconst function_with_argtypes | FUNCTION iconst OPEN_PAREN type_list CLOSE_PAREN function_with_argtypes | STORAGE typename ; opt_default : DEFAULT | ; opt_opfamily : FAMILY any_name | ; opclass_purpose : FOR SEARCH | FOR ORDER BY any_name | ; opt_recheck : RECHECK | ; createopfamilystmt : CREATE OPERATOR FAMILY any_name USING name ; alteropfamilystmt : ALTER OPERATOR FAMILY any_name USING name ADD_P opclass_item_list | ALTER OPERATOR FAMILY any_name USING name DROP opclass_drop_list ; opclass_drop_list : opclass_drop (COMMA opclass_drop)* ; opclass_drop : OPERATOR iconst OPEN_PAREN type_list CLOSE_PAREN | FUNCTION iconst OPEN_PAREN type_list CLOSE_PAREN ; dropopclassstmt : DROP OPERATOR CLASS any_name USING name opt_drop_behavior | DROP OPERATOR CLASS IF_P EXISTS any_name USING name opt_drop_behavior ; dropopfamilystmt : DROP OPERATOR FAMILY any_name USING name opt_drop_behavior | DROP OPERATOR FAMILY IF_P EXISTS any_name USING name opt_drop_behavior ; dropownedstmt : DROP OWNED BY role_list opt_drop_behavior ; reassignownedstmt : REASSIGN OWNED BY role_list TO rolespec ; dropstmt : DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior | DROP object_type_any_name any_name_list opt_drop_behavior | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior | DROP drop_type_name name_list opt_drop_behavior | DROP object_type_name_on_any_name name ON any_name opt_drop_behavior | DROP object_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior | DROP TYPE_P type_name_list opt_drop_behavior | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior | DROP DOMAIN_P type_name_list opt_drop_behavior | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior | DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior ; object_type_any_name : TABLE | SEQUENCE | VIEW | MATERIALIZED VIEW | INDEX | FOREIGN TABLE | COLLATION | CONVERSION_P | STATISTICS | TEXT_P SEARCH PARSER | TEXT_P SEARCH DICTIONARY | TEXT_P SEARCH TEMPLATE | TEXT_P SEARCH CONFIGURATION ; object_type_name : drop_type_name | DATABASE | ROLE | SUBSCRIPTION | TABLESPACE ; drop_type_name : ACCESS METHOD | EVENT TRIGGER | EXTENSION | FOREIGN DATA_P WRAPPER | opt_procedural LANGUAGE | PUBLICATION | SCHEMA | SERVER ; object_type_name_on_any_name : POLICY | RULE | TRIGGER ; any_name_list : any_name (COMMA any_name)* ; any_name : colid attrs? ; attrs :(DOT attr_name)+ ; type_name_list : typename (COMMA typename)* ; truncatestmt : TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior ; opt_restart_seqs : CONTINUE_P IDENTITY_P | RESTART IDENTITY_P | ; commentstmt : COMMENT ON object_type_any_name any_name IS comment_text | COMMENT ON COLUMN any_name IS comment_text | COMMENT ON object_type_name name IS comment_text | COMMENT ON TYPE_P typename IS comment_text | COMMENT ON DOMAIN_P typename IS comment_text | COMMENT ON AGGREGATE aggregate_with_argtypes IS comment_text | COMMENT ON FUNCTION function_with_argtypes IS comment_text | COMMENT ON OPERATOR operator_with_argtypes IS comment_text | COMMENT ON CONSTRAINT name ON any_name IS comment_text | COMMENT ON CONSTRAINT name ON DOMAIN_P any_name IS comment_text | COMMENT ON object_type_name_on_any_name name ON any_name IS comment_text | COMMENT ON PROCEDURE function_with_argtypes IS comment_text | COMMENT ON ROUTINE function_with_argtypes IS comment_text | COMMENT ON TRANSFORM FOR typename LANGUAGE name IS comment_text | COMMENT ON OPERATOR CLASS any_name USING name IS comment_text | COMMENT ON OPERATOR FAMILY any_name USING name IS comment_text | COMMENT ON LARGE_P OBJECT_P numericonly IS comment_text | COMMENT ON CAST OPEN_PAREN typename AS typename CLOSE_PAREN IS comment_text ; comment_text : sconst | NULL_P ; seclabelstmt : SECURITY LABEL opt_provider ON object_type_any_name any_name IS security_label | SECURITY LABEL opt_provider ON COLUMN any_name IS security_label | SECURITY LABEL opt_provider ON object_type_name name IS security_label | SECURITY LABEL opt_provider ON TYPE_P typename IS security_label | SECURITY LABEL opt_provider ON DOMAIN_P typename IS security_label | SECURITY LABEL opt_provider ON AGGREGATE aggregate_with_argtypes IS security_label | SECURITY LABEL opt_provider ON FUNCTION function_with_argtypes IS security_label | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P numericonly IS security_label | SECURITY LABEL opt_provider ON PROCEDURE function_with_argtypes IS security_label | SECURITY LABEL opt_provider ON ROUTINE function_with_argtypes IS security_label ; opt_provider : FOR nonreservedword_or_sconst | ; security_label : sconst | NULL_P ; fetchstmt : FETCH fetch_args | MOVE fetch_args ; fetch_args : cursor_name | from_in cursor_name | NEXT opt_from_in cursor_name | PRIOR opt_from_in cursor_name | FIRST_P opt_from_in cursor_name | LAST_P opt_from_in cursor_name | ABSOLUTE_P signediconst opt_from_in cursor_name | RELATIVE_P signediconst opt_from_in cursor_name | signediconst opt_from_in cursor_name | ALL opt_from_in cursor_name | FORWARD opt_from_in cursor_name | FORWARD signediconst opt_from_in cursor_name | FORWARD ALL opt_from_in cursor_name | BACKWARD opt_from_in cursor_name | BACKWARD signediconst opt_from_in cursor_name | BACKWARD ALL opt_from_in cursor_name ; from_in : FROM | IN_P ; opt_from_in : from_in | ; grantstmt : GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option ; revokestmt : REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior ; privileges : privilege_list | ALL | ALL PRIVILEGES | ALL OPEN_PAREN columnlist CLOSE_PAREN | ALL PRIVILEGES OPEN_PAREN columnlist CLOSE_PAREN ; privilege_list : privilege (COMMA privilege)* ; privilege : SELECT opt_column_list | REFERENCES opt_column_list | CREATE opt_column_list | colid opt_column_list ; privilege_target : qualified_name_list | TABLE qualified_name_list | SEQUENCE qualified_name_list | FOREIGN DATA_P WRAPPER name_list | FOREIGN SERVER name_list | FUNCTION function_with_argtypes_list | PROCEDURE function_with_argtypes_list | ROUTINE function_with_argtypes_list | DATABASE name_list | DOMAIN_P any_name_list | LANGUAGE name_list | LARGE_P OBJECT_P numericonly_list | SCHEMA name_list | TABLESPACE name_list | TYPE_P any_name_list | ALL TABLES IN_P SCHEMA name_list | ALL SEQUENCES IN_P SCHEMA name_list | ALL FUNCTIONS IN_P SCHEMA name_list | ALL PROCEDURES IN_P SCHEMA name_list | ALL ROUTINES IN_P SCHEMA name_list ; grantee_list : grantee (COMMA grantee)* ; grantee : rolespec | GROUP_P rolespec ; opt_grant_grant_option : WITH GRANT OPTION | ; grantrolestmt : GRANT privilege_list TO role_list opt_grant_admin_option opt_granted_by ; revokerolestmt : REVOKE privilege_list FROM role_list opt_granted_by opt_drop_behavior | REVOKE ADMIN OPTION FOR privilege_list FROM role_list opt_granted_by opt_drop_behavior ; opt_grant_admin_option : WITH ADMIN OPTION | ; opt_granted_by : GRANTED BY rolespec | ; alterdefaultprivilegesstmt : ALTER DEFAULT PRIVILEGES defacloptionlist defaclaction ; defacloptionlist : defacloption* ; defacloption : IN_P SCHEMA name_list | FOR ROLE role_list | FOR USER role_list ; defaclaction : GRANT privileges ON defacl_privilege_target TO grantee_list opt_grant_grant_option | REVOKE privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior | REVOKE GRANT OPTION FOR privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior ; defacl_privilege_target : TABLES | FUNCTIONS | ROUTINES | SEQUENCES | TYPES_P | SCHEMAS ; //create index indexstmt : CREATE opt_unique INDEX opt_concurrently opt_index_name ON relation_expr access_method_clause OPEN_PAREN index_params CLOSE_PAREN opt_include opt_reloptions opttablespace where_clause | CREATE opt_unique INDEX opt_concurrently IF_P NOT EXISTS name ON relation_expr access_method_clause OPEN_PAREN index_params CLOSE_PAREN opt_include opt_reloptions opttablespace where_clause ; opt_unique : UNIQUE | ; opt_concurrently : CONCURRENTLY | ; opt_index_name : name | ; access_method_clause : USING name | ; index_params : index_elem (COMMA index_elem)* ; index_elem_options : opt_collate opt_class opt_asc_desc opt_nulls_order | opt_collate any_name reloptions opt_asc_desc opt_nulls_order ; index_elem : colid index_elem_options | func_expr_windowless index_elem_options | OPEN_PAREN a_expr CLOSE_PAREN index_elem_options ; opt_include : INCLUDE OPEN_PAREN index_including_params CLOSE_PAREN | ; index_including_params : index_elem (COMMA index_elem)* ; opt_collate : COLLATE any_name | ; opt_class : any_name | ; opt_asc_desc : ASC | DESC | ; //TOD NULLS_LA was used opt_nulls_order : NULLS_P FIRST_P | NULLS_P LAST_P | ; createfunctionstmt : CREATE opt_or_replace (FUNCTION | PROCEDURE) func_name func_args_with_defaults ( RETURNS (func_return | TABLE OPEN_PAREN table_func_column_list CLOSE_PAREN) )? createfunc_opt_list ; opt_or_replace : OR REPLACE | ; func_args : OPEN_PAREN func_args_list? CLOSE_PAREN ; func_args_list : func_arg (COMMA func_arg)* ; function_with_argtypes_list : function_with_argtypes (COMMA function_with_argtypes)* ; function_with_argtypes : func_name func_args | type_func_name_keyword | colid indirection? ; func_args_with_defaults : OPEN_PAREN func_args_with_defaults_list? CLOSE_PAREN ; func_args_with_defaults_list : func_arg_with_default (COMMA func_arg_with_default)* ; func_arg : arg_class param_name? func_type | param_name arg_class? func_type | func_type ; arg_class : IN_P OUT_P? | OUT_P | INOUT | VARIADIC ; param_name : type_function_name | builtin_function_name | LEFT | RIGHT ; func_return : func_type ; func_type : typename | SETOF? (builtin_function_name | type_function_name | LEFT | RIGHT) attrs PERCENT TYPE_P ; func_arg_with_default : func_arg ((DEFAULT | EQUAL) a_expr)? ; aggr_arg : func_arg ; aggr_args : OPEN_PAREN (STAR | aggr_args_list | ORDER BY aggr_args_list | aggr_args_list ORDER BY aggr_args_list) CLOSE_PAREN ; aggr_args_list : aggr_arg (COMMA aggr_arg)* ; aggregate_with_argtypes : func_name aggr_args ; aggregate_with_argtypes_list : aggregate_with_argtypes (COMMA aggregate_with_argtypes)* ; createfunc_opt_list : createfunc_opt_item+ { ParseRoutineBody(_localctx); } // | createfunc_opt_list createfunc_opt_item ; common_func_opt_item : CALLED ON NULL_P INPUT_P | RETURNS NULL_P ON NULL_P INPUT_P | STRICT_P | IMMUTABLE | STABLE | VOLATILE | EXTERNAL SECURITY DEFINER | EXTERNAL SECURITY INVOKER | SECURITY DEFINER | SECURITY INVOKER | LEAKPROOF | NOT LEAKPROOF | SHIPPABLE | NOT SHIPPABLE | FENCED | NOT FENCED | PACKAGE | COST numericonly | ROWS numericonly | SUPPORT any_name | functionsetresetclause | PARALLEL colid ; createfunc_opt_item : AS func_as | LANGUAGE nonreservedword_or_sconst | TRANSFORM transform_type_list | WINDOW | common_func_opt_item ; //https://www.postgresql.org/docs/9.1/sql-createfunction.html // | AS 'definition' // | AS 'obj_file', 'link_symbol' func_as locals[ParserRuleContext Definition] : /* |AS 'definition'*/ def = sconst /*| AS 'obj_file', 'link_symbol'*/ | sconst COMMA sconst ; transform_type_list :FOR TYPE_P typename (COMMA FOR TYPE_P typename)* ; opt_definition : WITH definition | ; table_func_column : param_name func_type ; table_func_column_list : table_func_column (COMMA table_func_column)* ; alterfunctionstmt : ALTER (FUNCTION | PROCEDURE | ROUTINE) function_with_argtypes alterfunc_opt_list opt_restrict ; alterfunc_opt_list : common_func_opt_item+ ; opt_restrict : RESTRICT | ; removefuncstmt : DROP FUNCTION function_with_argtypes_list opt_drop_behavior | DROP FUNCTION IF_P EXISTS function_with_argtypes_list opt_drop_behavior | DROP PROCEDURE function_with_argtypes_list opt_drop_behavior | DROP PROCEDURE IF_P EXISTS function_with_argtypes_list opt_drop_behavior | DROP ROUTINE function_with_argtypes_list opt_drop_behavior | DROP ROUTINE IF_P EXISTS function_with_argtypes_list opt_drop_behavior ; removeaggrstmt : DROP AGGREGATE aggregate_with_argtypes_list opt_drop_behavior | DROP AGGREGATE IF_P EXISTS aggregate_with_argtypes_list opt_drop_behavior ; removeoperstmt : DROP OPERATOR operator_with_argtypes_list opt_drop_behavior | DROP OPERATOR IF_P EXISTS operator_with_argtypes_list opt_drop_behavior ; oper_argtypes : OPEN_PAREN typename CLOSE_PAREN | OPEN_PAREN typename COMMA typename CLOSE_PAREN | OPEN_PAREN NONE COMMA typename CLOSE_PAREN | OPEN_PAREN typename COMMA NONE CLOSE_PAREN ; any_operator : (colid DOT)* all_op ; operator_with_argtypes_list : operator_with_argtypes (COMMA operator_with_argtypes)* ; operator_with_argtypes : any_operator oper_argtypes ; dostmt : DO dostmt_opt_list ; dostmt_opt_list : dostmt_opt_item+ ; dostmt_opt_item : sconst | LANGUAGE nonreservedword_or_sconst ; createcaststmt : CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITH FUNCTION function_with_argtypes cast_context | CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITHOUT FUNCTION cast_context | CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITH INOUT cast_context ; cast_context : AS IMPLICIT_P | AS ASSIGNMENT | ; dropcaststmt : DROP CAST opt_if_exists OPEN_PAREN typename AS typename CLOSE_PAREN opt_drop_behavior ; opt_if_exists : IF_P EXISTS | ; createtransformstmt : CREATE opt_or_replace TRANSFORM FOR typename LANGUAGE name OPEN_PAREN transform_element_list CLOSE_PAREN ; transform_element_list : FROM SQL_P WITH FUNCTION function_with_argtypes COMMA TO SQL_P WITH FUNCTION function_with_argtypes | TO SQL_P WITH FUNCTION function_with_argtypes COMMA FROM SQL_P WITH FUNCTION function_with_argtypes | FROM SQL_P WITH FUNCTION function_with_argtypes | TO SQL_P WITH FUNCTION function_with_argtypes ; droptransformstmt : DROP TRANSFORM opt_if_exists FOR typename LANGUAGE name opt_drop_behavior ; reindexstmt : REINDEX reindex_target_type opt_concurrently qualified_name | REINDEX reindex_target_multitable opt_concurrently name | REINDEX OPEN_PAREN reindex_option_list CLOSE_PAREN reindex_target_type opt_concurrently qualified_name | REINDEX OPEN_PAREN reindex_option_list CLOSE_PAREN reindex_target_multitable opt_concurrently name ; reindex_target_type : INDEX | TABLE | SCHEMA | DATABASE | SYSTEM_P ; reindex_target_multitable : SCHEMA | SYSTEM_P | DATABASE ; reindex_option_list : reindex_option_elem (COMMA reindex_option_elem)* ; reindex_option_elem : VERBOSE | TABLESPACE | CONCURRENTLY ; altertblspcstmt : ALTER TABLESPACE name SET reloptions | ALTER TABLESPACE name RESET reloptions ; renamestmt : ALTER AGGREGATE aggregate_with_argtypes RENAME TO name | ALTER COLLATION any_name RENAME TO name | ALTER CONVERSION_P any_name RENAME TO name | ALTER DATABASE name RENAME TO name | ALTER DOMAIN_P any_name RENAME TO name | ALTER DOMAIN_P any_name RENAME CONSTRAINT name TO name | ALTER FOREIGN DATA_P WRAPPER name RENAME TO name | ALTER FUNCTION function_with_argtypes RENAME TO name | ALTER GROUP_P roleid RENAME TO roleid | ALTER opt_procedural LANGUAGE name RENAME TO name | ALTER OPERATOR CLASS any_name USING name RENAME TO name | ALTER OPERATOR FAMILY any_name USING name RENAME TO name | ALTER POLICY name ON qualified_name RENAME TO name | ALTER POLICY IF_P EXISTS name ON qualified_name RENAME TO name | ALTER PROCEDURE function_with_argtypes RENAME TO name | ALTER PUBLICATION name RENAME TO name | ALTER ROUTINE function_with_argtypes RENAME TO name | ALTER SCHEMA name RENAME TO name | ALTER SERVER name RENAME TO name | ALTER SUBSCRIPTION name RENAME TO name | ALTER TABLE relation_expr RENAME TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME TO name | ALTER SEQUENCE qualified_name RENAME TO name | ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name | ALTER VIEW qualified_name RENAME TO name | ALTER VIEW IF_P EXISTS qualified_name RENAME TO name | ALTER MATERIALIZED VIEW qualified_name RENAME TO name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name | ALTER INDEX qualified_name RENAME TO name | ALTER INDEX IF_P EXISTS qualified_name RENAME TO name | ALTER FOREIGN TABLE relation_expr RENAME TO name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME TO name | ALTER TABLE relation_expr RENAME opt_column name TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name | ALTER VIEW qualified_name RENAME opt_column name TO name | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name | ALTER TABLE relation_expr RENAME CONSTRAINT name TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name | ALTER FOREIGN TABLE relation_expr RENAME opt_column name TO name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name | ALTER RULE name ON qualified_name RENAME TO name | ALTER TRIGGER name ON qualified_name RENAME TO name | ALTER EVENT TRIGGER name RENAME TO name | ALTER ROLE roleid RENAME TO roleid | ALTER USER roleid RENAME TO roleid | ALTER TABLESPACE name RENAME TO name | ALTER STATISTICS any_name RENAME TO name | ALTER TEXT_P SEARCH PARSER any_name RENAME TO name | ALTER TEXT_P SEARCH DICTIONARY any_name RENAME TO name | ALTER TEXT_P SEARCH TEMPLATE any_name RENAME TO name | ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name | ALTER TYPE_P any_name RENAME TO name | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior ; opt_column : COLUMN | ; opt_set_data : SET DATA_P | ; alterobjectdependsstmt : ALTER FUNCTION function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER TRIGGER name ON qualified_name opt_no DEPENDS ON EXTENSION name | ALTER MATERIALIZED VIEW qualified_name opt_no DEPENDS ON EXTENSION name | ALTER INDEX qualified_name opt_no DEPENDS ON EXTENSION name ; opt_no : NO | ; alterobjectschemastmt : ALTER AGGREGATE aggregate_with_argtypes SET SCHEMA name | ALTER COLLATION any_name SET SCHEMA name | ALTER CONVERSION_P any_name SET SCHEMA name | ALTER DOMAIN_P any_name SET SCHEMA name | ALTER EXTENSION name SET SCHEMA name | ALTER FUNCTION function_with_argtypes SET SCHEMA name | ALTER OPERATOR operator_with_argtypes SET SCHEMA name | ALTER OPERATOR CLASS any_name USING name SET SCHEMA name | ALTER OPERATOR FAMILY any_name USING name SET SCHEMA name | ALTER PROCEDURE function_with_argtypes SET SCHEMA name | ALTER ROUTINE function_with_argtypes SET SCHEMA name | ALTER TABLE relation_expr SET SCHEMA name | ALTER TABLE IF_P EXISTS relation_expr SET SCHEMA name | ALTER STATISTICS any_name SET SCHEMA name | ALTER TEXT_P SEARCH PARSER any_name SET SCHEMA name | ALTER TEXT_P SEARCH DICTIONARY any_name SET SCHEMA name | ALTER TEXT_P SEARCH TEMPLATE any_name SET SCHEMA name | ALTER TEXT_P SEARCH CONFIGURATION any_name SET SCHEMA name | ALTER SEQUENCE qualified_name SET SCHEMA name | ALTER SEQUENCE IF_P EXISTS qualified_name SET SCHEMA name | ALTER VIEW qualified_name SET SCHEMA name | ALTER VIEW IF_P EXISTS qualified_name SET SCHEMA name | ALTER MATERIALIZED VIEW qualified_name SET SCHEMA name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET SCHEMA name | ALTER FOREIGN TABLE relation_expr SET SCHEMA name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr SET SCHEMA name | ALTER TYPE_P any_name SET SCHEMA name ; alteroperatorstmt : ALTER OPERATOR operator_with_argtypes SET OPEN_PAREN operator_def_list CLOSE_PAREN ; operator_def_list : operator_def_elem (COMMA operator_def_elem)* ; operator_def_elem : collabel EQUAL NONE | collabel EQUAL operator_def_arg ; operator_def_arg : func_type | reserved_keyword | qual_all_op | numericonly | sconst ; altertypestmt : ALTER TYPE_P any_name SET OPEN_PAREN operator_def_list CLOSE_PAREN ; alterownerstmt : ALTER AGGREGATE aggregate_with_argtypes OWNER TO rolespec | ALTER COLLATION any_name OWNER TO rolespec | ALTER CONVERSION_P any_name OWNER TO rolespec | ALTER DATABASE name OWNER TO rolespec | ALTER DOMAIN_P any_name OWNER TO rolespec | ALTER FUNCTION function_with_argtypes OWNER TO rolespec | ALTER opt_procedural LANGUAGE name OWNER TO rolespec | ALTER LARGE_P OBJECT_P numericonly OWNER TO rolespec | ALTER OPERATOR operator_with_argtypes OWNER TO rolespec | ALTER OPERATOR CLASS any_name USING name OWNER TO rolespec | ALTER OPERATOR FAMILY any_name USING name OWNER TO rolespec | ALTER PROCEDURE function_with_argtypes OWNER TO rolespec | ALTER ROUTINE function_with_argtypes OWNER TO rolespec | ALTER SCHEMA name OWNER TO rolespec | ALTER TYPE_P any_name OWNER TO rolespec | ALTER TABLESPACE name OWNER TO rolespec | ALTER STATISTICS any_name OWNER TO rolespec | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO rolespec | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO rolespec | ALTER FOREIGN DATA_P WRAPPER name OWNER TO rolespec | ALTER SERVER name OWNER TO rolespec | ALTER EVENT TRIGGER name OWNER TO rolespec | ALTER PUBLICATION name OWNER TO rolespec | ALTER SUBSCRIPTION name OWNER TO rolespec ; createpublicationstmt : CREATE PUBLICATION name opt_publication_for_tables opt_definition ; opt_publication_for_tables : publication_for_tables | ; publication_for_tables : FOR TABLE relation_expr_list | FOR ALL TABLES ; alterpublicationstmt : ALTER PUBLICATION name SET definition | ALTER PUBLICATION name ADD_P TABLE relation_expr_list | ALTER PUBLICATION name SET TABLE relation_expr_list | ALTER PUBLICATION name DROP TABLE relation_expr_list ; createsubscriptionstmt : CREATE SUBSCRIPTION name CONNECTION sconst PUBLICATION publication_name_list opt_definition ; publication_name_list : publication_name_item (COMMA publication_name_item)* ; publication_name_item : collabel ; altersubscriptionstmt : ALTER SUBSCRIPTION name SET definition | ALTER SUBSCRIPTION name CONNECTION sconst | ALTER SUBSCRIPTION name REFRESH PUBLICATION opt_definition | ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list opt_definition | ALTER SUBSCRIPTION name ENABLE_P | ALTER SUBSCRIPTION name DISABLE_P ; dropsubscriptionstmt : DROP SUBSCRIPTION name opt_drop_behavior | DROP SUBSCRIPTION IF_P EXISTS name opt_drop_behavior ; rulestmt : CREATE opt_or_replace RULE name AS ON event TO qualified_name where_clause DO opt_instead ruleactionlist ; ruleactionlist : NOTHING | ruleactionstmt | OPEN_PAREN ruleactionmulti CLOSE_PAREN ; ruleactionmulti : ruleactionstmtOrEmpty (SEMI ruleactionstmtOrEmpty)* ; ruleactionstmt : selectstmt | insertstmt | updatestmt | deletestmt | notifystmt ; ruleactionstmtOrEmpty : ruleactionstmt | ; event : SELECT | UPDATE | DELETE_P | INSERT ; opt_instead : INSTEAD | ALSO | ; notifystmt : NOTIFY colid notify_payload ; notify_payload : COMMA sconst | ; listenstmt : LISTEN colid ; unlistenstmt : UNLISTEN colid | UNLISTEN STAR ; transactionstmt : ABORT_P opt_transaction opt_transaction_chain | BEGIN_P opt_transaction transaction_mode_list_or_empty | START TRANSACTION transaction_mode_list_or_empty | COMMIT opt_transaction opt_transaction_chain | END_P opt_transaction opt_transaction_chain | ROLLBACK opt_transaction opt_transaction_chain | SAVEPOINT colid | RELEASE SAVEPOINT colid | RELEASE colid | ROLLBACK opt_transaction TO SAVEPOINT colid | ROLLBACK opt_transaction TO colid | PREPARE TRANSACTION sconst | COMMIT PREPARED sconst | ROLLBACK PREPARED sconst ; opt_transaction : WORK | TRANSACTION | ; transaction_mode_item : ISOLATION LEVEL iso_level | READ ONLY | READ WRITE | DEFERRABLE | NOT DEFERRABLE ; transaction_mode_list : transaction_mode_item (COMMA? transaction_mode_item)* ; transaction_mode_list_or_empty : transaction_mode_list | ; opt_transaction_chain : AND NO? CHAIN | ; viewstmt : CREATE (OR REPLACE)? opttemp ( VIEW qualified_name opt_column_list opt_reloptions | RECURSIVE VIEW qualified_name OPEN_PAREN columnlist CLOSE_PAREN opt_reloptions ) AS selectstmt opt_check_option ; opt_check_option : WITH (CASCADED | LOCAL)? CHECK OPTION | ; loadstmt : LOAD file_name ; createdbstmt : CREATE DATABASE name opt_with createdb_opt_list ; createdb_opt_list : createdb_opt_items | ; createdb_opt_items : createdb_opt_item+ ; createdb_opt_item : createdb_opt_name opt_equal (signediconst | opt_boolean_or_string | DEFAULT) ; createdb_opt_name : identifier | CONNECTION LIMIT | ENCODING | LOCATION | OWNER | TABLESPACE | TEMPLATE ; opt_equal : EQUAL | ; alterdatabasestmt : ALTER DATABASE name (WITH createdb_opt_list | createdb_opt_list | SET TABLESPACE name) ; alterdatabasesetstmt : ALTER DATABASE name setresetclause ; dropdbstmt : DROP DATABASE (IF_P EXISTS)? name (opt_with OPEN_PAREN drop_option_list CLOSE_PAREN)? ; drop_option_list : drop_option (COMMA drop_option)* ; drop_option : FORCE ; altercollationstmt : ALTER COLLATION any_name REFRESH VERSION_P ; altersystemstmt : ALTER SYSTEM_P (SET | RESET) generic_set ; createdomainstmt : CREATE DOMAIN_P any_name opt_as typename colquallist ; alterdomainstmt : ALTER DOMAIN_P any_name (alter_column_default | DROP NOT NULL_P | SET NOT NULL_P | ADD_P tableconstraint | DROP CONSTRAINT (IF_P EXISTS)? name opt_drop_behavior | VALIDATE CONSTRAINT name) ; opt_as : AS | ; altertsdictionarystmt : ALTER TEXT_P SEARCH DICTIONARY any_name definition ; altertsconfigurationstmt : ALTER TEXT_P SEARCH CONFIGURATION any_name ADD_P MAPPING FOR name_list any_with any_name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list any_with any_name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING REPLACE any_name any_with any_name | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list REPLACE any_name any_with any_name | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING FOR name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING IF_P EXISTS FOR name_list ; any_with : WITH //TODO // | WITH_LA ; createconversionstmt : CREATE opt_default CONVERSION_P any_name FOR sconst TO sconst FROM any_name ; clusterstmt : CLUSTER opt_verbose qualified_name cluster_index_specification | CLUSTER opt_verbose | CLUSTER opt_verbose name ON qualified_name ; cluster_index_specification : USING name | ; vacuumstmt : VACUUM opt_full opt_freeze opt_verbose opt_analyze opt_vacuum_relation_list | VACUUM OPEN_PAREN vac_analyze_option_list CLOSE_PAREN opt_vacuum_relation_list ; analyzestmt : analyze_keyword opt_verbose opt_vacuum_relation_list | analyze_keyword OPEN_PAREN vac_analyze_option_list CLOSE_PAREN opt_vacuum_relation_list ; vac_analyze_option_list : vac_analyze_option_elem (COMMA vac_analyze_option_elem)* ; analyze_keyword : ANALYZE | ANALYSE ; vac_analyze_option_elem : vac_analyze_option_name vac_analyze_option_arg ; vac_analyze_option_name : nonreservedword | analyze_keyword ; vac_analyze_option_arg : opt_boolean_or_string | numericonly | ; opt_analyze : analyze_keyword | ; opt_verbose : VERBOSE | ; opt_full : FULL | ; opt_freeze : FREEZE | ; opt_name_list : OPEN_PAREN name_list CLOSE_PAREN | ; vacuum_relation : qualified_name opt_name_list ; vacuum_relation_list : vacuum_relation (COMMA vacuum_relation)* ; opt_vacuum_relation_list : vacuum_relation_list | ; explainstmt : EXPLAIN explainablestmt | EXPLAIN analyze_keyword opt_verbose explainablestmt | EXPLAIN VERBOSE explainablestmt | EXPLAIN OPEN_PAREN explain_option_list CLOSE_PAREN explainablestmt ; explainablestmt : selectstmt | insertstmt | updatestmt | deletestmt | declarecursorstmt | createasstmt | creatematviewstmt | refreshmatviewstmt | executestmt ; explain_option_list : explain_option_elem (COMMA explain_option_elem)* ; explain_option_elem : explain_option_name explain_option_arg ; explain_option_name : nonreservedword | analyze_keyword ; explain_option_arg : opt_boolean_or_string | numericonly | ; preparestmt : PREPARE name prep_type_clause AS preparablestmt ; prep_type_clause : OPEN_PAREN type_list CLOSE_PAREN | ; preparablestmt : selectstmt | insertstmt | updatestmt | deletestmt ; executestmt : EXECUTE name execute_param_clause | CREATE opttemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data | CREATE opttemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data ; execute_param_clause : OPEN_PAREN expr_list CLOSE_PAREN | ; deallocatestmt : DEALLOCATE name | DEALLOCATE PREPARE name | DEALLOCATE ALL | DEALLOCATE PREPARE ALL ; insertstmt : opt_with_clause INSERT INTO insert_target insert_rest opt_on_conflict returning_clause ; insert_target : qualified_name (AS colid)? ; insert_rest : selectstmt | OVERRIDING override_kind VALUE_P selectstmt | OPEN_PAREN insert_column_list CLOSE_PAREN (OVERRIDING override_kind VALUE_P)? selectstmt | DEFAULT VALUES ; override_kind : USER | SYSTEM_P ; insert_column_list : insert_column_item (COMMA insert_column_item)* ; insert_column_item : colid opt_indirection ; opt_on_conflict : ON CONFLICT opt_conf_expr DO (UPDATE SET set_clause_list where_clause | NOTHING) | ; opt_conf_expr : OPEN_PAREN index_params CLOSE_PAREN where_clause | ON CONSTRAINT name | ; returning_clause : RETURNING target_list | ; // https://www.postgresql.org/docs/current/sql-merge.html mergestmt : MERGE INTO? qualified_name alias_clause? USING (select_with_parens|qualified_name) alias_clause? ON a_expr (merge_insert_clause merge_update_clause? | merge_update_clause merge_insert_clause?) merge_delete_clause? ; merge_insert_clause : WHEN NOT MATCHED (AND a_expr)? THEN? INSERT (OPEN_PAREN insert_column_list CLOSE_PAREN)? values_clause ; merge_update_clause : WHEN MATCHED (AND a_expr)? THEN? UPDATE SET set_clause_list ; merge_delete_clause : WHEN MATCHED THEN? DELETE_P ; deletestmt : opt_with_clause DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause ; using_clause : USING from_list | ; lockstmt : LOCK_P opt_table relation_expr_list opt_lock opt_nowait ; opt_lock : IN_P lock_type MODE | ; lock_type : ACCESS (SHARE | EXCLUSIVE) | ROW (SHARE | EXCLUSIVE) | SHARE (UPDATE EXCLUSIVE | ROW EXCLUSIVE)? | EXCLUSIVE ; opt_nowait : NOWAIT | ; opt_nowait_or_skip : NOWAIT | SKIP_P LOCKED | ; updatestmt : opt_with_clause UPDATE relation_expr_opt_alias SET set_clause_list from_clause where_or_current_clause returning_clause ; set_clause_list : set_clause (COMMA set_clause)* ; set_clause : set_target EQUAL a_expr | OPEN_PAREN set_target_list CLOSE_PAREN EQUAL a_expr ; set_target : colid opt_indirection ; set_target_list : set_target (COMMA set_target)* ; declarecursorstmt : DECLARE cursor_name cursor_options CURSOR opt_hold FOR selectstmt ; cursor_name : name ; cursor_options : (NO SCROLL | SCROLL | BINARY | INSENSITIVE)* ; opt_hold : | WITH HOLD | WITHOUT HOLD ; /* TODO: why select_with_parens alternative is needed at all? i guess it because original byson grammar can choose selectstmt(2)->select_with_parens on only OPEN_PARENT/SELECT kewords at the begining of statement; (select * from tab); parse can go through selectstmt( )->select_no_parens(1)->select_clause(2)->select_with_parens(1)->select_no_parens(1)->select_clause(1)->simple_select instead of selectstmt(1)->select_no_parens(1)->select_clause(2)->select_with_parens(1)->select_no_parens(1)->select_clause(1)->simple_select all standard tests passed on both variants */ selectstmt : select_no_parens | select_with_parens ; select_with_parens : OPEN_PAREN select_no_parens CLOSE_PAREN | OPEN_PAREN select_with_parens CLOSE_PAREN ; select_no_parens : select_clause opt_sort_clause (for_locking_clause opt_select_limit | select_limit opt_for_locking_clause)? | with_clause select_clause opt_sort_clause (for_locking_clause opt_select_limit | select_limit opt_for_locking_clause)? ; select_clause : simple_select_intersect ((UNION | EXCEPT) all_or_distinct simple_select_intersect)* ; simple_select_intersect : simple_select_pramary (INTERSECT all_or_distinct simple_select_pramary)* ; simple_select_pramary : ( SELECT (opt_all_clause into_clause opt_target_list | distinct_clause target_list) into_clause from_clause where_clause group_clause having_clause window_clause ) | values_clause | TABLE relation_expr | select_with_parens ; with_clause : WITH RECURSIVE? cte_list ; cte_list : common_table_expr (COMMA common_table_expr)* ; common_table_expr : name opt_name_list AS opt_materialized OPEN_PAREN preparablestmt CLOSE_PAREN ; opt_materialized : MATERIALIZED | NOT MATERIALIZED | ; opt_with_clause : with_clause | ; into_clause : INTO (opt_strict opttempTableName | into_target) | ; opt_strict : | STRICT_P ; opttempTableName : (LOCAL|GLOBAL)? (TEMPORARY | TEMP) opt_table qualified_name | UNLOGGED opt_table qualified_name | TABLE qualified_name | qualified_name ; opt_table : TABLE | ; all_or_distinct : ALL | DISTINCT | ; distinct_clause : DISTINCT (ON OPEN_PAREN expr_list CLOSE_PAREN)? ; opt_all_clause : ALL | ; opt_sort_clause : sort_clause | ; sort_clause : ORDER BY sortby_list ; sortby_list : sortby (COMMA sortby)* ; sortby : a_expr (USING qual_all_op | opt_asc_desc) opt_nulls_order ; select_limit : limit_clause offset_clause? | offset_clause limit_clause? ; opt_select_limit : select_limit | ; limit_clause : LIMIT select_limit_value (COMMA select_offset_value)? | FETCH first_or_next (select_fetch_first_value row_or_rows (ONLY | WITH TIES) | row_or_rows (ONLY | WITH TIES)) ; offset_clause : OFFSET (select_offset_value | select_fetch_first_value row_or_rows) ; select_limit_value : a_expr | ALL ; select_offset_value : a_expr ; select_fetch_first_value : c_expr | PLUS i_or_f_const | MINUS i_or_f_const ; i_or_f_const : iconst | fconst ; row_or_rows : ROW | ROWS ; first_or_next : FIRST_P | NEXT ; group_clause : GROUP_P BY group_by_list | ; group_by_list : group_by_item (COMMA group_by_item)* ; group_by_item : empty_grouping_set | cube_clause | rollup_clause | grouping_sets_clause | a_expr ; empty_grouping_set : OPEN_PAREN CLOSE_PAREN ; rollup_clause : ROLLUP OPEN_PAREN expr_list CLOSE_PAREN ; cube_clause : CUBE OPEN_PAREN expr_list CLOSE_PAREN ; grouping_sets_clause : GROUPING SETS OPEN_PAREN group_by_list CLOSE_PAREN ; having_clause : HAVING a_expr | ; for_locking_clause : for_locking_items | FOR READ ONLY ; opt_for_locking_clause : for_locking_clause | ; for_locking_items : for_locking_item+ ; for_locking_item : for_locking_strength locked_rels_list opt_nowait_or_skip ; for_locking_strength : FOR ((NO KEY)? UPDATE | KEY? SHARE) ; locked_rels_list : OF qualified_name_list | ; values_clause : VALUES OPEN_PAREN expr_list CLOSE_PAREN (COMMA OPEN_PAREN expr_list CLOSE_PAREN)* ; from_clause : FROM from_list | ; from_list : non_ansi_join | table_ref (COMMA table_ref)* ; non_ansi_join : table_ref (COMMA table_ref)+ ; table_ref : (relation_expr opt_alias_clause tablesample_clause? | func_table func_alias_clause | xmltable opt_alias_clause | select_with_parens opt_alias_clause | LATERAL_P ( xmltable opt_alias_clause | func_table func_alias_clause | select_with_parens opt_alias_clause ) | OPEN_PAREN table_ref ( CROSS JOIN table_ref | NATURAL join_type? JOIN table_ref | join_type? JOIN table_ref join_qual )? CLOSE_PAREN opt_alias_clause ) (CROSS JOIN table_ref | NATURAL join_type? JOIN table_ref | join_type? JOIN table_ref join_qual)* ; alias_clause : AS? colid (OPEN_PAREN name_list CLOSE_PAREN)? ; opt_alias_clause : table_alias_clause | ; table_alias_clause : AS? table_alias (OPEN_PAREN name_list CLOSE_PAREN)? ; func_alias_clause : alias_clause | (AS colid? | colid) OPEN_PAREN tablefuncelementlist CLOSE_PAREN | ; join_type : (FULL | LEFT | RIGHT | INNER_P) OUTER_P? ; join_qual : USING OPEN_PAREN name_list CLOSE_PAREN | ON a_expr ; relation_expr : qualified_name STAR? | ONLY (qualified_name | OPEN_PAREN qualified_name CLOSE_PAREN) ; relation_expr_list : relation_expr (COMMA relation_expr)* ; relation_expr_opt_alias : relation_expr (AS? colid)? ; tablesample_clause : TABLESAMPLE func_name OPEN_PAREN expr_list CLOSE_PAREN opt_repeatable_clause ; opt_repeatable_clause : REPEATABLE OPEN_PAREN a_expr CLOSE_PAREN | ; func_table : func_expr_windowless opt_ordinality | ROWS FROM OPEN_PAREN rowsfrom_list CLOSE_PAREN opt_ordinality ; rowsfrom_item : func_expr_windowless opt_col_def_list ; rowsfrom_list : rowsfrom_item (COMMA rowsfrom_item)* ; opt_col_def_list : AS OPEN_PAREN tablefuncelementlist CLOSE_PAREN | ; //TODO WITH_LA was used opt_ordinality : WITH ORDINALITY | ; where_clause : WHERE a_expr | ; where_or_current_clause : WHERE (CURRENT_P OF cursor_name | a_expr) | ; opttablefuncelementlist : tablefuncelementlist | ; tablefuncelementlist : tablefuncelement (COMMA tablefuncelement)* ; tablefuncelement : colid typename opt_collate_clause ; xmltable : XMLTABLE OPEN_PAREN (c_expr xmlexists_argument COLUMNS xmltable_column_list | XMLNAMESPACES OPEN_PAREN xml_namespace_list CLOSE_PAREN COMMA c_expr xmlexists_argument COLUMNS xmltable_column_list) CLOSE_PAREN ; xmltable_column_list : xmltable_column_el (COMMA xmltable_column_el)* ; xmltable_column_el : colid (typename xmltable_column_option_list? | FOR ORDINALITY) ; xmltable_column_option_list : xmltable_column_option_el+ ; xmltable_column_option_el : DEFAULT a_expr | identifier a_expr | NOT NULL_P | NULL_P ; xml_namespace_list : xml_namespace_el (COMMA xml_namespace_el)* ; xml_namespace_el : b_expr AS collabel | DEFAULT b_expr ; typename : SETOF? simpletypename (opt_array_bounds | ARRAY (OPEN_BRACKET iconst CLOSE_BRACKET)?) | qualified_name PERCENT (ROWTYPE | TYPE_P) ; opt_array_bounds : (OPEN_BRACKET iconst? CLOSE_BRACKET)* ; simpletypename : generictype | numeric | bit | character | constdatetime | constinterval (opt_interval | OPEN_PAREN iconst CLOSE_PAREN) ; consttypename : numeric | constbit | constcharacter | constdatetime ; generictype : (builtin_function_name | type_function_name | LEFT | RIGHT) attrs? opt_type_modifiers ; opt_type_modifiers : OPEN_PAREN expr_list CLOSE_PAREN | ; numeric : INT_P | INTEGER | SMALLINT | BIGINT | REAL | FLOAT_P opt_float | DOUBLE_P PRECISION | DECIMAL_P opt_type_modifiers | DEC opt_type_modifiers | NUMERIC opt_type_modifiers | BOOLEAN_P ; opt_float : OPEN_PAREN iconst CLOSE_PAREN | ; //todo: merge alts bit : bitwithlength | bitwithoutlength ; constbit : bitwithlength | bitwithoutlength ; bitwithlength : BIT opt_varying OPEN_PAREN expr_list CLOSE_PAREN ; bitwithoutlength : BIT opt_varying ; character : character_c (OPEN_PAREN iconst CLOSE_PAREN)? ; constcharacter : character_c (OPEN_PAREN iconst CLOSE_PAREN)? ; character_c : (CHARACTER | CHAR_P | NCHAR) opt_varying | VARCHAR | NATIONAL (CHARACTER | CHAR_P) opt_varying ; opt_varying : VARYING | ; constdatetime : (TIMESTAMP | TIME) (OPEN_PAREN iconst CLOSE_PAREN)? opt_timezone ; constinterval : INTERVAL ; //TODO with_la was used opt_timezone : WITH TIME ZONE | WITHOUT TIME ZONE | ; opt_interval : YEAR_P | MONTH_P | DAY_P | HOUR_P | MINUTE_P | interval_second | YEAR_P TO MONTH_P | DAY_P TO (HOUR_P | MINUTE_P | interval_second) | HOUR_P TO (MINUTE_P | interval_second) | MINUTE_P TO interval_second | ; interval_second : SECOND_P (OPEN_PAREN iconst CLOSE_PAREN)? ; opt_escape : ESCAPE a_expr | ; //precendence accroding to Table 4.2. Operator Precedence (highest to lowest) //https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-PRECEDENCE /* original version of a_expr, for info a_expr: c_expr //:: left PostgreSQL-style typecast | a_expr TYPECAST typename -- 1 | a_expr COLLATE any_name -- 2 | a_expr AT TIME ZONE a_expr-- 3 //right unary plus, unary minus | (PLUS| MINUS) a_expr -- 4 //left exponentiation | a_expr CARET a_expr -- 5 //left multiplication, division, modulo | a_expr (STAR | SLASH | PERCENT) a_expr -- 6 //left addition, subtraction | a_expr (PLUS | MINUS) a_expr -- 7 //left all other native and user-defined operators | a_expr qual_op a_expr -- 8 | qual_op a_expr -- 9 //range containment, set membership, string matching BETWEEN IN LIKE ILIKE SIMILAR | a_expr NOT? (LIKE|ILIKE|SIMILAR TO|(BETWEEN SYMMETRIC?)) a_expr opt_escape -- 10 //< > = <= >= <> comparison operators | a_expr (LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) a_expr -- 11 //IS ISNULL NOTNULL IS TRUE, IS FALSE, IS NULL, IS DISTINCT FROM, etc | a_expr IS NOT? ( NULL_P |TRUE_P |FALSE_P |UNKNOWN |DISTINCT FROM a_expr |OF OPEN_PAREN type_list CLOSE_PAREN |DOCUMENT_P |unicode_normal_form? NORMALIZED ) -- 12 | a_expr (ISNULL|NOTNULL) -- 13 | row OVERLAPS row -- 14 //NOT right logical negation | NOT a_expr -- 15 //AND left logical conjunction | a_expr AND a_expr -- 16 //OR left logical disjunction | a_expr OR a_expr -- 17 | a_expr (LESS_LESS|GREATER_GREATER) a_expr -- 18 | a_expr qual_op -- 19 | a_expr NOT? IN_P in_expr -- 20 | a_expr subquery_Op sub_type (select_with_parens|OPEN_PAREN a_expr CLOSE_PAREN) -- 21 | UNIQUE select_with_parens -- 22 | DEFAULT -- 23 ; */ a_expr : a_expr_qual ; /*23*/ /*moved to c_expr*/ /*22*/ /*moved to c_expr*/ /*19*/ a_expr_qual : a_expr_lessless qual_op? ; /*18*/ a_expr_lessless : a_expr_or ((LESS_LESS | GREATER_GREATER) a_expr_or)* ; /*17*/ a_expr_or : a_expr_and (OR a_expr_and)* ; /*16*/ a_expr_and : a_expr_between (AND a_expr_between)* ; /*21*/ a_expr_between : a_expr_in (NOT? BETWEEN SYMMETRIC? a_expr_in AND a_expr_in)? ; /*20*/ a_expr_in : a_expr_unary_not (NOT? IN_P in_expr)? ; /*15*/ a_expr_unary_not : NOT? a_expr_isnull ; /*14*/ /*moved to c_expr*/ /*13*/ a_expr_isnull : a_expr_is_not (ISNULL | NOTNULL)? ; /*12*/ a_expr_is_not : a_expr_compare (IS NOT? (NULL_P | TRUE_P | FALSE_P | UNKNOWN | DISTINCT FROM a_expr | OF OPEN_PAREN type_list CLOSE_PAREN | DOCUMENT_P | unicode_normal_form? NORMALIZED))? ; /*11*/ a_expr_compare : a_expr_like ((LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) a_expr_like |subquery_Op sub_type (select_with_parens | OPEN_PAREN a_expr CLOSE_PAREN) /*21*/ )? ; /*10*/ a_expr_like : a_expr_qual_op (NOT? (LIKE | ILIKE | SIMILAR TO) a_expr_qual_op opt_escape)? ; /* 8*/ a_expr_qual_op : a_expr_unary_qualop (qual_op a_expr_unary_qualop)* ; /* 9*/ a_expr_unary_qualop : qual_op? a_expr_add ; /* 7*/ a_expr_add : a_expr_mul ((MINUS | PLUS) a_expr_mul)* ; /* 6*/ a_expr_mul : a_expr_caret ((STAR | SLASH | PERCENT) a_expr_caret)* ; /* 5*/ a_expr_caret : a_expr_unary_sign (CARET a_expr)? ; /* 4*/ a_expr_unary_sign : (MINUS | PLUS)? a_expr_at_time_zone /* */ ; /* 3*/ a_expr_at_time_zone : a_expr_collate (AT TIME ZONE a_expr)? ; /* 2*/ a_expr_collate : a_expr_typecast (COLLATE any_name)? ; /* 1*/ a_expr_typecast : c_expr (TYPECAST typename)* ; b_expr : c_expr | b_expr TYPECAST typename //right unary plus, unary minus | (PLUS | MINUS) b_expr //^ left exponentiation | b_expr CARET b_expr //* / % left multiplication, division, modulo | b_expr (STAR | SLASH | PERCENT) b_expr //+ - left addition, subtraction | b_expr (PLUS | MINUS) b_expr //(any other operator) left all other native and user-defined operators | b_expr qual_op b_expr //< > = <= >= <> comparison operators | b_expr (LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) b_expr | qual_op b_expr | b_expr qual_op //S ISNULL NOTNULL IS TRUE, IS FALSE, IS NULL, IS DISTINCT FROM, etc | b_expr IS NOT? (DISTINCT FROM b_expr | OF OPEN_PAREN type_list CLOSE_PAREN | DOCUMENT_P) ; c_expr : EXISTS select_with_parens # c_expr_exists | ARRAY (select_with_parens | array_expr) # c_expr_expr | PARAM opt_indirection # c_expr_expr | GROUPING OPEN_PAREN expr_list CLOSE_PAREN # c_expr_expr | /*22*/ UNIQUE select_with_parens # c_expr_expr | columnref # c_expr_expr | aexprconst # c_expr_expr | plsqlvariablename # c_expr_expr | OPEN_PAREN a_expr_in_parens = a_expr CLOSE_PAREN opt_indirection # c_expr_expr | case_expr # c_expr_case | func_expr # c_expr_expr | select_with_parens indirection? # c_expr_expr | explicit_row # c_expr_expr | implicit_row # c_expr_expr | row OVERLAPS row /* 14*/ # c_expr_expr ; plsqlvariablename : PLSQLVARIABLENAME ; func_application : func_name OPEN_PAREN (func_arg_list (COMMA VARIADIC func_arg_expr)? opt_sort_clause | VARIADIC func_arg_expr opt_sort_clause | (ALL | DISTINCT) func_arg_list opt_sort_clause | STAR |) CLOSE_PAREN ; func_expr : func_application within_group_clause filter_clause over_clause | func_expr_common_subexpr ; func_expr_windowless : func_application | func_expr_common_subexpr ; func_expr_common_subexpr : COLLATION FOR OPEN_PAREN a_expr CLOSE_PAREN | CURRENT_DATE | CURRENT_TIME (OPEN_PAREN iconst CLOSE_PAREN)? | CURRENT_TIMESTAMP (OPEN_PAREN iconst CLOSE_PAREN)? | LOCALTIME (OPEN_PAREN iconst CLOSE_PAREN)? | LOCALTIMESTAMP (OPEN_PAREN iconst CLOSE_PAREN)? | CURRENT_ROLE | CURRENT_USER | SESSION_USER | USER | CURRENT_CATALOG | CURRENT_SCHEMA | CAST OPEN_PAREN a_expr AS typename CLOSE_PAREN | EXTRACT OPEN_PAREN extract_list CLOSE_PAREN | NORMALIZE OPEN_PAREN a_expr (COMMA unicode_normal_form)? CLOSE_PAREN | OVERLAY OPEN_PAREN overlay_list CLOSE_PAREN | POSITION OPEN_PAREN position_list CLOSE_PAREN | SUBSTRING OPEN_PAREN substr_list CLOSE_PAREN | TREAT OPEN_PAREN a_expr AS typename CLOSE_PAREN | TRIM OPEN_PAREN (BOTH | LEADING | TRAILING)? trim_list CLOSE_PAREN | NULLIF OPEN_PAREN a_expr COMMA a_expr CLOSE_PAREN | COALESCE OPEN_PAREN expr_list CLOSE_PAREN | GREATEST OPEN_PAREN expr_list CLOSE_PAREN | LEAST OPEN_PAREN expr_list CLOSE_PAREN | XMLCONCAT OPEN_PAREN expr_list CLOSE_PAREN | XMLELEMENT OPEN_PAREN NAME_P collabel (COMMA (xml_attributes | expr_list))? CLOSE_PAREN | XMLEXISTS OPEN_PAREN c_expr xmlexists_argument CLOSE_PAREN | XMLFOREST OPEN_PAREN xml_attribute_list CLOSE_PAREN | XMLPARSE OPEN_PAREN document_or_content a_expr xml_whitespace_option CLOSE_PAREN | XMLPI OPEN_PAREN NAME_P collabel (COMMA a_expr)? CLOSE_PAREN | XMLROOT OPEN_PAREN XML_P a_expr COMMA xml_root_version opt_xml_root_standalone CLOSE_PAREN | XMLSERIALIZE OPEN_PAREN document_or_content a_expr AS simpletypename CLOSE_PAREN ; xml_root_version : VERSION_P a_expr | VERSION_P NO VALUE_P ; opt_xml_root_standalone : COMMA STANDALONE_P YES_P | COMMA STANDALONE_P NO | COMMA STANDALONE_P NO VALUE_P | ; xml_attributes : XMLATTRIBUTES OPEN_PAREN xml_attribute_list CLOSE_PAREN ; xml_attribute_list : xml_attribute_el (COMMA xml_attribute_el)* ; xml_attribute_el : a_expr (AS collabel)? ; document_or_content : DOCUMENT_P | CONTENT_P ; xml_whitespace_option : PRESERVE WHITESPACE_P | STRIP_P WHITESPACE_P | ; xmlexists_argument : PASSING c_expr | PASSING c_expr xml_passing_mech | PASSING xml_passing_mech c_expr | PASSING xml_passing_mech c_expr xml_passing_mech ; xml_passing_mech : BY (REF | VALUE_P) ; within_group_clause : WITHIN GROUP_P OPEN_PAREN sort_clause CLOSE_PAREN | ; filter_clause : FILTER OPEN_PAREN WHERE a_expr CLOSE_PAREN | ; window_clause : WINDOW window_definition_list | ; window_definition_list : window_definition (COMMA window_definition)* ; window_definition : colid AS window_specification ; over_clause : OVER (window_specification | colid) | ; window_specification : OPEN_PAREN opt_existing_window_name opt_partition_clause opt_sort_clause opt_frame_clause CLOSE_PAREN ; opt_existing_window_name : colid | ; opt_partition_clause : PARTITION BY expr_list | ; opt_frame_clause : RANGE frame_extent opt_window_exclusion_clause | ROWS frame_extent opt_window_exclusion_clause | GROUPS frame_extent opt_window_exclusion_clause | ; frame_extent : frame_bound | BETWEEN frame_bound AND frame_bound ; frame_bound : UNBOUNDED (PRECEDING | FOLLOWING) | CURRENT_P ROW | a_expr (PRECEDING | FOLLOWING) ; opt_window_exclusion_clause : EXCLUDE (CURRENT_P ROW | GROUP_P | TIES | NO OTHERS) | ; row : ROW OPEN_PAREN expr_list? CLOSE_PAREN | OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN ; explicit_row : ROW OPEN_PAREN expr_list? CLOSE_PAREN ; /* TODO: for some reason v1 implicit_row: OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN; works better than v2 implicit_row: OPEN_PAREN expr_list CLOSE_PAREN; while looks like they are almost the same, except v2 requieres at least 2 items in list while v1 allows single item in list */ implicit_row : OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN ; sub_type : ANY | SOME | ALL ; all_op : Operator | mathop ; mathop : PLUS | MINUS | STAR | SLASH | PERCENT | CARET | LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS ; qual_op : Operator | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN ; qual_all_op : all_op | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN ; subquery_Op : all_op | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN | LIKE | NOT LIKE | ILIKE | NOT ILIKE ; expr_list : a_expr (COMMA a_expr)* ; func_arg_list : func_arg_expr (COMMA func_arg_expr)* ; func_arg_expr : a_expr | param_name (COLON_EQUALS | EQUALS_GREATER) a_expr ; type_list : typename (COMMA typename)* ; array_expr : OPEN_BRACKET (expr_list | array_expr_list)? CLOSE_BRACKET ; array_expr_list : array_expr (COMMA array_expr)* ; extract_list : extract_arg FROM a_expr | ; extract_arg : identifier | YEAR_P | MONTH_P | DAY_P | HOUR_P | MINUTE_P | SECOND_P | sconst ; unicode_normal_form : NFC | NFD | NFKC | NFKD ; overlay_list : a_expr PLACING a_expr FROM a_expr (FOR a_expr)? ; position_list : b_expr IN_P b_expr | ; substr_list : a_expr FROM a_expr FOR a_expr | a_expr FOR a_expr FROM a_expr | a_expr FROM a_expr | a_expr FOR a_expr | a_expr SIMILAR a_expr ESCAPE a_expr | expr_list ; trim_list : a_expr FROM expr_list | FROM expr_list | expr_list ; in_expr : select_with_parens # in_expr_select | OPEN_PAREN expr_list CLOSE_PAREN # in_expr_list ; case_expr : CASE case_arg when_clause_list case_default END_P ; when_clause_list : when_clause+ ; when_clause : WHEN a_expr THEN a_expr ; case_default : ELSE a_expr | ; case_arg : a_expr | ; columnref : colid indirection? ; indirection_el : DOT (attr_name | STAR) | OPEN_BRACKET (a_expr | opt_slice_bound COLON opt_slice_bound) CLOSE_BRACKET ; opt_slice_bound : a_expr | ; indirection : indirection_el+ ; opt_indirection : indirection_el* ; opt_target_list : target_list | ; target_list : target_el (COMMA target_el)* ; target_el : a_expr (AS collabel | identifier |) # target_label | STAR # target_star ; qualified_name_list : qualified_name (COMMA qualified_name)* ; qualified_name : colid indirection? ; name_list : name (COMMA name)* ; name : colid ; attr_name : collabel ; file_name : sconst ; func_name : builtin_function_name | type_function_name | colid indirection | LEFT | RIGHT ; aexprconst : iconst | fconst | sconst | bconst | xconst | func_name (sconst | OPEN_PAREN func_arg_list opt_sort_clause CLOSE_PAREN sconst) | consttypename sconst | constinterval (sconst opt_interval | OPEN_PAREN iconst CLOSE_PAREN sconst) | TRUE_P | FALSE_P | NULL_P ; xconst : HexadecimalStringConstant ; bconst : BinaryStringConstant ; fconst : Numeric ; iconst : Integral ; sconst : anysconst opt_uescape ; anysconst : StringConstant | UnicodeEscapeStringConstant | BeginDollarStringConstant DollarText* EndDollarStringConstant | EscapeStringConstant ; opt_uescape : UESCAPE anysconst | ; signediconst : iconst | PLUS iconst | MINUS iconst ; roleid : rolespec ; rolespec : nonreservedword | CURRENT_USER | SESSION_USER ; role_list : rolespec (COMMA rolespec)* ; colid : identifier | unreserved_keyword | col_name_keyword | plsql_unreserved_keyword | LEFT | RIGHT ; table_alias : identifier | unreserved_keyword | col_name_keyword | plsql_unreserved_keyword ; type_function_name : identifier | unreserved_keyword | plsql_unreserved_keyword | type_func_name_keyword ; nonreservedword : identifier | unreserved_keyword | col_name_keyword | type_func_name_keyword ; collabel : identifier | plsql_unreserved_keyword | unreserved_keyword | col_name_keyword | type_func_name_keyword | reserved_keyword ; identifier : Identifier opt_uescape | QuotedIdentifier | UnicodeQuotedIdentifier | plsqlvariablename | plsqlidentifier | plsql_unreserved_keyword ; plsqlidentifier : PLSQLIDENTIFIER ; unreserved_keyword : ABORT_P | ABSOLUTE_P | ACCESS | ACTION | ADD_P | ADMIN | AFTER | AGGREGATE | ALSO | ALTER | ALWAYS | ASSERTION | ASSIGNMENT | AT | ATTACH | ATTRIBUTE | BACKWARD | BEFORE | BEGIN_P | BY | CACHE | CALL | CALLED | CASCADE | CASCADED | CATALOG | CHAIN | CHARACTERISTICS | CHECKPOINT | CLASS | CLOSE | CLUSTER | COLUMNS | COMMENT | COMMENTS | COMMIT | COMMITTED | CONFIGURATION | CONFLICT | CONNECTION | CONSTRAINTS | CONTENT_P | CONTINUE_P | CONVERSION_P | COPY | COST | CSV | CUBE | CURRENT_P | CURSOR | CYCLE | DATA_P | DATABASE | DAY_P | DEALLOCATE | DECLARE | DEFAULTS | DEFERRED | DEFINER | DELETE_P | DELIMITER | DELIMITERS | DEPENDS | DETACH | DICTIONARY | DISABLE_P | DISCARD | DOCUMENT_P | DOMAIN_P | DOUBLE_P | DROP | EACH | ENABLE_P | ENCODING | ENCRYPTED | ENUM_P | ESCAPE | EVENT | EXCLUDE | EXCLUDING | EXCLUSIVE | EXECUTE | EXPLAIN | EXPRESSION | EXTENSION | EXTERNAL | FAMILY | FILTER | FIRST_P | FOLLOWING | FORCE | FORWARD | FUNCTION | FUNCTIONS | GENERATED | GLOBAL | GRANTED | GROUPS | HANDLER | HEADER_P | HOLD | HOUR_P | IDENTITY_P | IF_P | IMMEDIATE | IMMUTABLE | IMPLICIT_P | IMPORT_P | INCLUDE | INCLUDING | INCREMENT | INDEX | INDEXES | INHERIT | INHERITS | INLINE_P | INPUT_P | INSENSITIVE | INSERT | INSTEAD | INVOKER | ISOLATION | KEY | LABEL | LANGUAGE | LARGE_P | LAST_P | LEAKPROOF | SHIPPABLE | FENCED | PACKAGE | LEVEL | LISTEN | LOAD | LOCAL | LOCATION | LOCK_P | LOCKED | LOGGED | MAPPING | MATCH | MATERIALIZED | MAXVALUE | METHOD | MINUTE_P | MINVALUE | MODE | MONTH_P | MOVE | NAME_P | NAMES | NEW | NEXT | NFC | NFD | NFKC | NFKD | NO | NORMALIZED | NOTHING | NOTIFY | NOWAIT | NULLS_P | OBJECT_P | OF | OFF | OIDS | OLD | OPERATOR | OPTION | OPTIONS | ORDINALITY | OTHERS | OVER | OVERRIDING | OWNED | OWNER | PARALLEL | PARSER | PARTIAL | PARTITION | PASSING | PASSWORD | PLANS | POLICY | PRECEDING | PREPARE | PREPARED | PRESERVE | PRIOR | PRIVILEGES | PROCEDURAL | PROCEDURE | PROCEDURES | PROGRAM | PUBLICATION | QUOTE | RANGE | READ | REASSIGN | RECHECK | RECURSIVE | REF | REFERENCING | REFRESH | REINDEX | RELATIVE_P | RELEASE | RENAME | REPEATABLE | REPLICA | RESET | RESTART | RESTRICT | RETURNS | REVOKE | ROLE | ROLLBACK | ROLLUP | ROUTINE | ROUTINES | ROWS | RULE | SAVEPOINT | SCHEMA | SCHEMAS | SCROLL | SEARCH | SECOND_P | SECURITY | SEQUENCE | SEQUENCES | SERIALIZABLE | SERVER | SESSION | SET | SETS | SHARE | SHOW | SIMPLE | SKIP_P | SNAPSHOT | SQL_P | STABLE | STANDALONE_P | START | STATEMENT | STATISTICS | STDIN | STDOUT | STORAGE | STORED | STRICT_P | STRIP_P | SUBSCRIPTION | SUPPORT | SYSID | SYSTEM_P | TABLES | TABLESPACE | TEMP | TEMPLATE | TEMPORARY | TEXT_P | TIES | TRANSACTION | TRANSFORM | TRIGGER | TRUNCATE | TRUSTED | TYPE_P | TYPES_P | UESCAPE | UNBOUNDED | UNCOMMITTED | UNENCRYPTED | UNKNOWN | UNLISTEN | UNLOGGED | UNTIL | UPDATE | VACUUM | VALID | VALIDATE | VALIDATOR | VALUE_P | VARYING | VERSION_P | VIEW | VIEWS | VOLATILE | WHITESPACE_P | WITHIN | WITHOUT | WORK | WRAPPER | WRITE | XML_P | YEAR_P | YES_P | ZONE ; col_name_keyword : BETWEEN | BIGINT | bit | BOOLEAN_P | CHAR_P | character | COALESCE | DEC | DECIMAL_P | EXISTS | EXTRACT | FLOAT_P | GREATEST | GROUPING | INOUT | INT_P | INTEGER | INTERVAL | LEAST | NATIONAL | NCHAR | NONE | NORMALIZE | NULLIF | numeric | OUT_P | OVERLAY | POSITION | PRECISION | REAL | ROW | SETOF | SMALLINT | SUBSTRING | TIME | TIMESTAMP | TREAT | TRIM | VALUES | VARCHAR | XMLATTRIBUTES | XMLCONCAT | XMLELEMENT | XMLEXISTS | XMLFOREST | XMLNAMESPACES | XMLPARSE | XMLPI | XMLROOT | XMLSERIALIZE | XMLTABLE | builtin_function_name ; type_func_name_keyword : AUTHORIZATION | BINARY | COLLATION | CONCURRENTLY | CROSS | CURRENT_SCHEMA | FREEZE | FULL | ILIKE | INNER_P | IS | ISNULL | JOIN | LIKE | NATURAL | NOTNULL | OUTER_P | OVERLAPS | SIMILAR | TABLESAMPLE | VERBOSE ; reserved_keyword : ALL | ANALYSE | ANALYZE | AND | ANY | ARRAY | AS | ASC | ASYMMETRIC | BOTH | CASE | CAST | CHECK | COLLATE | COLUMN | CONSTRAINT | CREATE | CURRENT_CATALOG | CURRENT_DATE | CURRENT_ROLE | CURRENT_TIME | CURRENT_TIMESTAMP | CURRENT_USER // | DEFAULT | DEFERRABLE | DESC | DISTINCT | DO | ELSE | END_P | EXCEPT | FALSE_P | FETCH | FOR | FOREIGN | FROM | GRANT | GROUP_P | HAVING | IN_P | INITIALLY | INTERSECT /* from pl_gram.y, line ~2982 * Fortunately, INTO is a fully reserved word in the main grammar, so * at least we need not worry about it appearing as an identifier. */ // | INTO | LATERAL_P | LEADING | LIMIT | LOCALTIME | LOCALTIMESTAMP | NOT | NULL_P | OFFSET | ON | ONLY | OR | ORDER | PLACING | PRIMARY | REFERENCES | RETURNING | SELECT | SESSION_USER | SOME | SYMMETRIC | TABLE | THEN | TO | TRAILING | TRUE_P | UNION | UNIQUE | USER | USING | VARIADIC | WHEN | WHERE | WINDOW | WITH ; builtin_function_name : XMLCOMMENT | XML_IS_WELL_FORMED | XML_IS_WELL_FORMED_DOCUMENT | XML_IS_WELL_FORMED_CONTENT | XMLAGG | XPATH | XPATH_EXISTS | ABS | CBRT | CEIL | CEILING | DEGREES | DIV | EXP | FACTORIAL | FLOOR | GCD | LCM | LN | LOG | LOG10 | MIN_SCALE | MOD | PI | POWER | RADIANS | ROUND | SCALE | SIGN | SQRT | TRIM_SCALE | TRUNC | WIDTH_BUCKET | RANDOM | SETSEED | ACOS | ACOSD | ACOSH | ASIN | ASIND | ASINH | ATAN | ATAND | ATANH | ATAN2 | ATAN2D | COS | COSD | COSH | COT | COTD | SIN | SIND | SINH | TAN | TAND | TANH | BIT_LENGTH | CHAR_LENGTH | CHARACTER_LENGTH | LOWER | OCTET_LENGTH | OCTET_LENGTH | UPPER | ASCII | BTRIM | CHR | CONCAT | CONCAT_WS | FORMAT | INITCAP | LENGTH | LPAD | LTRIM | MD5 | PARSE_IDENT | PG_CLIENT_ENCODING | QUOTE_IDENT | QUOTE_LITERAL | QUOTE_NULLABLE | REGEXP_COUNT | REGEXP_INSTR | REGEXP_LIKE | REGEXP_MATCH | REGEXP_MATCHES | REGEXP_REPLACE | REGEXP_SPLIT_TO_ARRAY | REGEXP_SPLIT_TO_TABLE | REGEXP_SUBSTR | REPEAT | REPLACE | REVERSE | RPAD | RTRIM | SPLIT_PART | STARTS_WITH | STRING_TO_ARRAY | STRING_TO_TABLE | STRPOS | SUBSTR | TO_ASCII | TO_HEX | TRANSLATE | UNISTR | AGE | DATE_BIN | DATE_PART | DATE_TRUNC | ISFINITE | JUSTIFY_DAYS | JUSTIFY_HOURS | JUSTIFY_INTERVAL | MAKE_DATE | MAKE_INTERVAL | MAKE_TIME | MAKE_TIMESTAMP | MAKE_TIMESTAMPTZ | CLOCK_TIMESTAMP | NOW | STATEMENT_TIMESTAMP | TIMEOFDAY | TRANSACTION_TIMESTAMP | TO_TIMESTAMP | JUSTIFY_INTERVAL | JUSTIFY_INTERVAL | TO_CHAR | TO_DATE | TO_NUMBER ; /************************************************************************************************************************************************************/ /*PL/SQL GRAMMAR */ /*PLSQL grammar */ /************************************************************************************************************************************************************/ pl_function : comp_options pl_block opt_semi ; comp_options : comp_option* ; comp_option : sharp OPTION DUMP | sharp PRINT_STRICT_PARAMS option_value | sharp VARIABLE_CONFLICT ERROR | sharp VARIABLE_CONFLICT USE_VARIABLE | sharp VARIABLE_CONFLICT USE_COLUMN ; sharp : Operator ; option_value : sconst | reserved_keyword | plsql_unreserved_keyword | unreserved_keyword ; opt_semi : | SEMI ; // exception_sect means opt_exception_sect in original grammar, don't be confused! pl_block : decl_sect BEGIN_P proc_sect exception_sect END_P opt_label ; decl_sect : opt_block_label (decl_start decl_stmts?)? ; decl_start : DECLARE ; decl_stmts : decl_stmt+ ; label_decl : LESS_LESS any_identifier GREATER_GREATER ; decl_stmt : decl_statement | DECLARE | label_decl ; decl_statement : decl_varname ( ALIAS FOR decl_aliasitem | decl_const decl_datatype decl_collate decl_notnull decl_defval | opt_scrollable CURSOR decl_cursor_args decl_is_for decl_cursor_query ) SEMI ; opt_scrollable : | NO SCROLL | SCROLL ; decl_cursor_query : selectstmt ; decl_cursor_args : | OPEN_PAREN decl_cursor_arglist CLOSE_PAREN ; decl_cursor_arglist : decl_cursor_arg (COMMA decl_cursor_arg)* ; decl_cursor_arg : decl_varname decl_datatype ; decl_is_for : IS | FOR ; decl_aliasitem : PARAM | colid ; decl_varname : any_identifier ; decl_const : | CONSTANT ; decl_datatype : typename ; //TODO: $$ = read_datatype(yychar); decl_collate : | COLLATE any_name ; decl_notnull : | NOT NULL_P ; decl_defval : | decl_defkey sql_expression ; decl_defkey : assign_operator | DEFAULT ; assign_operator : EQUAL | COLON_EQUALS ; proc_sect : proc_stmt* ; proc_stmt : pl_block SEMI | stmt_return | stmt_raise | stmt_assign | stmt_if | stmt_case | stmt_loop | stmt_while | stmt_for | stmt_foreach_a | stmt_exit | stmt_assert | stmt_execsql | stmt_dynexecute | stmt_perform | stmt_call | stmt_getdiag | stmt_open | stmt_fetch | stmt_move | stmt_close | stmt_null | stmt_commit | stmt_rollback | stmt_set ; stmt_perform : PERFORM expr_until_semi SEMI ; stmt_call : CALL any_identifier OPEN_PAREN opt_expr_list CLOSE_PAREN SEMI | DO any_identifier OPEN_PAREN opt_expr_list CLOSE_PAREN SEMI ; opt_expr_list : | expr_list ; stmt_assign : assign_var assign_operator sql_expression SEMI ; stmt_getdiag : GET getdiag_area_opt DIAGNOSTICS getdiag_list SEMI ; getdiag_area_opt : | CURRENT_P | STACKED ; getdiag_list : getdiag_list_item (COMMA getdiag_list_item)* ; getdiag_list_item : getdiag_target assign_operator getdiag_item ; getdiag_item : colid ; getdiag_target : assign_var ; assign_var : (any_name | PARAM) (OPEN_BRACKET expr_until_rightbracket CLOSE_BRACKET)* ; stmt_if : IF_P expr_until_then THEN proc_sect stmt_elsifs stmt_else END_P IF_P SEMI ; stmt_elsifs : (ELSIF a_expr THEN proc_sect)* ; stmt_else : | ELSE proc_sect ; stmt_case : CASE opt_expr_until_when case_when_list opt_case_else END_P CASE SEMI ; opt_expr_until_when : | sql_expression ; case_when_list : case_when+ ; case_when : WHEN expr_list THEN proc_sect ; opt_case_else : | ELSE proc_sect ; stmt_loop : opt_loop_label loop_body ; stmt_while : opt_loop_label WHILE expr_until_loop loop_body ; stmt_for : opt_loop_label FOR for_control loop_body ; //TODO: rewrite using read_sql_expression logic? for_control : for_variable IN_P ( cursor_name opt_cursor_parameters | selectstmt | explainstmt | EXECUTE a_expr opt_for_using_expression | opt_reverse a_expr DOT_DOT a_expr opt_by_expression ) ; opt_for_using_expression : | USING expr_list ; opt_cursor_parameters : | OPEN_PAREN a_expr (COMMA a_expr)* CLOSE_PAREN ; opt_reverse : | REVERSE ; opt_by_expression : | BY a_expr ; for_variable : any_name_list ; stmt_foreach_a : opt_loop_label FOREACH for_variable foreach_slice IN_P ARRAY a_expr loop_body ; foreach_slice : | SLICE iconst ; stmt_exit : exit_type opt_label opt_exitcond SEMI ; exit_type : EXIT | CONTINUE_P ; //todo implement RETURN statement according to initial grammar line 1754 stmt_return : RETURN (NEXT sql_expression | QUERY (EXECUTE a_expr opt_for_using_expression | selectstmt) | opt_return_result) SEMI ; opt_return_result : | sql_expression ; //https://www.postgresql.org/docs/current/plpgsql-errors-and-messages.html //RAISE [ level ] 'format' [, expression [, ... ]] [ USING option = expression [, ... ] ]; //RAISE [ level ] condition_name [ USING option = expression [, ... ] ]; //RAISE [ level ] SQLSTATE 'sqlstate' [ USING option = expression [, ... ] ]; //RAISE [ level ] USING option = expression [, ... ]; //RAISE ; stmt_raise : RAISE opt_stmt_raise_level sconst opt_raise_list opt_raise_using SEMI | RAISE opt_stmt_raise_level identifier opt_raise_using SEMI | RAISE opt_stmt_raise_level SQLSTATE sconst opt_raise_using SEMI | RAISE opt_stmt_raise_level opt_raise_using SEMI | RAISE ; opt_stmt_raise_level : | | DEBUG | LOG | INFO | NOTICE | WARNING | EXCEPTION ; opt_raise_list : | (COMMA a_expr)+ ; opt_raise_using : | USING opt_raise_using_elem_list ; opt_raise_using_elem : identifier EQUAL a_expr ; opt_raise_using_elem_list : opt_raise_using_elem (COMMA opt_raise_using_elem)* ; //todo imnplement stmt_assert : ASSERT sql_expression opt_stmt_assert_message SEMI ; opt_stmt_assert_message : | COMMA sql_expression ; loop_body : LOOP proc_sect END_P LOOP opt_label SEMI ; //TODO: looks like all other statements like INSERT/SELECT/UPDATE/DELETE are handled here; //pls take a look at original grammar stmt_execsql : make_execsql_stmt SEMI /*K_IMPORT | K_INSERT | t_word | t_cword */ ; //https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT //EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ]; stmt_dynexecute : EXECUTE a_expr ( /*this is silly, but i have to time to find nice way to code */ opt_execute_into opt_execute_using | opt_execute_using opt_execute_into |) SEMI ; opt_execute_using : | USING opt_execute_using_list ; opt_execute_using_list : a_expr (COMMA a_expr)* ; opt_execute_into : | INTO STRICT_P? into_target ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //OPEN unbound_cursorvar [ [ NO ] SCROLL ] FOR query; //OPEN unbound_cursorvar [ [ NO ] SCROLL ] FOR EXECUTE query_string // [ USING expression [, ... ] ]; //OPEN bound_cursorvar [ ( [ argument_name := ] argument_value [, ...] ) ]; stmt_open : OPEN ( cursor_variable opt_scroll_option FOR (selectstmt | EXECUTE sql_expression opt_open_using) | colid (OPEN_PAREN opt_open_bound_list CLOSE_PAREN)? ) SEMI ; opt_open_bound_list_item : colid COLON_EQUALS a_expr | a_expr ; opt_open_bound_list : opt_open_bound_list_item (COMMA opt_open_bound_list_item)* ; opt_open_using : | USING expr_list ; opt_scroll_option : | opt_scroll_option_no SCROLL ; opt_scroll_option_no : | NO ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //FETCH [ direction { FROM | IN } ] cursor INTO target; stmt_fetch : FETCH direction = opt_fetch_direction opt_cursor_from cursor_variable INTO into_target SEMI ; into_target : expr_list ; opt_cursor_from : | FROM | IN_P ; opt_fetch_direction : | | NEXT | PRIOR | FIRST_P | LAST_P | ABSOLUTE_P a_expr | RELATIVE_P a_expr | a_expr | ALL | (FORWARD | BACKWARD) (a_expr | ALL)? ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //MOVE [ direction { FROM | IN } ] cursor; stmt_move : MOVE opt_fetch_direction cursor_variable SEMI ; stmt_close : CLOSE cursor_variable SEMI ; stmt_null : NULL_P SEMI ; stmt_commit : COMMIT plsql_opt_transaction_chain SEMI ; stmt_rollback : ROLLBACK plsql_opt_transaction_chain SEMI ; plsql_opt_transaction_chain : AND NO? CHAIN | ; stmt_set : SET any_name TO DEFAULT SEMI | RESET (any_name | ALL) SEMI ; cursor_variable : colid | PARAM ; exception_sect : | EXCEPTION proc_exceptions ; proc_exceptions : proc_exception+ ; proc_exception : WHEN proc_conditions THEN proc_sect ; proc_conditions : proc_condition (OR proc_condition)* ; proc_condition : any_identifier | SQLSTATE sconst ; //expr_until_semi: //; //expr_until_rightbracket: //; //expr_until_loop: //; opt_block_label : | label_decl ; opt_loop_label : | label_decl ; opt_label : | any_identifier ; opt_exitcond : WHEN expr_until_semi | ; any_identifier : colid | plsql_unreserved_keyword ; plsql_unreserved_keyword : ABSOLUTE_P | ALIAS | AND | ARRAY | ASSERT | BACKWARD | CALL | CHAIN | CLOSE | COLLATE | COLUMN //| COLUMN_NAME | COMMIT | CONSTANT | CONSTRAINT //| CONSTRAINT_NAME | CONTINUE_P | CURRENT_P | CURSOR //| DATATYPE | DEBUG | DEFAULT //| DETAIL | DIAGNOSTICS | DO | DUMP | ELSIF //| ERRCODE | ERROR | EXCEPTION | EXIT | FETCH | FIRST_P | FORWARD | GET //| HINT //| IMPORT | INFO | INSERT | IS | LAST_P //| MESSAGE //| MESSAGE_TEXT | MOVE | NEXT | NO | NOTICE | OPEN | OPTION | PERFORM //| PG_CONTEXT //| PG_DATATYPE_NAME //| PG_EXCEPTION_CONTEXT //| PG_EXCEPTION_DETAIL //| PG_EXCEPTION_HINT | PRINT_STRICT_PARAMS | PRIOR | QUERY | RAISE | RELATIVE_P | RESET | RETURN //| RETURNED_SQLSTATE | ROLLBACK //| ROW_COUNT | ROWTYPE | SCHEMA //| SCHEMA_NAME | SCROLL | SET | SLICE | SQLSTATE | STACKED | TABLE //| TABLE_NAME | TYPE_P | USE_COLUMN | USE_VARIABLE | VARIABLE_CONFLICT | WARNING | OUTER_P ; sql_expression : opt_target_list into_clause from_clause where_clause group_clause having_clause window_clause ; expr_until_then : sql_expression ; expr_until_semi : sql_expression ; expr_until_rightbracket : a_expr ; expr_until_loop : a_expr ; make_execsql_stmt : stmt opt_returning_clause_into ; opt_returning_clause_into : INTO opt_strict into_target | ; ================================================ FILE: superior-postgres-parser/src/main/java/io/github/melin/superior/parser/postgre/antlr4/LexerDispatchingErrorListener.java ================================================ package io.github.melin.superior.parser.postgre.antlr4; import java.util.BitSet; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.*; public class LexerDispatchingErrorListener implements ANTLRErrorListener { Lexer _parent; public LexerDispatchingErrorListener(Lexer parent) { _parent = parent; } public void syntaxError( Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); } public void reportAmbiguity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs); } public void reportAttemptingFullContext( Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs); } public void reportContextSensitivity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs); } } ================================================ FILE: superior-postgres-parser/src/main/java/io/github/melin/superior/parser/postgre/antlr4/ParserDispatchingErrorListener.java ================================================ package io.github.melin.superior.parser.postgre.antlr4; import java.util.BitSet; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.*; public class ParserDispatchingErrorListener implements ANTLRErrorListener { Parser _parent; public ParserDispatchingErrorListener(Parser parent) { _parent = parent; } public void syntaxError( Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); } public void reportAmbiguity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs); } public void reportAttemptingFullContext( Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs); } public void reportContextSensitivity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs); } } ================================================ FILE: superior-postgres-parser/src/main/java/io/github/melin/superior/parser/postgre/antlr4/PostgreSqlLexerBase.java ================================================ package io.github.melin.superior.parser.postgre.antlr4; import java.util.ArrayDeque; import java.util.Deque; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.Lexer; public abstract class PostgreSqlLexerBase extends Lexer { protected final Deque tags = new ArrayDeque<>(); protected PostgreSqlLexerBase(CharStream input) { super(input); } public void pushTag() { tags.push(getText()); } public boolean isTag() { return getText().equals(tags.peek()); } public void popTag() { tags.pop(); } public boolean checkLA(int c) { return getInputStream().LA(1) != c; } public boolean charIsLetter() { return Character.isLetter(getInputStream().LA(-1)); } public void HandleNumericFail() { getInputStream().seek(getInputStream().index() - 2); setType(PostgreSqlLexer.Integral); } public void HandleLessLessGreaterGreater() { if (getText() == "<<") setType(PostgreSqlLexer.LESS_LESS); if (getText() == ">>") setType(PostgreSqlLexer.GREATER_GREATER); } public void UnterminatedBlockCommentDebugAssert() { // Debug.Assert(InputStream.LA(1) == -1 /*EOF*/); } public boolean CheckIfUtf32Letter() { int codePoint = getInputStream().LA(-2) << 8 + getInputStream().LA(-1); char[] c; if (codePoint < 0x10000) { c = new char[] {(char) codePoint}; } else { codePoint -= 0x10000; c = new char[] {(char) (codePoint / 0x400 + 0xd800), (char) (codePoint % 0x400 + 0xdc00)}; } return Character.isLetter(c[0]); } } ================================================ FILE: superior-postgres-parser/src/main/java/io/github/melin/superior/parser/postgre/antlr4/PostgreSqlParserBase.java ================================================ package io.github.melin.superior.parser.postgre.antlr4; import io.github.melin.superior.common.antlr4.UpperCaseCharStream; import java.util.List; import org.antlr.v4.runtime.*; import org.apache.commons.lang3.StringUtils; public abstract class PostgreSqlParserBase extends Parser { public PostgreSqlParserBase(TokenStream input) { super(input); } ParserRuleContext GetParsedSqlTree(String script, int line) { PostgreSqlParser ph = getPostgreSQLParser(script); ParserRuleContext result = ph.root(); return result; } public void ParseRoutineBody(PostgreSqlParser.Createfunc_opt_listContext _localctx) { String lang = null; for (PostgreSqlParser.Createfunc_opt_itemContext coi : _localctx.createfunc_opt_item()) { if (coi.LANGUAGE() != null) { if (coi.nonreservedword_or_sconst() != null) if (coi.nonreservedword_or_sconst().nonreservedword() != null) if (coi.nonreservedword_or_sconst().nonreservedword().identifier() != null) if (coi.nonreservedword_or_sconst() .nonreservedword() .identifier() .Identifier() != null) { lang = coi.nonreservedword_or_sconst() .nonreservedword() .identifier() .Identifier() .getText(); break; } } } if (null == lang) return; PostgreSqlParser.Createfunc_opt_itemContext func_as = null; for (PostgreSqlParser.Createfunc_opt_itemContext a : _localctx.createfunc_opt_item()) { if (a.func_as() != null) { func_as = a; break; } } lang = StringUtils.trim(lang); if (func_as != null) { String txt = GetRoutineBodyString(func_as.func_as().sconst(0)); PostgreSqlParser ph = getPostgreSQLParser(StringUtils.trim(txt)); switch (lang) { case "plpgsql": func_as.func_as().Definition = ph.plsqlroot(); break; case "sql": func_as.func_as().Definition = ph.root(); break; } } } private String TrimQuotes(String s) { return (s == null || s.isEmpty()) ? s : s.substring(1, s.length() - 1); } public String unquote(String s) { int slength = s.length(); StringBuilder r = new StringBuilder(slength); int i = 0; while (i < slength) { Character c = s.charAt(i); r.append(c); if (c == '\'' && i < slength - 1 && (s.charAt(i + 1) == '\'')) i++; i++; } return r.toString(); } public String GetRoutineBodyString(PostgreSqlParser.SconstContext rule) { PostgreSqlParser.AnysconstContext anysconst = rule.anysconst(); org.antlr.v4.runtime.tree.TerminalNode StringConstant = anysconst.StringConstant(); if (null != StringConstant) return unquote(TrimQuotes(StringConstant.getText())); org.antlr.v4.runtime.tree.TerminalNode UnicodeEscapeStringConstant = anysconst.UnicodeEscapeStringConstant(); if (null != UnicodeEscapeStringConstant) return TrimQuotes(UnicodeEscapeStringConstant.getText()); org.antlr.v4.runtime.tree.TerminalNode EscapeStringConstant = anysconst.EscapeStringConstant(); if (null != EscapeStringConstant) return TrimQuotes(EscapeStringConstant.getText()); String result = ""; List dollartext = anysconst.DollarText(); for (org.antlr.v4.runtime.tree.TerminalNode s : dollartext) { result += s.getText(); } return result; } public PostgreSqlParser getPostgreSQLParser(String script) { UpperCaseCharStream charStream = new UpperCaseCharStream(CharStreams.fromString(script)); Lexer lexer = new PostgreSqlLexer(charStream); CommonTokenStream tokens = new CommonTokenStream(lexer); PostgreSqlParser parser = new PostgreSqlParser(tokens); lexer.removeErrorListeners(); parser.removeErrorListeners(); LexerDispatchingErrorListener listener_lexer = new LexerDispatchingErrorListener( (Lexer) (((CommonTokenStream) (this.getInputStream())).getTokenSource())); ParserDispatchingErrorListener listener_parser = new ParserDispatchingErrorListener(this); lexer.addErrorListener(listener_lexer); parser.addErrorListener(listener_parser); return parser; } } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(PostgreSqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: PostgreSqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(PostgreSqlParser._ATN)) } } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/PostgreSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.postgre import com.github.melin.superior.sql.parser.util.CommonUtils import com.google.common.collect.Lists import io.github.melin.superior.common.* import io.github.melin.superior.common.AlterActionType.* import io.github.melin.superior.common.StatementType.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.RefreshMaterializedView import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropMaterializedView import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.drop.DropView import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.common.relational.table.TruncateTable import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser.ColconstraintelemContext import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser.Indirection_elContext import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser.OpttempTableNameContext import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser.PlsqlrootContext import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParserBaseVisitor import io.github.melin.superior.parser.postgre.relational.CreatePartitionTable import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:57 上午 */ class PostgreSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : PostgreSqlParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() // 多语句解析结果 private var statements: ArrayList = arrayListOf() // 存储过程和函数中包含的子语句 private var childStatements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitDecl_cursor_query(ctx: PostgreSqlParser.Decl_cursor_queryContext): Statement? { val statement = visitSelectstmt(ctx.selectstmt()) statement.setSql(source(ctx)) childStatements.add(statement) return null } override fun visitStmtmulti(ctx: PostgreSqlParser.StmtmultiContext): Statement? { ctx.stmt().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitStmt(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) currentOptType = StatementType.UNKOWN clean() } } return null } override fun visitStmt(ctx: PostgreSqlParser.StmtContext): Statement? { val stmt: Statement? = super.visitStmt(ctx) if (stmt != null) { if (currentOptType != CREATE_FUNCTION && currentOptType != CREATE_PROCEDURE) { stmt.setSql(source(ctx)) childStatements.add(stmt) } } clean() return stmt } private fun clean() { limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() } private fun addOutputTableId(tableId: TableId) { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } // -----------------------------------database------------------------------------------------- override fun visitCreatedbstmt(ctx: PostgreSqlParser.CreatedbstmtContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.name().text) return CreateDatabase(databaseName) } override fun visitDropdbstmt(ctx: PostgreSqlParser.DropdbstmtContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.name().text) return DropDatabase(databaseName) } // -----------------------------------schema------------------------------------------------- override fun visitCreateschemastmt(ctx: PostgreSqlParser.CreateschemastmtContext): Statement { val schemaName = CommonUtils.cleanQuote(ctx.colid().text) return CreateSchema(schemaName) } // -----------------------------------table------------------------------------------------- override fun visitCreatestmt(ctx: PostgreSqlParser.CreatestmtContext): Statement { currentOptType = CREATE_TABLE if (ctx.PARTITION() != null) { val partitionTableId = parseTableName(ctx.qualified_name(0)) val tableId = parseTableName(ctx.qualified_name(1)) return CreatePartitionTable(tableId, partitionTableId) } val tableId = parseTableName(ctx.qualified_name(0)) val columns = ctx.opttableelementlist()?.tableelementlist()?.tableelement()?.map { val colDef = it.columnDef() val colName = colDef.colid().text val dataType = colDef.typename().text val columnRel = ColumnRel(colName, dataType) colDef.colquallist().colconstraint().forEach { colconstraint -> val child = colconstraint.getChild(0) if (child is ColconstraintelemContext) { if (child.NOT() != null) { columnRel.nullable = false } else if (child.PRIMARY() != null) { columnRel.primaryKey = true } } } columnRel } val createTable = CreateTable(tableId, TableType.POSTGRES, columnRels = columns) if (ctx.opttemp().TEMP() != null || ctx.opttemp().TEMPORARY() != null) { createTable.temporary = true } val partitionspec = ctx.optpartitionspec()?.partitionspec() val tablePartition = ctx.gaussextension()?.tablePartition() if (partitionspec != null) { val partitionType = partitionspec.colid().text.uppercase() val partitionColumns = partitionspec.part_params().part_elem().map { it.text } createTable.partitionColumnNames.addAll(partitionColumns) if ("RANGE" == partitionType) { createTable.partitionType = PartitionType.RANGE } else { createTable.partitionType = PartitionType.LIST } } else if (tablePartition != null) { var partitionType: PartitionType? = null val partitionColumns = mutableListOf() val ptSpec = tablePartition.partition_list() if (ptSpec.list_partition_stmt() != null) { partitionType = PartitionType.LIST partitionColumns.add(ptSpec.list_partition_stmt().partition_key().colid().text) } else if (ptSpec.value_partition_stmt() != null) { partitionType = PartitionType.VALUES partitionColumns.add(ptSpec.value_partition_stmt().partition_key().colid().text) } else if (ptSpec.range_partition_stmt() != null) { partitionType = PartitionType.RANGE partitionColumns.add(ptSpec.range_partition_stmt().partition_key().colid().text) } else if (ptSpec.normal_partition_stmt() != null) { partitionType = PartitionType.NORMAL } createTable.partitionColumnNames.addAll(partitionColumns) createTable.partitionType = partitionType } return createTable } override fun visitFunc_as(ctx: PostgreSqlParser.Func_asContext): Statement? { if (ctx.Definition != null) { visitPlsqlroot(ctx.Definition as PlsqlrootContext) } return super.visitFunc_as(ctx) } override fun visitCreatefunctionstmt(ctx: PostgreSqlParser.CreatefunctionstmtContext): Statement { currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE childStatements = arrayListOf() super.visitCreatefunctionstmt(ctx) val replace = if (ctx.opt_or_replace().REPLACE() != null) true else false val funcName = ctx.func_name() if (ctx.FUNCTION() != null) { val functionId = if (funcName.type_function_name() != null) { FunctionId(funcName.text) } else { FunctionId(funcName.colid().text, funcName.indirection().indirection_el()[0].attr_name().text) } currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE return CreateFunction(functionId, childStatements, replace) } else { val procedureId = if (funcName.type_function_name() != null) { ProcedureId(funcName.text) } else { ProcedureId(funcName.colid().text, funcName.indirection().indirection_el()[0].attr_name().text) } currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE return CreateProcedure(procedureId, childStatements, replace) } } override fun visitProc_stmt(ctx: PostgreSqlParser.Proc_stmtContext): Statement? { super.visitProc_stmt(ctx) return null } override fun visitViewstmt(ctx: PostgreSqlParser.ViewstmtContext): Statement { currentOptType = CREATE_VIEW val tableId = parseTableName(ctx.qualified_name()) val replace = if (ctx.REPLACE() != null) true else false val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createView = CreateView(tableId, queryStmt) createView.replace = replace if (ctx.opttemp().TEMP() != null || ctx.opttemp().TEMPORARY() != null) { createView.temporary = true } return createView } override fun visitCreatematviewstmt(ctx: PostgreSqlParser.CreatematviewstmtContext): Statement { currentOptType = CREATE_MATERIALIZED_VIEW val tableId = parseTableName(ctx.create_mv_target().qualified_name()) val ifNotExists = if (ctx.IF_P() != null) true else false val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createView = CreateMaterializedView(tableId, queryStmt) createView.ifNotExists = ifNotExists return createView } override fun visitRefreshmatviewstmt(ctx: PostgreSqlParser.RefreshmatviewstmtContext): Statement { val tableId = parseTableName(ctx.qualified_name()) return RefreshMaterializedView(tableId) } override fun visitRenamestmt(ctx: PostgreSqlParser.RenamestmtContext): Statement? { if (ctx.TABLE() != null) { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterTable(tableId, action) } else if (ctx.VIEW() != null) { if (ctx.MATERIALIZED() == null) { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterView(tableId, action) } else { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterMaterializedView(tableId, action) } } else { return null } } override fun visitSelectstmt(ctx: PostgreSqlParser.SelectstmtContext): Statement { currentOptType = SELECT super.visitSelectstmt(ctx) return QueryStmt(inputTables, limit, offset) } override fun visitCreateasstmt(ctx: PostgreSqlParser.CreateasstmtContext): Statement { currentOptType = CREATE_TABLE_AS_SELECT val tableId = parseTableName(ctx.create_as_target().qualified_name()) val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createTable = CreateTableAsSelect(tableId, queryStmt) return createTable } override fun visitUpdatestmt(ctx: PostgreSqlParser.UpdatestmtContext): Statement { currentOptType = UPDATE val tableId = parseTableName(ctx.relation_expr_opt_alias().relation_expr()) addOutputTableId(tableId) super.visitWhere_or_current_clause(ctx.where_or_current_clause()) super.visitFrom_clause(ctx.from_clause()) return UpdateTable(tableId, inputTables) } override fun visitDeletestmt(ctx: PostgreSqlParser.DeletestmtContext): Statement { currentOptType = DELETE val tableId = parseTableName(ctx.relation_expr_opt_alias().relation_expr()) addOutputTableId(tableId) super.visitWhere_or_current_clause(ctx.where_or_current_clause()) super.visitUsing_clause(ctx.using_clause()) return DeleteTable(tableId, inputTables) } override fun visitInsertstmt(ctx: PostgreSqlParser.InsertstmtContext): Statement { currentOptType = INSERT if (ctx.opt_with_clause() != null) { this.visitOpt_with_clause(ctx.opt_with_clause()) } val tableId = parseTableName(ctx.insert_target().qualified_name()) addOutputTableId(tableId) val queryStmt = this.visitSelectstmt(ctx.insert_rest().selectstmt()) as QueryStmt val insertTable = InsertTable(InsertMode.INTO, queryStmt, tableId) insertTable.outputTables.addAll(outputTables.subList(1, outputTables.size)) insertTable?.setSql(source(ctx)) return insertTable } override fun visitMergestmt(ctx: PostgreSqlParser.MergestmtContext): Statement { currentOptType = MERGE val mergeTableId = parseTableName(ctx.qualified_name(0)) val mergeTable = MergeTable(mergeTableId) if (ctx.qualified_name().size == 2) { val tableId = parseTableName(ctx.qualified_name(1)) inputTables.add(tableId) } else if (ctx.select_with_parens() != null) { super.visitSelect_with_parens(ctx.select_with_parens()) } mergeTable.inputTables = inputTables return mergeTable } override fun visitCte_list(ctx: PostgreSqlParser.Cte_listContext): Statement { ctx.common_table_expr().forEach { cteTempTables.add(TableId(it.name().text)) } return super.visitCte_list(ctx) } override fun visitQualified_name(ctx: PostgreSqlParser.Qualified_nameContext): Statement? { if ( currentOptType == SELECT || currentOptType == CREATE_VIEW || currentOptType == CREATE_MATERIALIZED_VIEW || currentOptType == CREATE_TABLE_AS_SELECT || currentOptType == UPDATE || currentOptType == DELETE || currentOptType == MERGE || currentOptType == INSERT || currentOptType == CREATE_FUNCTION || currentOptType == CREATE_PROCEDURE ) { if (ctx.parent is OpttempTableNameContext) { return null } val tableId = parseTableName(ctx) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } return null } else { throw SQLParserException("not support") } } // create index override fun visitIndexstmt(ctx: PostgreSqlParser.IndexstmtContext): Statement { val tableId = parseTableName(ctx.relation_expr()) val indexName = if (ctx.opt_index_name() != null) { ctx.opt_index_name().text } else { ctx.name().text } val createIndex = CreateIndex(indexName) return AlterTable(tableId, createIndex) } override fun visitDropstmt(ctx: PostgreSqlParser.DropstmtContext): Statement { if (ctx.object_type_any_name() != null) { val ifExists = ctx.IF_P() != null if (ctx.object_type_any_name().INDEX() != null) { val actions = ctx.any_name_list().any_name().map { indexName -> DropIndex(indexName.text, ifExists) } val tableId = TableId("") val alterTable = AlterTable(tableId) alterTable.ifExists = ifExists alterTable.addActions(actions) return alterTable } else if (ctx.object_type_any_name().TABLE() != null) { val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } val dropTable = DropTable(tableIds.first(), ifExists) dropTable.tableIds.addAll(tableIds) return dropTable } else if (ctx.object_type_any_name().VIEW() != null) { val isMaterialized = if (ctx.object_type_any_name().MATERIALIZED() != null) { true } else { false } val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } if (isMaterialized) { val dropView = DropMaterializedView(tableIds.first(), ifExists) dropView.tableIds.addAll(tableIds) return dropView } else { val dropView = DropView(tableIds.first(), ifExists) dropView.tableIds.addAll(tableIds) return dropView } } else if (ctx.object_type_any_name().SEQUENCE() != null) { val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } val dropSequence = io.github.melin.superior.common.relational.drop.DropSequence(tableIds.first(), ifExists) dropSequence.tableIds.addAll(tableIds) return dropSequence } } throw SQLParserException("not support") } override fun visitTruncatestmt(ctx: PostgreSqlParser.TruncatestmtContext): Statement { val tableIds = ctx.relation_expr_list().relation_expr().map { parseTableName(it) } return TruncateTable(Lists.newArrayList(tableIds)) } override fun visitAltertablestmt(ctx: PostgreSqlParser.AltertablestmtContext): Statement? { if (ctx.TABLE() != null) { if (ctx.relation_expr() != null) { val tableId = parseTableName(ctx.relation_expr()) if (ctx.alter_table_cmds() != null) { val alterTable = AlterTable(tableId) val cmds = ctx.alter_table_cmds().alter_table_cmd() for (cmdContext in cmds) { if (cmdContext.ADD_P() != null && cmdContext.columnDef() != null) { val columnDef = cmdContext.columnDef() val columnName = columnDef.colid().text val dataType = source(columnDef.typename()) val action = AlterColumnAction(ADD_COLUMN, columnName, dataType) action.ifNotExists = cmdContext.EXISTS() != null alterTable.actions.add(action) } else if (cmdContext.alter_column_default() != null) { val columnDefaultDef = cmdContext.alter_column_default() val columnName = cmdContext.colid().get(0).text if (columnDefaultDef.DROP() != null) { val action = AlterColumnAction(DROP_COLUMN_DRFAULT, columnName) alterTable.actions.add(action) } else { val value = source(columnDefaultDef.a_expr()) val action = AlterColumnAction(SET_COLUMN_DEFAULT, columnName) action.defaultExpression = CommonUtils.cleanQuote(value) alterTable.actions.add(action) } } } return alterTable } else { var alterTable: AlterTable? = null val partitionCmd = ctx.partition_cmd() if (partitionCmd.ATTACH() != null) { alterTable = AlterTable(tableId, AlterTableAction(ATTACH_PARTITION)) } else { alterTable = AlterTable(tableId, AlterTableAction(DETACH_PARTITION)) } return alterTable } return null } } return null } override fun visitCommentstmt(ctx: PostgreSqlParser.CommentstmtContext): Statement { val objType: String? = if (ctx.object_type_any_name() != null) { ctx.object_type_any_name().children.map { it.text }.joinToString(" ") } else if (ctx.object_type_name() != null) { ctx.object_type_name().children.map { it.text }.joinToString(" ") } else if (ctx.object_type_name_on_any_name() != null) { ctx.object_type_name_on_any_name().children.map { it.text }.joinToString(" ") } else if (ctx.COLUMN() != null) { ctx.COLUMN().text } else if (ctx.FUNCTION() != null) { ctx.FUNCTION().text } else { null } val objValue = if (ctx.any_name() != null) ctx.any_name().text else null val isNull = if (ctx.comment_text().NULL_P() != null) true else false val text: String? = if (ctx.comment_text().text != null) CommonUtils.cleanQuote(ctx.comment_text().sconst().text) else null return CommentStatement(text, isNull, objType, objValue) } override fun visitStmt_dynexecute(ctx: PostgreSqlParser.Stmt_dynexecuteContext): Statement? { var execSql = StringUtils.substringAfter(ctx.a_expr().text, "'") execSql = StringUtils.substringBeforeLast(execSql, "'") execSql = StringUtils.trim(execSql) execSql = StringUtils.replace(execSql, "''", "'") val statements = PostgreSqlHelper.parseMultiStatement(execSql) childStatements.addAll(statements) return null } override fun visitSelect_limit(ctx: PostgreSqlParser.Select_limitContext): Statement? { val limitClause = ctx.limit_clause() val offsetClause = ctx.offset_clause() if (limitClause != null) { if (limitClause.LIMIT() != null) { if (limitClause.select_limit_value().a_expr() != null) { limit = limitClause.select_limit_value().a_expr().text.toInt() } if (limitClause.select_offset_value() != null) { offset = limitClause.select_offset_value().a_expr().text.toInt() } } if (limitClause.FETCH() != null && limitClause.select_fetch_first_value() != null) { if (limitClause.select_fetch_first_value().c_expr() != null) { limit = limitClause.select_fetch_first_value().c_expr().text.toInt() } } } if (offsetClause != null) { if (offsetClause.select_offset_value() != null) { offset = offsetClause.select_offset_value().text.toInt() } if (offsetClause.select_fetch_first_value() != null) { if (offsetClause.select_fetch_first_value().c_expr() != null) { offset = offsetClause.select_fetch_first_value().c_expr().text.toInt() } } } return super.visitSelect_limit(ctx) } // ----------------------------------------private methods------------------------------------ fun parseTableName(ctx: PostgreSqlParser.Any_nameContext): TableId { val attrNames = ctx.attrs()?.attr_name() if (attrNames == null) { return TableId(null, null, ctx.colid().text) } if (attrNames.size == 2) { return TableId(ctx.colid().text, attrNames.get(0).text, attrNames.get(1).text) } else if (attrNames.size == 1) { return TableId(null, ctx.colid().text, attrNames.get(0).text) } throw SQLParserException("parse schema qualified name error") } fun parseTableName(ctx: PostgreSqlParser.Relation_exprContext): TableId { return parseTableName(ctx.qualified_name()) } fun parseTableName(ctx: PostgreSqlParser.Qualified_nameContext): TableId { if (ctx.childCount == 2) { val obj = ctx.getChild(1) if (obj.childCount == 2) { return TableId(ctx.getChild(0).text, obj.getChild(0).getChild(1).text, obj.getChild(1).getChild(1).text) } else if (obj.childCount == 1) { val inEl = obj.getChild(0) as Indirection_elContext return TableId(ctx.colid().text, inEl.attr_name().text) } } else if (ctx.childCount == 1) { return TableId(ctx.getChild(0).text) } throw SQLParserException("parse schema qualified name error") } } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/PostgreSqlHelper.kt ================================================ package io.github.melin.superior.parser.postgre import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlLexer import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParser import io.github.melin.superior.parser.postgre.antlr4.PostgreSqlParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:58 上午 */ object PostgreSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until PostgreSqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = PostgreSqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = PostgreSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = PostgreSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = PostgreSqlParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: PostgreSqlParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = PostgreSqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = PostgreSqlParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) // parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.root()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.root()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/relational/CreatePartitionTable.kt ================================================ package io.github.melin.superior.parser.postgre.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class CreatePartitionTable(override val tableId: TableId, val partitionTableId: TableId) : AbsTableStatement() { // 是否存在 if exists 关键字 override val statementType = StatementType.CREATE_TABLE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/BooleanType.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsType class BooleanType : AbsType() { override val name: String = "boolean" override val alias: String = "bool" } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/JsonType.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsType class JsonType : AbsType() { override val name: String = "json" } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/datetime.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsDataTimeType class DateType : AbsDataTimeType() { override val name: String = "date" } data class TimeType(val precision: Int = 0, val timezone: Boolean = false) : AbsDataTimeType() { override val name: String = "time" override val alias: String = "timez" } data class TimeStampType(val precision: Int = 0, val timezone: Boolean = false) : AbsDataTimeType() { override val name: String = "timestamp" override val alias: String = "timestampz" } class IntervalType : AbsDataTimeType() { override val name: String = "interval" } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/numeric.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsNumericType data class SmallIntType(val length: Int) : AbsNumericType() { override val name: String = "smallint" override val alias: String = "int2" companion object { const val MIN_VALUE: Int = -32768 const val MAX_VALUE: Int = 32767 } } data class IntegerType(val length: Int) : AbsNumericType() { override val name: String = "integer" override val alias: String = "int" override val alias2: String = "int4" companion object { const val MIN_VALUE: Long = -2147483648L const val MAX_VALUE: Long = 2147483647L } } data class BigIntType(val length: Int) : AbsNumericType() { override val name: String = "bigint" override val alias: String = "int8" } data class NumericType(val precision: Int = 10, val scale: Int = 0) : AbsNumericType() { override val name: String = "numeric" override val alias: String = "decimal" } data class FloatType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "float" } data class DoubleType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "double precision" override val alias: String = "float8" } data class RealType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "real" override val alias: String = "float4" } data class SmallserialType(val length: Int) : AbsNumericType() { override val name: String = "smallserial" override val alias: String = "serial2" companion object { const val MIN_VALUE: Int = 1 const val MAX_VALUE: Int = 32767 } } data class SerialType(val length: Int) : AbsNumericType() { override val name: String = "serial" override val alias: String = "serial4" companion object { const val MIN_VALUE: Long = 1 const val MAX_VALUE: Long = 2147483647L } } data class BigserialType(val length: Int) : AbsNumericType() { override val name: String = "bigserial" override val alias: String = "serial8" } data class BitType(val length: Int) : AbsNumericType() { override val name: String = "bit" } data class VarbitType(val length: Int) : AbsNumericType() { override val name: String = "bit varying" override val alias: String = "varbit" } ================================================ FILE: superior-postgres-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/string.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsStringType data class CharType(val length: Int) : AbsStringType() { override val name: String = "char" override val alias: String = "character" companion object { const val MAX_LENGTH: Int = 255 } } data class VarcharType(val length: Int) : AbsStringType() { override val name: String = "varchar" override val alias: String = "character varying" companion object { const val MAX_LENGTH: Int = 65535 } } class TextType : AbsStringType() { override val name: String = "text" } class ByteaType : AbsStringType() { override val name: String = "bytea" } data class EnumType(val typeName: String, val values: List) : AbsStringType() { override val name: String = "enum" } ================================================ FILE: superior-postgres-parser/src/test/java/io/github/melin/superior/parser/postgre/PostgreSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.AlterActionType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.RefreshMaterializedView import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropMaterializedView import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.parser.postgre.relational.CreatePartitionTable import org.junit.Assert import org.junit.Test /** * Created by libinsong on 2020/6/30 11:04 上午 */ class PostgreSqlParserDdlTest { @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE bigdata1; drop DATABASE bigdata2 """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("bigdata1", createDatabse.databaseName) } else { Assert.fail() } if (dropDatabase is DropDatabase) { Assert.assertEquals("bigdata2", dropDatabase.databaseName) } else { Assert.fail() } } @Test fun createSchemaTest() { val sql = """ CREATE schema bigdata1; CREATE schema bigdata2; """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) val createSchema1 = statements.get(0) val createSchema2 = statements.get(1) if (createSchema1 is CreateSchema) { Assert.assertEquals("bigdata1", createSchema1.schemaName) } else { Assert.fail() } if (createSchema2 is CreateSchema) { Assert.assertEquals("bigdata2", createSchema2.schemaName) } else { Assert.fail() } } @Test fun createTable0() { val sql = """ CREATE TEMPORARY TABLE test.public.authors ( id INTEGER NOT NULL PRIMARY KEY, last_name TEXT, first_name TEXT, age int not null ) PARTITION BY RANGE (age); """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertTrue(statement.temporary) Assert.assertEquals(TableId("test", "public", "authors"), statement.tableId) Assert.assertEquals(4, statement.columnRels?.size) Assert.assertTrue(statement.columnRels?.get(0)?.primaryKey!!) Assert.assertEquals(PartitionType.RANGE, statement.partitionType) Assert.assertEquals(1, statement.partitionColumnNames.size) } else { Assert.fail() } } @Test fun createTable1() { val sql = """ CREATE TABLE IF NOT EXISTS sales_range_partitioned3 ( id INT, sales_date DATE, amount DECIMAL(10, 2) ) PARTITION BY RANGE (sales_date) ( PARTITION p2022 VALUES LESS THAN ('2023-01-01'), PARTITION p2023 VALUES LESS THAN ('2024-01-01'), PARTITION p2024 VALUES LESS THAN ('2025-01-01') ); """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals(TableId("sales_range_partitioned3"), statement.tableId) Assert.assertEquals(3, statement.columnRels?.size) Assert.assertEquals(PartitionType.RANGE, statement.partitionType) Assert.assertEquals(1, statement.partitionColumnNames.size) } else { Assert.fail() } } @Test fun createView0() { val sql = """ CREATE OR REPLACE VIEW comedies AS SELECT f.*, country_code_to_name(f.country_code) AS country, (SELECT avg(r.rating) FROM user_ratings r WHERE r.film_id = f.id) AS avg_rating FROM films f WHERE f.kind = 'Comedy' WITH CASCADED CHECK OPTION; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("comedies", statement.tableId.tableName) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun createMatView0() { val sql = """ CREATE MATERIALIZED VIEW sales_summary AS SELECT seller_no, invoice_date, sum(invoice_amt)::numeric(13,2) as sales_amt FROM invoice WHERE invoice_date < CURRENT_DATE GROUP BY seller_no, invoice_date; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateMaterializedView) { Assert.assertEquals(StatementType.CREATE_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals("sales_summary", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun dropMvTest() { val sql = """ DROP MATERIALIZED VIEW tickets_mv; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is DropMaterializedView) { Assert.assertEquals(StatementType.DROP_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) } else { Assert.fail() } } @Test fun refreshMvTest() { val sql = """ REFRESH MATERIALIZED VIEW tickets_mv; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is RefreshMaterializedView) { Assert.assertEquals(StatementType.REFRESH_MV, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) } else { Assert.fail() } } @Test fun renameMvTest() { val sql = """ ALTER MATERIALIZED VIEW tickets_mv RENAME TO tickets_mv_1; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is AlterMaterializedView) { Assert.assertEquals(StatementType.ALTER_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) Assert.assertEquals(AlterActionType.RENAME, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun dropTable0() { val sql = """ drop TABLE test.public.authors """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals(TableId("test", "public", "authors"), statement.tableId) } else { Assert.fail() } } @Test fun dropTable1() { val sql = """ drop TABLE authors, tests """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals(TableId("authors"), statement.tableId) Assert.assertEquals(2, statement.tableIds.size) } else { Assert.fail() } } @Test fun createIndexTest() { val sql = "CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);\n" val statement = PostgreSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("films"), statement.tableId) val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals(AlterActionType.ADD_INDEX, createIndex.alterType) Assert.assertEquals("title_idx", createIndex.indexName) } else { Assert.fail() } } @Test fun dropIndexTest() { val sql = "DROP INDEX title_idx" val statement = PostgreSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { val dropIndex = statement.firstAction() as DropIndex Assert.assertEquals(AlterActionType.DROP_INDEX, dropIndex.alterType) Assert.assertEquals("title_idx", dropIndex.indexName) } else { Assert.fail() } } @Test fun createPartitonTableTest() { val sql = "create table pkslow_person_r1 partition of pkslow_person_r for values from (MINVALUE) to (10); \n" val statement = PostgreSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreatePartitionTable) { Assert.assertEquals("pkslow_person_r", statement.tableId.tableName) Assert.assertEquals("pkslow_person_r1", statement.partitionTableId.tableName) } else { Assert.fail() } } @Test fun commentTest0() { val sql = """ COMMENT ON TABLE my_schema.my_table IS 'Employee Information'; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, statement.statementType) Assert.assertEquals("Employee Information", statement.comment) Assert.assertFalse(statement.isNull) } else { Assert.fail() } } @Test fun alterTableTest() { val sql = """ ALTER TABLE distributors ADD COLUMN address varchar(30), ALTER COLUMN status SET default 'current'; """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) val alterTable1 = statements.get(0) as AlterTable Assert.assertEquals("distributors", alterTable1.tableId.tableName) var action = alterTable1.actions.get(0) as AlterColumnAction Assert.assertEquals(AlterActionType.ADD_COLUMN, action.alterType) Assert.assertEquals("address", action.columName) Assert.assertEquals("varchar(30)", action.dataType) action = alterTable1.actions.get(1) as AlterColumnAction Assert.assertEquals(AlterActionType.SET_COLUMN_DEFAULT, action.alterType) Assert.assertEquals("status", action.columName) Assert.assertEquals("current", action.defaultExpression) } } ================================================ FILE: superior-postgres-parser/src/test/java/io/github/melin/superior/parser/postgre/PostgreSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.table.TruncateTable import org.junit.Assert import org.junit.Test /** * Created by libinsong on 2020/6/30 11:04 上午 */ class PostgreSqlParserDmlTest { @Test fun queryTest0() { val sql = """ select a.* from datacompute1.datacompute.dc_job a left join datacompute1.datacompute.dc_job_scheduler b on a.id=b.job_id LIMIT 3, 2 """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(3, statement.limit) Assert.assertEquals(2, statement.offset) } else { Assert.fail() } } @Test fun queryTest1() { val sql = """ SELECT * FROM public.usertest LIMIT 3 OFFSET 2; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(3, statement.limit) Assert.assertEquals(2, statement.offset) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun queryTest2() { val sql = """ SELECT * FROM public.usertest FETCH FIRST 5 ROWS ONLY; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(5, statement.limit) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun queryTest3() { val sql = """ SELECT * FROM public.usertest OFFSET 10 FETCH FIRST 10 ROWS ONLY; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(10, statement.limit) Assert.assertEquals(10, statement.offset) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun cteSqlTest0() { val sql = """ WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("orders"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun createAsQueryTest0() { val sql = """ CREATE TABLE films_recent AS SELECT * FROM films WHERE date_prod >= '2002-01-01'; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("films_recent", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) Assert.assertEquals("films", statement.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun deleteTest0() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest1() { val sql = """ DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo'; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("producers", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest1() { val sql = """ UPDATE product p SET net_price = price - price * discount FROM product_segment s WHERE p.segment_id = s.id; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("product", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("product_segment", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun insertTest0() { val sql = """ INSERT INTO films (code, title, did, date_prod, kind) VALUES ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(0, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest1() { val sql = """ WITH upd AS ( UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation') RETURNING * ) INSERT INTO employees_log SELECT *, current_timestamp FROM upd; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("employees_log", statement.tableId?.tableName) Assert.assertEquals(2, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest2() { val sql = """ truncate table films INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) var statement = statements.get(0) if (statement is TruncateTable) { Assert.assertEquals(StatementType.TRUNCATE_TABLE, statement.statementType) Assert.assertEquals("films", statement.tableId.tableName) } else { Assert.fail() } statement = statements.get(1) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest() { val sql = """ MERGE INTO wines w USING wine_stock_changes s ON s.winename = w.winename WHEN NOT MATCHED AND s.stock_delta > 0 THEN INSERT VALUES(s.winename, s.stock_delta) WHEN MATCHED AND w.stock + s.stock_delta > 0 THEN UPDATE SET stock = w.stock + s.stock_delta WHEN MATCHED THEN DELETE; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("wines", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-postgres-parser/src/test/java/io/github/melin/superior/parser/postgre/PostgreSqlProcessParserTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.create.CreateFunction import io.github.melin.superior.common.relational.create.CreateProcedure import org.junit.Assert import org.junit.Test class PostgreSqlProcessParserTest { @Test fun createFunctionTest() { val sql = """ CREATE FUNCTION public.myadd(integer, integer) RETURNS integer AS 'select ${'$'}1 + ${'$'}2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("public", "myadd"), statement.functionId) Assert.assertEquals("myadd", statement.functionId.functionName) } else { Assert.fail() } } @Test fun createFunctionTest1() { val sql = """ CREATE FUNCTION myadd(integer, integer) RETURNS integer AS 'select ${'$'}1 + ${'$'}2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("myadd"), statement.functionId) Assert.assertEquals("myadd", statement.functionId.functionName) } else { Assert.fail() } } @Test fun createFunctionTest2() { val sql = """ CREATE FUNCTION check_password(uname TEXT, pass TEXT) RETURNS BOOLEAN AS ${'$'}${'$'} DECLARE passed BOOLEAN; BEGIN SELECT (pwd = ${'$'}2) INTO passed FROM pwds WHERE username = ${'$'}1; RETURN passed; update accounts_2 set balance = balance + amount where id = receiver; END; ${'$'}${'$'} LANGUAGE plpgsql SECURITY DEFINER """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId( "check_password"), statement.functionId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest3() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) LANGUAGE plpgsql as ${'$'}${'$'} DECLARE max_rk int; max_trade_time_length int; max_trade_time character varying; BEGIN update accounts_1 set balance = balance - amount where id = sender; update accounts_2 set balance = balance + amount where id = receiver; commit; END;${'$'}${'$'}; create or replace procedure prac_transfer1( sender int, receiver int, amount dec ) LANGUAGE plpgsql as ${'$'}${'$'} DECLARE max_rk int; max_trade_time_length int; max_trade_time character varying; BEGIN update accounts_1 set balance = balance - amount where id = sender; update accounts_2 set balance = balance + amount where id = receiver; commit; END;${'$'}${'$'}; """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) val statement = statements.get(0) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest4() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) RETURNS SETOF record LANGUAGE plpgsql NOT FENCED NOT SHIPPABLE as ${'$'}${'$'} BEGIN update accounts set balance = balance - amount where id = sender; update accounts set balance = balance + amount where id = receiver; commit; END;${'$'}${'$'}; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest5() { val sql = """ CREATE OR REPLACE FUNCTION fetch_film_titles_and_years( OUT p_title VARCHAR(255), OUT p_release_year INTEGER ) RETURNS SETOF RECORD LANGUAGE plpgsql AS ${'$'}${'$'} DECLARE film_cursor CURSOR FOR SELECT title, release_year FROM film; film_record RECORD; BEGIN -- Open cursor OPEN film_cursor; -- Fetch rows and return LOOP FETCH NEXT FROM film_cursor INTO film_record; EXIT WHEN NOT FOUND; p_title = film_record.title; p_release_year = film_record.release_year; RETURN NEXT; END LOOP; -- Close cursor CLOSE film_cursor; update accounts set balance = balance + amount where id = receiver; END; ${'$'}${'$'} """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId( "fetch_film_titles_and_years"), statement.functionId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest6() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) RETURNS SETOF record LANGUAGE plpgsql NOT FENCED NOT SHIPPABLE as ${'$'}${'$'} BEGIN update accounts set balance = balance - amount where id = sender; commit; END;${'$'}${'$'}; create or replace procedure prac_transfer1( sender int, receiver int, amount dec ) RETURNS SETOF record LANGUAGE plpgsql NOT FENCED NOT SHIPPABLE as ${'$'}${'$'} BEGIN update accounts_1 set balance = balance - amount where id = sender; commit; END;${'$'}${'$'}; """.trimIndent() val statements = PostgreSqlHelper.parseMultiStatement(sql) Assert.assertEquals(2, statements.size) var statement = statements.get(0) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer"), statement.procedureId) Assert.assertEquals(1, statement.childStatements.size) } else { Assert.fail() } statement = statements.get(1) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer1"), statement.procedureId) Assert.assertEquals(1, statement.childStatements.size) Assert.assertEquals("update accounts_1\n" + " set balance = balance - amount \n" + " where id = sender", statement.childStatements.get(0).getSql()) } else { Assert.fail() } } @Test fun processTest5() { val sql = """ CREATE FUNCTION get_bal(acc_no IN NUMBER) RETURNS SETOF record LANGUAGE plpgsql NOT FENCED NOT SHIPPABLE as ${'$'}${'$'} BEGIN INSERT INTO widgets(map_id,widget_name) SELECT mt.map_id, 'Bupo' FROM map_tags mt WHERE mt.map_license = '12345'; END ${'$'}${'$'}; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("get_bal"), statement.functionId) Assert.assertEquals(1, statement.childStatements.size) Assert.assertEquals(StatementType.INSERT, statement.childStatements.get(0).statementType) } else { Assert.fail() } } @Test fun processTest6() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) LANGUAGE plpgsql as ${'$'}${'$'} BEGIN EXECUTE IMMEDIATE ' CREATE TABLE schema1.test_table_s1 ( id NUMBER PRIMARY KEY, name VARCHAR2(100) ) '; EXECUTE IMMEDIATE 'INSERT INTO schema1.test_table_s1 (id, name) VALUES (1, ''Alice'')'; END ${'$'}${'$'}; """.trimIndent() val statement = PostgreSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId("prac_transfer"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) Assert.assertEquals(StatementType.CREATE_TABLE, statement.childStatements.get(0).statementType) Assert.assertEquals(StatementType.INSERT, statement.childStatements.get(1).statementType) Assert.assertEquals("INSERT INTO schema1.test_table_s1 (id, name) VALUES (1, 'Alice')", statement.childStatements.get(1).getSql()) } else { Assert.fail() } } } ================================================ FILE: superior-postgres-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-presto-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-presto-parser superior-presto-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-presto-parser/src/main/antlr4/io/github/melin/superior/parser/presto/antlr4/PrestoSqlBase.g4 ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ grammar PrestoSqlBase; tokens { DELIMITER } sqlStatements : singleStatement* EOF ; singleStatement : statement ';'? ; standaloneExpression : expression EOF ; standaloneRoutineBody : routineBody EOF ; statement : query #statementDefault | USE schema=identifier #use | USE catalog=identifier '.' schema=identifier #use | CREATE SCHEMA (IF NOT EXISTS)? qualifiedName (WITH properties)? #createSchema | DROP SCHEMA (IF EXISTS)? qualifiedName (CASCADE | RESTRICT)? #dropSchema | ALTER SCHEMA qualifiedName RENAME TO identifier #renameSchema | CREATE TABLE (IF NOT EXISTS)? qualifiedName columnAliases? (COMMENT string)? (WITH properties)? AS (query | '('query')') (WITH (NO)? DATA)? #createTableAsSelect | CREATE TABLE (IF NOT EXISTS)? qualifiedName '(' tableElement (',' tableElement)* ')' (COMMENT string)? (WITH properties)? #createTable | DROP TABLE (IF EXISTS)? qualifiedName #dropTable | INSERT INTO qualifiedName columnAliases? query #insertInto | DELETE FROM qualifiedName whereClause? #delete | TRUNCATE TABLE qualifiedName #truncateTable | ALTER TABLE (IF EXISTS)? from=qualifiedName RENAME TO to=qualifiedName #renameTable | ALTER TABLE (IF EXISTS)? tableName=qualifiedName RENAME COLUMN (IF EXISTS)? from=identifier TO to=identifier #renameColumn | ALTER TABLE (IF EXISTS)? tableName=qualifiedName DROP COLUMN (IF EXISTS)? column=qualifiedName #dropColumn | ALTER TABLE (IF EXISTS)? tableName=qualifiedName ADD COLUMN (IF NOT EXISTS)? column=columnDefinition #addColumn | ANALYZE qualifiedName (WITH properties)? #analyze | CREATE TYPE qualifiedName AS ( '(' sqlParameterDeclaration (',' sqlParameterDeclaration)* ')' | type) #createType | CREATE (OR REPLACE)? VIEW qualifiedName (SECURITY (DEFINER | INVOKER))? AS query #createView | DROP VIEW (IF EXISTS)? qualifiedName #dropView | CREATE MATERIALIZED VIEW (IF NOT EXISTS)? qualifiedName (COMMENT string)? (WITH properties)? AS (query | '('query')') #createMaterializedView | DROP MATERIALIZED VIEW (IF EXISTS)? qualifiedName #dropMaterializedView | REFRESH MATERIALIZED VIEW qualifiedName WHERE booleanExpression #refreshMaterializedView | CREATE (OR REPLACE)? TEMPORARY? FUNCTION functionName=qualifiedName '(' (sqlParameterDeclaration (',' sqlParameterDeclaration)*)? ')' RETURNS returnType=type (COMMENT string)? routineCharacteristics routineBody #createFunction | ALTER FUNCTION qualifiedName types? alterRoutineCharacteristics #alterFunction | DROP TEMPORARY? FUNCTION (IF EXISTS)? qualifiedName types? #dropFunction | CALL qualifiedName '(' (callArgument (',' callArgument)*)? ')' #call | CREATE ROLE name=identifier (WITH ADMIN grantor)? #createRole | DROP ROLE name=identifier #dropRole | GRANT roles TO principal (',' principal)* (WITH ADMIN OPTION)? (GRANTED BY grantor)? #grantRoles | REVOKE (ADMIN OPTION FOR)? roles FROM principal (',' principal)* (GRANTED BY grantor)? #revokeRoles | SET ROLE (ALL | NONE | role=identifier) #setRole | GRANT (privilege (',' privilege)* | ALL PRIVILEGES) ON TABLE? qualifiedName TO grantee=principal (WITH GRANT OPTION)? #grant | REVOKE (GRANT OPTION FOR)? (privilege (',' privilege)* | ALL PRIVILEGES) ON TABLE? qualifiedName FROM grantee=principal #revoke | SHOW GRANTS (ON TABLE? qualifiedName)? #showGrants | EXPLAIN ANALYZE? VERBOSE? ('(' explainOption (',' explainOption)* ')')? statement #explain | SHOW CREATE TABLE qualifiedName #showCreateTable | SHOW CREATE VIEW qualifiedName #showCreateView | SHOW CREATE MATERIALIZED VIEW qualifiedName #showCreateMaterializedView | SHOW CREATE FUNCTION qualifiedName types? #showCreateFunction | SHOW TABLES ((FROM | IN) qualifiedName)? (LIKE pattern=string (ESCAPE escape=string)?)? #showTables | SHOW SCHEMAS ((FROM | IN) identifier)? (LIKE pattern=string (ESCAPE escape=string)?)? #showSchemas | SHOW CATALOGS (LIKE pattern=string (ESCAPE escape=string)?)? #showCatalogs | SHOW COLUMNS (FROM | IN) qualifiedName #showColumns | SHOW STATS FOR qualifiedName #showStats | SHOW STATS FOR '(' querySpecification ')' #showStatsForQuery | SHOW CURRENT? ROLES ((FROM | IN) identifier)? #showRoles | SHOW ROLE GRANTS ((FROM | IN) identifier)? #showRoleGrants | DESCRIBE qualifiedName #showColumns | DESC qualifiedName #showColumns | SHOW FUNCTIONS (LIKE pattern=string (ESCAPE escape=string)?)? #showFunctions | SHOW SESSION (LIKE pattern=string (ESCAPE escape=string)?)? #showSession | SET SESSION qualifiedName EQ expression #setSession | RESET SESSION qualifiedName #resetSession | START TRANSACTION (transactionMode (',' transactionMode)*)? #startTransaction | COMMIT WORK? #commit | ROLLBACK WORK? #rollback | PREPARE identifier FROM statement #prepare | DEALLOCATE PREPARE identifier #deallocate | EXECUTE identifier (USING expression (',' expression)*)? #execute | DESCRIBE INPUT identifier #describeInput | DESCRIBE OUTPUT identifier #describeOutput ; query : with? queryNoWith ; with : WITH RECURSIVE? namedQuery (',' namedQuery)* ; tableElement : columnDefinition | likeClause ; columnDefinition : identifier type (NOT NULL)? (COMMENT string)? (WITH properties)? ; likeClause : LIKE qualifiedName (optionType=(INCLUDING | EXCLUDING) PROPERTIES)? ; properties : '(' property (',' property)* ')' ; property : identifier EQ expression ; sqlParameterDeclaration : identifier type ; routineCharacteristics : routineCharacteristic* ; routineCharacteristic : LANGUAGE language | determinism | nullCallClause ; alterRoutineCharacteristics : alterRoutineCharacteristic* ; alterRoutineCharacteristic : nullCallClause ; routineBody : returnStatement | externalBodyReference ; returnStatement : RETURN expression ; externalBodyReference : EXTERNAL (NAME externalRoutineName)? ; language : SQL | identifier ; determinism : DETERMINISTIC | NOT DETERMINISTIC; nullCallClause : RETURNS NULL ON NULL INPUT | CALLED ON NULL INPUT ; externalRoutineName : identifier ; queryNoWith: queryTerm (ORDER BY sortItem (',' sortItem)*)? (OFFSET offset=INTEGER_VALUE (ROW | ROWS)?)? ((LIMIT limit=(INTEGER_VALUE | ALL) | (FETCH FIRST fetchFirstNRows=INTEGER_VALUE ROWS ONLY))?)? ; queryTerm : queryPrimary #queryTermDefault | left=queryTerm operator=INTERSECT setQuantifier? right=queryTerm #setOperation | left=queryTerm operator=(UNION | EXCEPT) setQuantifier? right=queryTerm #setOperation ; queryPrimary : querySpecification #queryPrimaryDefault | TABLE qualifiedName #table | VALUES expression (',' expression)* #inlineTable | '(' queryNoWith ')' #subquery ; sortItem : expression ordering=(ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; querySpecification : SELECT setQuantifier? selectItem (',' selectItem)* (FROM relation (',' relation)*)? (WHERE where=booleanExpression)? (GROUP BY groupBy)? (HAVING having=booleanExpression)? ; groupBy : setQuantifier? groupingElement (',' groupingElement)* ; groupingElement : groupingSet #singleGroupingSet | ROLLUP '(' (expression (',' expression)*)? ')' #rollup | CUBE '(' (expression (',' expression)*)? ')' #cube | GROUPING SETS '(' groupingSet (',' groupingSet)* ')' #multipleGroupingSets ; groupingSet : '(' (expression (',' expression)*)? ')' | expression ; namedQuery : name=identifier (columnAliases)? AS '(' query ')' ; setQuantifier : DISTINCT | ALL ; selectItem : expression (AS? identifier)? #selectSingle | qualifiedName '.' ASTERISK #selectAll | ASTERISK #selectAll ; relation : left=relation ( CROSS JOIN right=sampledRelation | joinType JOIN rightRelation=relation joinCriteria | NATURAL joinType JOIN right=sampledRelation ) #joinRelation | sampledRelation #relationDefault ; joinType : INNER? | LEFT OUTER? | RIGHT OUTER? | FULL OUTER? ; joinCriteria : ON booleanExpression | USING '(' identifier (',' identifier)* ')' ; sampledRelation : aliasedRelation ( TABLESAMPLE sampleType '(' percentage=expression ')' )? ; sampleType : BERNOULLI | SYSTEM ; aliasedRelation : relationPrimary (AS? identifier columnAliases?)? ; columnAliases : '(' identifier (',' identifier)* ')' ; relationPrimary : qualifiedName #tableName | '(' query ')' #subqueryRelation | UNNEST '(' expression (',' expression)* ')' (WITH ORDINALITY)? #unnest | LATERAL '(' query ')' #lateral | '(' relation ')' #parenthesizedRelation ; expression : booleanExpression ; whereClause : WHERE booleanExpression ; booleanExpression : valueExpression predicate[$valueExpression.ctx]? #predicated | NOT booleanExpression #logicalNot | left=booleanExpression operator=AND right=booleanExpression #logicalBinary | left=booleanExpression operator=OR right=booleanExpression #logicalBinary ; // workaround for https://github.com/antlr/antlr4/issues/780 predicate[ParserRuleContext value] : comparisonOperator right=valueExpression #comparison | comparisonOperator comparisonQuantifier '(' query ')' #quantifiedComparison | NOT? BETWEEN lower=valueExpression AND upper=valueExpression #between | NOT? IN '(' expression (',' expression)* ')' #inList | NOT? IN '(' query ')' #inSubquery | NOT? LIKE pattern=valueExpression (ESCAPE escape=valueExpression)? #like | IS NOT? NULL #nullPredicate | IS NOT? DISTINCT FROM right=valueExpression #distinctFrom ; valueExpression : primaryExpression #valueExpressionDefault | valueExpression AT timeZoneSpecifier #atTimeZone | operator=(MINUS | PLUS) valueExpression #arithmeticUnary | left=valueExpression operator=(ASTERISK | SLASH | PERCENT) right=valueExpression #arithmeticBinary | left=valueExpression operator=(PLUS | MINUS) right=valueExpression #arithmeticBinary | left=valueExpression CONCAT right=valueExpression #concatenation ; primaryExpression : NULL #nullLiteral | interval #intervalLiteral | identifier string #typeConstructor | DOUBLE_PRECISION string #typeConstructor | number #numericLiteral | booleanValue #booleanLiteral | string #stringLiteral | BINARY_LITERAL #binaryLiteral | '?' #parameter | POSITION '(' valueExpression IN valueExpression ')' #position | '(' expression (',' expression)+ ')' #rowConstructor | ROW '(' expression (',' expression)* ')' #rowConstructor | qualifiedName '(' ASTERISK ')' filter? over? #functionCall | qualifiedName '(' (setQuantifier? expression (',' expression)*)? (ORDER BY sortItem (',' sortItem)*)? ')' filter? (nullTreatment? over)? #functionCall | identifier '->' expression #lambda | '(' (identifier (',' identifier)*)? ')' '->' expression #lambda | '(' query ')' #subqueryExpression // This is an extension to ANSI SQL, which considers EXISTS to be a | EXISTS '(' query ')' #exists | CASE valueExpression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | CAST '(' expression AS type ')' #cast | TRY_CAST '(' expression AS type ')' #cast | ARRAY '[' (expression (',' expression)*)? ']' #arrayConstructor | value=primaryExpression '[' index=valueExpression ']' #subscript | identifier #columnReference | base=primaryExpression '.' fieldName=identifier #dereference | name=CURRENT_DATE #specialDateTimeFunction | name=CURRENT_TIME ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction | name=CURRENT_TIMESTAMP ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction | name=LOCALTIME ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction | name=LOCALTIMESTAMP ('(' precision=INTEGER_VALUE ')')? #specialDateTimeFunction | name=CURRENT_USER #currentUser | SUBSTRING '(' valueExpression FROM valueExpression (FOR valueExpression)? ')' #substring | NORMALIZE '(' valueExpression (',' normalForm)? ')' #normalize | EXTRACT '(' identifier FROM valueExpression ')' #extract | '(' expression ')' #parenthesizedExpression | GROUPING '(' (qualifiedName (',' qualifiedName)*)? ')' #groupingOperation ; string : STRING #basicStringLiteral | UNICODE_STRING (UESCAPE STRING)? #unicodeStringLiteral ; nullTreatment : IGNORE NULLS | RESPECT NULLS ; timeZoneSpecifier : TIME ZONE interval #timeZoneInterval | TIME ZONE string #timeZoneString ; comparisonOperator : EQ | NEQ | LT | LTE | GT | GTE ; comparisonQuantifier : ALL | SOME | ANY ; booleanValue : TRUE | FALSE ; interval : INTERVAL sign=(PLUS | MINUS)? string from=intervalField (TO to=intervalField)? ; intervalField : YEAR | MONTH | DAY | HOUR | MINUTE | SECOND ; normalForm : NFD | NFC | NFKD | NFKC ; types : '(' (type (',' type)*)? ')' ; type : type ARRAY | ARRAY '<' type '>' | MAP '<' type ',' type '>' | ROW '(' identifier type (',' identifier type)* ')' | baseType ('(' typeParameter (',' typeParameter)* ')')? | INTERVAL from=intervalField TO to=intervalField ; typeParameter : INTEGER_VALUE | type ; baseType : TIME_WITH_TIME_ZONE | TIMESTAMP_WITH_TIME_ZONE | DOUBLE_PRECISION | qualifiedName ; whenClause : WHEN condition=expression THEN result=expression ; filter : FILTER '(' WHERE booleanExpression ')' ; over : OVER '(' (PARTITION BY partition+=expression (',' partition+=expression)*)? (ORDER BY sortItem (',' sortItem)*)? windowFrame? ')' ; windowFrame : frameType=RANGE start=frameBound | frameType=ROWS start=frameBound | frameType=GROUPS start=frameBound | frameType=RANGE BETWEEN start=frameBound AND end=frameBound | frameType=ROWS BETWEEN start=frameBound AND end=frameBound | frameType=GROUPS BETWEEN start=frameBound AND end=frameBound ; frameBound : UNBOUNDED boundType=PRECEDING #unboundedFrame | UNBOUNDED boundType=FOLLOWING #unboundedFrame | CURRENT ROW #currentRowBound | expression boundType=(PRECEDING | FOLLOWING) #boundedFrame // expression should be unsignedLiteral ; explainOption : FORMAT value=(TEXT | GRAPHVIZ | JSON) #explainFormat | TYPE value=(LOGICAL | DISTRIBUTED | VALIDATE | IO) #explainType ; transactionMode : ISOLATION LEVEL levelOfIsolation #isolationLevel | READ accessMode=(ONLY | WRITE) #transactionAccessMode ; levelOfIsolation : READ UNCOMMITTED #readUncommitted | READ COMMITTED #readCommitted | REPEATABLE READ #repeatableRead | SERIALIZABLE #serializable ; callArgument : expression #positionalArgument | identifier '=>' expression #namedArgument ; privilege : SELECT | DELETE | INSERT | identifier ; qualifiedName : identifier ('.' identifier)* ; grantor : CURRENT_USER #currentUserGrantor | CURRENT_ROLE #currentRoleGrantor | principal #specifiedPrincipal ; principal : USER identifier #userPrincipal | ROLE identifier #rolePrincipal | identifier #unspecifiedPrincipal ; roles : identifier (',' identifier)* ; identifier : IDENTIFIER #unquotedIdentifier | QUOTED_IDENTIFIER #quotedIdentifier | nonReserved #unquotedIdentifier | BACKQUOTED_IDENTIFIER #backQuotedIdentifier | DIGIT_IDENTIFIER #digitIdentifier ; number : DECIMAL_VALUE #decimalLiteral | DOUBLE_VALUE #doubleLiteral | INTEGER_VALUE #integerLiteral ; nonReserved // IMPORTANT: this rule must only contain tokens. Nested rules are not supported. See SqlParser.exitNonReserved : ADD | ADMIN | ALL | ANALYZE | ANY | ARRAY | ASC | AT | BERNOULLI | CALL | CALLED | CASCADE | CATALOGS | COLUMN | COLUMNS | COMMENT | COMMIT | COMMITTED | CURRENT | CURRENT_ROLE | DATA | DATE | DAY | DEFINER | DESC | DETERMINISTIC | DISTRIBUTED | EXCLUDING | EXPLAIN | EXTERNAL | FETCH | FILTER | FIRST | FOLLOWING | FORMAT | FUNCTION | FUNCTIONS | GRANT | GRANTED | GRANTS | GRAPHVIZ | GROUPS | HOUR | IF | IGNORE | INCLUDING | INPUT | INTERVAL | INVOKER | IO | ISOLATION | JSON | LANGUAGE | LAST | LATERAL | LEVEL | LIMIT | LOGICAL | MAP | MATERIALIZED | MINUTE | MONTH | NAME | NFC | NFD | NFKC | NFKD | NO | NONE | NULLIF | NULLS | OFFSET | ONLY | OPTION | ORDINALITY | OUTPUT | OVER | PARTITION | PARTITIONS | POSITION | PRECEDING | PRIVILEGES | PROPERTIES | RANGE | READ | REFRESH | RENAME | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | RETURN | RETURNS | REVOKE | ROLE | ROLES | ROLLBACK | ROW | ROWS | SCHEMA | SCHEMAS | SECOND | SECURITY | SERIALIZABLE | SESSION | SET | SETS | SQL | SHOW | SOME | START | STATS | SUBSTRING | SYSTEM | TABLES | TABLESAMPLE | TEMPORARY | TEXT | TIME | TIMESTAMP | TO | TRANSACTION | TRUNCATE | TRY_CAST | TYPE | UNBOUNDED | UNCOMMITTED | USE | USER | VALIDATE | VERBOSE | VIEW | WORK | WRITE | YEAR | ZONE ; ADD: 'ADD'; ADMIN: 'ADMIN'; ALL: 'ALL'; ALTER: 'ALTER'; ANALYZE: 'ANALYZE'; AND: 'AND'; ANY: 'ANY'; ARRAY: 'ARRAY'; AS: 'AS'; ASC: 'ASC'; AT: 'AT'; BERNOULLI: 'BERNOULLI'; BETWEEN: 'BETWEEN'; BY: 'BY'; CALL: 'CALL'; CALLED: 'CALLED'; CASCADE: 'CASCADE'; CASE: 'CASE'; CAST: 'CAST'; CATALOGS: 'CATALOGS'; COLUMN: 'COLUMN'; COLUMNS: 'COLUMNS'; COMMENT: 'COMMENT'; COMMIT: 'COMMIT'; COMMITTED: 'COMMITTED'; CONSTRAINT: 'CONSTRAINT'; CREATE: 'CREATE'; CROSS: 'CROSS'; CUBE: 'CUBE'; CURRENT: 'CURRENT'; CURRENT_DATE: 'CURRENT_DATE'; CURRENT_ROLE: 'CURRENT_ROLE'; CURRENT_TIME: 'CURRENT_TIME'; CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'; CURRENT_USER: 'CURRENT_USER'; DATA: 'DATA'; DATE: 'DATE'; DAY: 'DAY'; DEALLOCATE: 'DEALLOCATE'; DEFINER: 'DEFINER'; DELETE: 'DELETE'; DESC: 'DESC'; DESCRIBE: 'DESCRIBE'; DETERMINISTIC: 'DETERMINISTIC'; DISTINCT: 'DISTINCT'; DISTRIBUTED: 'DISTRIBUTED'; DROP: 'DROP'; ELSE: 'ELSE'; END: 'END'; ESCAPE: 'ESCAPE'; EXCEPT: 'EXCEPT'; EXCLUDING: 'EXCLUDING'; EXECUTE: 'EXECUTE'; EXISTS: 'EXISTS'; EXPLAIN: 'EXPLAIN'; EXTRACT: 'EXTRACT'; EXTERNAL: 'EXTERNAL'; FALSE: 'FALSE'; FETCH: 'FETCH'; FILTER: 'FILTER'; FIRST: 'FIRST'; FOLLOWING: 'FOLLOWING'; FOR: 'FOR'; FORMAT: 'FORMAT'; FROM: 'FROM'; FULL: 'FULL'; FUNCTION: 'FUNCTION'; FUNCTIONS: 'FUNCTIONS'; GRANT: 'GRANT'; GRANTED: 'GRANTED'; GRANTS: 'GRANTS'; GRAPHVIZ: 'GRAPHVIZ'; GROUP: 'GROUP'; GROUPING: 'GROUPING'; GROUPS: 'GROUPS'; HAVING: 'HAVING'; HOUR: 'HOUR'; IF: 'IF'; IGNORE: 'IGNORE'; IN: 'IN'; INCLUDING: 'INCLUDING'; INNER: 'INNER'; INPUT: 'INPUT'; INSERT: 'INSERT'; INTERSECT: 'INTERSECT'; INTERVAL: 'INTERVAL'; INTO: 'INTO'; INVOKER: 'INVOKER'; IO: 'IO'; IS: 'IS'; ISOLATION: 'ISOLATION'; JSON: 'JSON'; JOIN: 'JOIN'; LANGUAGE: 'LANGUAGE'; LAST: 'LAST'; LATERAL: 'LATERAL'; LEFT: 'LEFT'; LEVEL: 'LEVEL'; LIKE: 'LIKE'; LIMIT: 'LIMIT'; LOCALTIME: 'LOCALTIME'; LOCALTIMESTAMP: 'LOCALTIMESTAMP'; LOGICAL: 'LOGICAL'; MAP: 'MAP'; MATERIALIZED: 'MATERIALIZED'; MINUTE: 'MINUTE'; MONTH: 'MONTH'; NAME: 'NAME'; NATURAL: 'NATURAL'; NFC : 'NFC'; NFD : 'NFD'; NFKC : 'NFKC'; NFKD : 'NFKD'; NO: 'NO'; NONE: 'NONE'; NORMALIZE: 'NORMALIZE'; NOT: 'NOT'; NULL: 'NULL'; NULLIF: 'NULLIF'; NULLS: 'NULLS'; OFFSET: 'OFFSET'; ON: 'ON'; ONLY: 'ONLY'; OPTION: 'OPTION'; OR: 'OR'; ORDER: 'ORDER'; ORDINALITY: 'ORDINALITY'; OUTER: 'OUTER'; OUTPUT: 'OUTPUT'; OVER: 'OVER'; PARTITION: 'PARTITION'; PARTITIONS: 'PARTITIONS'; POSITION: 'POSITION'; PRECEDING: 'PRECEDING'; PREPARE: 'PREPARE'; PRIVILEGES: 'PRIVILEGES'; PROPERTIES: 'PROPERTIES'; RANGE: 'RANGE'; READ: 'READ'; RECURSIVE: 'RECURSIVE'; REFRESH: 'REFRESH'; RENAME: 'RENAME'; REPEATABLE: 'REPEATABLE'; REPLACE: 'REPLACE'; RESET: 'RESET'; RESPECT: 'RESPECT'; RESTRICT: 'RESTRICT'; RETURN: 'RETURN'; RETURNS: 'RETURNS'; REVOKE: 'REVOKE'; RIGHT: 'RIGHT'; ROLE: 'ROLE'; ROLES: 'ROLES'; ROLLBACK: 'ROLLBACK'; ROLLUP: 'ROLLUP'; ROW: 'ROW'; ROWS: 'ROWS'; SCHEMA: 'SCHEMA'; SCHEMAS: 'SCHEMAS'; SECOND: 'SECOND'; SECURITY: 'SECURITY'; SELECT: 'SELECT'; SERIALIZABLE: 'SERIALIZABLE'; SESSION: 'SESSION'; SET: 'SET'; SETS: 'SETS'; SHOW: 'SHOW'; SOME: 'SOME'; SQL: 'SQL'; START: 'START'; STATS: 'STATS'; SUBSTRING: 'SUBSTRING'; SYSTEM: 'SYSTEM'; TABLE: 'TABLE'; TABLES: 'TABLES'; TABLESAMPLE: 'TABLESAMPLE'; TEMPORARY: 'TEMPORARY'; TEXT: 'TEXT'; THEN: 'THEN'; TIME: 'TIME'; TIMESTAMP: 'TIMESTAMP'; TO: 'TO'; TRANSACTION: 'TRANSACTION'; TRUE: 'TRUE'; TRUNCATE: 'TRUNCATE'; TRY_CAST: 'TRY_CAST'; TYPE: 'TYPE'; UESCAPE: 'UESCAPE'; UNBOUNDED: 'UNBOUNDED'; UNCOMMITTED: 'UNCOMMITTED'; UNION: 'UNION'; UNNEST: 'UNNEST'; USE: 'USE'; USER: 'USER'; USING: 'USING'; VALIDATE: 'VALIDATE'; VALUES: 'VALUES'; VERBOSE: 'VERBOSE'; VIEW: 'VIEW'; WHEN: 'WHEN'; WHERE: 'WHERE'; WITH: 'WITH'; WORK: 'WORK'; WRITE: 'WRITE'; YEAR: 'YEAR'; ZONE: 'ZONE'; EQ : '='; NEQ : '<>' | '!='; LT : '<'; LTE : '<='; GT : '>'; GTE : '>='; PLUS: '+'; MINUS: '-'; ASTERISK: '*'; SLASH: '/'; PERCENT: '%'; CONCAT: '||'; STRING : '\'' ( ~'\'' | '\'\'' )* '\'' ; UNICODE_STRING : 'U&\'' ( ~'\'' | '\'\'' )* '\'' ; // Note: we allow any character inside the binary literal and validate // its a correct literal when the AST is being constructed. This // allows us to provide more meaningful error messages to the user BINARY_LITERAL : 'X\'' (~'\'')* '\'' ; INTEGER_VALUE : DIGIT+ ; DECIMAL_VALUE : DIGIT+ '.' DIGIT* | '.' DIGIT+ ; DOUBLE_VALUE : DIGIT+ ('.' DIGIT*)? EXPONENT | '.' DIGIT+ EXPONENT ; IDENTIFIER : (LETTER | '_') (LETTER | DIGIT | '_' | '@' | ':')* ; DIGIT_IDENTIFIER : DIGIT (LETTER | DIGIT | '_' | '@' | ':')+ ; QUOTED_IDENTIFIER : '"' ( ~'"' | '""' )* '"' ; BACKQUOTED_IDENTIFIER : '`' ( ~'`' | '``' )* '`' ; TIME_WITH_TIME_ZONE : 'TIME' WS 'WITH' WS 'TIME' WS 'ZONE' ; TIMESTAMP_WITH_TIME_ZONE : 'TIMESTAMP' WS 'WITH' WS 'TIME' WS 'ZONE' ; DOUBLE_PRECISION : 'DOUBLE' WS 'PRECISION' ; fragment EXPONENT : 'E' [+-]? DIGIT+ ; fragment DIGIT : [0-9] ; fragment LETTER : [A-Z] ; SIMPLE_COMMENT : '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) ; BRACKETED_COMMENT : '/*' .*? '*/' -> channel(HIDDEN) ; WS : [ \r\n\t]+ -> channel(HIDDEN) ; // Catch-all for anything we can't recognize. // We use this to be able to ignore and recover all the text // when splitting statements with DelimiterLexer UNRECOGNIZED : . ; ================================================ FILE: superior-presto-parser/src/main/java/io/github/melin/superior/parser/presto/CaseInsensitiveStream.java ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.github.melin.superior.parser.presto; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.IntStream; import org.antlr.v4.runtime.misc.Interval; public class CaseInsensitiveStream implements CharStream { private final CharStream stream; public CaseInsensitiveStream(CharStream stream) { this.stream = stream; } @Override public String getText(Interval interval) { return stream.getText(interval); } @Override public void consume() { stream.consume(); } @Override public int LA(int i) { int result = stream.LA(i); switch (result) { case 0: case IntStream.EOF: return result; default: return Character.toUpperCase(result); } } @Override public int mark() { return stream.mark(); } @Override public void release(int marker) { stream.release(marker); } @Override public int index() { return stream.index(); } @Override public void seek(int index) { stream.seek(index); } @Override public int size() { return stream.size(); } @Override public String getSourceName() { return stream.getSourceName(); } } ================================================ FILE: superior-presto-parser/src/main/kotlin/io/github/melin/superior/parser/presto/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.presto import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(PrestoSqlBaseParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: PrestoSqlBaseParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(PrestoSqlBaseParser._ATN)) } } ================================================ FILE: superior-presto-parser/src/main/kotlin/io/github/melin/superior/parser/presto/PrestoSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.presto import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.DeleteTable import io.github.melin.superior.common.relational.dml.InsertMode import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseBaseVisitor import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseParser import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ class PrestoSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : PrestoSqlBaseBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() private var functionNames: HashSet = hashSetOf() private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitSqlStatements(ctx: PrestoSqlBaseParser.SqlStatementsContext): Statement? { ctx.singleStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSingleStatement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() cteTempTables = arrayListOf() } override fun visitStatementDefault(ctx: PrestoSqlBaseParser.StatementDefaultContext): Statement? { if (StringUtils.equalsIgnoreCase("select", ctx.start.text)) { currentOptType = StatementType.SELECT super.visitQuery(ctx.query()) val limit = ctx.query()?.queryNoWith()?.limit?.text?.toInt() return QueryStmt(inputTables, limit) } else { return null } } private fun parseQuery(ctx: PrestoSqlBaseParser.QueryContext): QueryStmt { currentOptType = StatementType.SELECT this.visitQuery(ctx) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) val querySql = source(ctx) queryStmt.setSql(querySql) return queryStmt } override fun visitCreateTableAsSelect(ctx: PrestoSqlBaseParser.CreateTableAsSelectContext): Statement? { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val tableId = parseTableName(ctx.qualifiedName()) val queryStmt = parseQuery(ctx.query()) val createTable = CreateTableAsSelect(tableId, queryStmt) createTable.lifeCycle = 7 return createTable } override fun visitInsertInto(ctx: PrestoSqlBaseParser.InsertIntoContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val queryStmt = parseQuery(ctx.query()) val stmt = InsertTable(InsertMode.INTO, queryStmt, tableId) return stmt } override fun visitDelete(ctx: PrestoSqlBaseParser.DeleteContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.qualifiedName()) if (ctx.whereClause() != null) { super.visitWhereClause(ctx.whereClause()) } return DeleteTable(tableId, inputTables) } override fun visitDropTable(ctx: PrestoSqlBaseParser.DropTableContext): Statement? { val tableId = parseTableName(ctx.qualifiedName()) val dropTable = DropTable(tableId) dropTable.ifExists = ctx.EXISTS() != null return dropTable } override fun visitExplain(ctx: PrestoSqlBaseParser.ExplainContext): Statement? { return DefaultStatement(StatementType.EXPLAIN) } override fun visitQualifiedName(ctx: PrestoSqlBaseParser.QualifiedNameContext): Statement? { if (!(ctx.parent is PrestoSqlBaseParser.TableNameContext)) { return null } if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.INSERT || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.CREATE_TABLE_AS_SELECT ) { val tableName = parseTableName(ctx) inputTables.add(tableName) } return null } private fun parseTableName(ctx: PrestoSqlBaseParser.QualifiedNameContext): TableId { val list = ctx.identifier() var catalogName: String? = null var databaseName: String? = null val tableName = if (list.size == 1) { ctx.text } else if (list.size == 2) { val index = StringUtils.lastIndexOf(ctx.text, ".") databaseName = StringUtils.substring(ctx.text, 0, index) StringUtils.substring(ctx.text, index + 1) } else { val items = StringUtils.split(ctx.text, ".") catalogName = items[0] databaseName = items[1] items[2] } return TableId(catalogName, databaseName, tableName) } } ================================================ FILE: superior-presto-parser/src/main/kotlin/io/github/melin/superior/parser/presto/PrestoSqlHelper.kt ================================================ package io.github.melin.superior.parser.presto import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseBaseVisitor import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseLexer import io.github.melin.superior.parser.presto.antlr4.PrestoSqlBaseParser import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object PrestoSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until PrestoSqlBaseLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = PrestoSqlBaseLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = PrestoSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = PrestoSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = PrestoSqlBaseBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: PrestoSqlBaseBaseVisitor) { val charStream = CaseInsensitiveStream(CharStreams.fromString(command)) val lexer = PrestoSqlBaseLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = PrestoSqlBaseParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-presto-parser/src/test/kotlin/io/github/melin/superior/parser/presto/PrestoSqlParserTest.kt ================================================ package io.github.melin.superior.parser.presto import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.DeleteTable import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.drop.DropTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class PrestoSqlParserTest { @Test fun queryTest0() { val sql = """ select a.* from datacompute1.datacompute.dc_job a left join datacompute1.datacompute.dc_job_scheduler b on a.id=b.job_id """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryTest1() { val sql = """ SELECT COUNT(app_name) AS "应用名" FROM (SELECT * FROM ops.dwd_app_to_container_wt WHERE ds=date_format(CURRENT_DATE - interval '1' DAY, "%Y%m%d") ) tdbi_view """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryLimitTest() { val sql = """ select * from preso_table limit 10 """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(10, statement.limit) } else { Assert.fail() } } @Test fun createTableSelectTest() { val sql = """ create table dd_s_s as select * from bigdata.test_demo_test limit 1 """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("dd_s_s", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun dropTableTest() { val sql = """ drop table if exists bigdata.tdl_small_files_2 """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals("bigdata", statement.tableId.schemaName) Assert.assertEquals("tdl_small_files_2", statement.tableId.tableName) } else { Assert.fail() } } @Test fun insertTest() { val sql = """ insert into orders select * from new_orders; """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("orders", statement.tableId.tableName) } else { Assert.fail() } } @Test fun deleteTest() { val sql = """ DELETE FROM lineitem WHERE orderkey IN (SELECT orderkey FROM orders WHERE priority = 'LOW'); """ .trimIndent() val statement = PrestoSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("lineitem", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-presto-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-redshift-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-redshift-parser superior-redshift-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-redshift-parser/src/main/antlr4/io/github/melin/superior/parser/redshift/antlr4/RedshiftLexer.g4 ================================================ /* based on https://github.com/tunnelvisionlabs/antlr4-grammar-postgresql/blob/master/src/com/tunnelvisionlabs/postgresql/PostgreSqlLexer.g4 */ /* * [The "MIT license"] * Copyright (C) 2014 Sam Harwell, Tunnel Vision Laboratories, LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * 1. The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * 2. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * 3. Except as contained in this notice, the name of Tunnel Vision * Laboratories, LLC. shall not be used in advertising or otherwise to * promote the sale, use or other dealings in this Software without prior * written authorization from Tunnel Vision Laboratories, LLC. */ lexer grammar RedshiftLexer; /* Reference: * http://www.postgresql.org/docs/9.3/static/sql-syntax-lexical.html */ options { superClass = RedshiftLexerBase; } @ header { } @ members { /* This field stores the tags which are used to detect the end of a dollar-quoted string literal. */ } // // SPECIAL CHARACTERS (4.1.4) // // Note that Asterisk is a valid operator, but does not have the type Operator due to its syntactic use in locations // that are not expressions. Dollar : '$' ; OPEN_PAREN : '(' ; CLOSE_PAREN : ')' ; OPEN_BRACKET : '[' ; CLOSE_BRACKET : ']' ; COMMA : ',' ; SEMI : ';' ; COLON : ':' ; STAR : '*' ; EQUAL : '=' ; DOT : '.' ; //NamedArgument : ':='; PLUS : '+' ; MINUS : '-' ; SLASH : '/' ; CARET : '^' ; LT : '<' ; GT : '>' ; LESS_LESS : '<<' ; GREATER_GREATER : '>>' ; COLON_EQUALS : ':=' ; LESS_EQUALS : '<=' ; EQUALS_GREATER : '=>' ; GREATER_EQUALS : '>=' ; DOT_DOT : '..' ; NOT_EQUALS : '<>' ; TYPECAST : '::' ; PERCENT : '%' ; PARAM : '$' ([0-9])+ ; // // OPERATORS (4.1.3) // // this rule does not allow + or - at the end of a multi-character operator Operator : ((OperatorCharacter | ('+' | '-' {checkLA('-')}?)+ (OperatorCharacter | '/' {checkLA('*')}?) | '/' {checkLA('*')}?)+ | // special handling for the single-character operators + and - [+-]) //TODO somehow rewrite this part without using Actions { HandleLessLessGreaterGreater(); } ; /* This rule handles operators which end with + or -, and sets the token type to Operator. It is comprised of four * parts, in order: * * 1. A prefix, which does not contain a character from the required set which allows + or - to appear at the end of * the operator. * 2. A character from the required set which allows + or - to appear at the end of the operator. * 3. An optional sub-token which takes the form of an operator which does not include a + or - at the end of the * sub-token. * 4. A suffix sequence of + and - characters. */ OperatorEndingWithPlusMinus : (OperatorCharacterNotAllowPlusMinusAtEnd | '-' {checkLA('-')}? | '/' {checkLA('*')}?)* OperatorCharacterAllowPlusMinusAtEnd Operator? ('+' | '-' {checkLA('-')}?)+ -> type (Operator) ; // Each of the following fragment rules omits the +, -, and / characters, which must always be handled in a special way // by the operator rules above. fragment OperatorCharacter : [*<>=~!@%^&|`?#] ; // these are the operator characters that don't count towards one ending with + or - fragment OperatorCharacterNotAllowPlusMinusAtEnd : [*<>=+] ; // an operator may end with + or - if it contains one of these characters fragment OperatorCharacterAllowPlusMinusAtEnd : [~!@%^&|`?#] ; // // KEYWORDS (Appendix C) // // // reserved keywords // ALL : 'ALL' ; ANALYSE : 'ANALYSE' ; ANALYZE : 'ANALYZE' ; AND : 'AND' ; ANY : 'ANY' ; ARRAY : 'ARRAY' ; AS : 'AS' ; ASC : 'ASC' ; ASYMMETRIC : 'ASYMMETRIC' ; BOTH : 'BOTH' ; CASE : 'CASE' ; CAST : 'CAST' ; CHECK : 'CHECK' ; COLLATE : 'COLLATE' ; COLUMN : 'COLUMN' ; CONSTRAINT : 'CONSTRAINT' ; CREATE : 'CREATE' ; CURRENT_CATALOG : 'CURRENT_CATALOG' ; CURRENT_DATE : 'CURRENT_DATE' ; CURRENT_ROLE : 'CURRENT_ROLE' ; CURRENT_TIME : 'CURRENT_TIME' ; CURRENT_TIMESTAMP : 'CURRENT_TIMESTAMP' ; CURRENT_USER : 'CURRENT_USER' ; DEFAULT : 'DEFAULT' ; DEFERRABLE : 'DEFERRABLE' ; DESC : 'DESC' ; DISTINCT : 'DISTINCT' ; DO : 'DO' ; ELSE : 'ELSE' ; EXCEPT : 'EXCEPT' ; FALSE_P : 'FALSE' ; FETCH : 'FETCH' ; FOR : 'FOR' ; FOREIGN : 'FOREIGN' ; FROM : 'FROM' ; GRANT : 'GRANT' ; GROUP_P : 'GROUP' ; HAVING : 'HAVING' ; IN_P : 'IN' ; INITIALLY : 'INITIALLY' ; INTERSECT : 'INTERSECT' ; INTO : 'INTO' ; LATERAL_P : 'LATERAL' ; LEADING : 'LEADING' ; LIMIT : 'LIMIT' ; LOCALTIME : 'LOCALTIME' ; LOCALTIMESTAMP : 'LOCALTIMESTAMP' ; NOT : 'NOT' ; NULL_P : 'NULL' ; OFFSET : 'OFFSET' ; ON : 'ON' ; ONLY : 'ONLY' ; OR : 'OR' ; ORDER : 'ORDER' ; PLACING : 'PLACING' ; PRIMARY : 'PRIMARY' ; REFERENCES : 'REFERENCES' ; RETURNING : 'RETURNING' ; SELECT : 'SELECT' ; SESSION_USER : 'SESSION_USER' ; SOME : 'SOME' ; SYMMETRIC : 'SYMMETRIC' ; TABLE : 'TABLE' ; THEN : 'THEN' ; TO : 'TO' ; TRAILING : 'TRAILING' ; TRUE_P : 'TRUE' ; UNION : 'UNION' ; UNIQUE : 'UNIQUE' ; USER : 'USER' ; USING : 'USING' ; VARIADIC : 'VARIADIC' ; WHEN : 'WHEN' ; WHERE : 'WHERE' ; WINDOW : 'WINDOW' ; WITH : 'WITH' ; // // reserved keywords (can be function or type) // AUTHORIZATION : 'AUTHORIZATION' ; BINARY : 'BINARY' ; COLLATION : 'COLLATION' ; CONCURRENTLY : 'CONCURRENTLY' ; CROSS : 'CROSS' ; CURRENT_SCHEMA : 'CURRENT_SCHEMA' ; FREEZE : 'FREEZE' ; FULL : 'FULL' ; ILIKE : 'ILIKE' ; INNER_P : 'INNER' ; IS : 'IS' ; ISNULL : 'ISNULL' ; JOIN : 'JOIN' ; LEFT : 'LEFT' ; LIKE : 'LIKE' ; NATURAL : 'NATURAL' ; NOTNULL : 'NOTNULL' ; OUTER_P : 'OUTER' ; OVER : 'OVER' ; OVERLAPS : 'OVERLAPS' ; RIGHT : 'RIGHT' ; SIMILAR : 'SIMILAR' ; VERBOSE : 'VERBOSE' ; // // non-reserved keywords // ABORT_P : 'ABORT' ; ABSOLUTE_P : 'ABSOLUTE' ; ACCESS : 'ACCESS' ; ACTION : 'ACTION' ; ADD_P : 'ADD' ; ADMIN : 'ADMIN' ; AFTER : 'AFTER' ; AGGREGATE : 'AGGREGATE' ; ALSO : 'ALSO' ; ALTER : 'ALTER' ; ALWAYS : 'ALWAYS' ; ASSERTION : 'ASSERTION' ; ASSIGNMENT : 'ASSIGNMENT' ; AT : 'AT' ; ATTRIBUTE : 'ATTRIBUTE' ; BACKWARD : 'BACKWARD' ; BEFORE : 'BEFORE' ; BEGIN_P : 'BEGIN' ; BY : 'BY' ; CACHE : 'CACHE' ; CALLED : 'CALLED' ; CASCADE : 'CASCADE' ; CASCADED : 'CASCADED' ; CATALOG : 'CATALOG' ; CHAIN : 'CHAIN' ; CHARACTERISTICS : 'CHARACTERISTICS' ; CHECKPOINT : 'CHECKPOINT' ; CLASS : 'CLASS' ; CLOSE : 'CLOSE' ; CLUSTER : 'CLUSTER' ; COMMENT : 'COMMENT' ; COMMENTS : 'COMMENTS' ; COMMIT : 'COMMIT' ; COMMITTED : 'COMMITTED' ; CONFIGURATION : 'CONFIGURATION' ; CONNECTION : 'CONNECTION' ; CONSTRAINTS : 'CONSTRAINTS' ; CONTENT_P : 'CONTENT' ; CONTINUE_P : 'CONTINUE' ; CONVERSION_P : 'CONVERSION' ; COPY : 'COPY' ; COST : 'COST' ; CSV : 'CSV' ; CURSOR : 'CURSOR' ; CYCLE : 'CYCLE' ; DATA_P : 'DATA' ; DATABASE : 'DATABASE' ; DAY_P : 'DAY' ; DEALLOCATE : 'DEALLOCATE' ; DECLARE : 'DECLARE' ; DEFAULTS : 'DEFAULTS' ; DEFERRED : 'DEFERRED' ; DEFINER : 'DEFINER' ; DELETE_P : 'DELETE' ; DELIMITER : 'DELIMITER' ; DELIMITERS : 'DELIMITERS' ; DICTIONARY : 'DICTIONARY' ; DISABLE_P : 'DISABLE' ; DISCARD : 'DISCARD' ; DOCUMENT_P : 'DOCUMENT' ; DOMAIN_P : 'DOMAIN' ; DOUBLE_P : 'DOUBLE' ; DROP : 'DROP' ; EACH : 'EACH' ; ENABLE_P : 'ENABLE' ; ENCODING : 'ENCODING' ; ENCRYPTED : 'ENCRYPTED' ; ENUM_P : 'ENUM' ; ESCAPE : 'ESCAPE' ; EVENT : 'EVENT' ; EXCLUDE : 'EXCLUDE' ; EXCLUDING : 'EXCLUDING' ; EXCLUSIVE : 'EXCLUSIVE' ; EXECUTE : 'EXECUTE' ; EXPLAIN : 'EXPLAIN' ; EXTENSION : 'EXTENSION' ; EXTERNAL : 'EXTERNAL' ; FAMILY : 'FAMILY' ; FIRST_P : 'FIRST' ; FOLLOWING : 'FOLLOWING' ; FORCE : 'FORCE' ; FORWARD : 'FORWARD' ; FUNCTION : 'FUNCTION' ; FUNCTIONS : 'FUNCTIONS' ; GLOBAL : 'GLOBAL' ; GRANTED : 'GRANTED' ; HANDLER : 'HANDLER' ; HEADER_P : 'HEADER' ; HOLD : 'HOLD' ; HOUR_P : 'HOUR' ; IDENTITY_P : 'IDENTITY' ; IF_P : 'IF' ; IMMEDIATE : 'IMMEDIATE' ; IMMUTABLE : 'IMMUTABLE' ; IMPLICIT_P : 'IMPLICIT' ; INCLUDING : 'INCLUDING' ; INCREMENT : 'INCREMENT' ; INDEX : 'INDEX' ; INDEXES : 'INDEXES' ; INHERIT : 'INHERIT' ; INHERITS : 'INHERITS' ; INLINE_P : 'INLINE' ; INSENSITIVE : 'INSENSITIVE' ; INSERT : 'INSERT' ; INSTEAD : 'INSTEAD' ; INVOKER : 'INVOKER' ; ISOLATION : 'ISOLATION' ; KEY : 'KEY' ; LABEL : 'LABEL' ; LANGUAGE : 'LANGUAGE' ; LARGE_P : 'LARGE' ; LAST_P : 'LAST' ; //LC_COLLATE : 'LC'_'COLLATE; //LC_CTYPE : 'LC'_'CTYPE; LEAKPROOF : 'LEAKPROOF' ; LEVEL : 'LEVEL' ; LISTEN : 'LISTEN' ; LOAD : 'LOAD' ; LOCAL : 'LOCAL' ; LOCATION : 'LOCATION' ; LOCK_P : 'LOCK' ; MAPPING : 'MAPPING' ; MATCH : 'MATCH' ; MATCHED : 'MATCHED' ; MATERIALIZED : 'MATERIALIZED' ; MAXVALUE : 'MAXVALUE' ; MERGE : 'MERGE' ; MINUTE_P : 'MINUTE' ; MINVALUE : 'MINVALUE' ; MODE : 'MODE' ; MONTH_P : 'MONTH' ; MOVE : 'MOVE' ; NAME_P : 'NAME' ; NAMES : 'NAMES' ; NEXT : 'NEXT' ; NO : 'NO' ; NOTHING : 'NOTHING' ; NOTIFY : 'NOTIFY' ; NOWAIT : 'NOWAIT' ; NULLS_P : 'NULLS' ; OBJECT_P : 'OBJECT' ; OF : 'OF' ; OFF : 'OFF' ; OIDS : 'OIDS' ; OPERATOR : 'OPERATOR' ; OPTION : 'OPTION' ; OPTIONS : 'OPTIONS' ; OWNED : 'OWNED' ; OWNER : 'OWNER' ; PARSER : 'PARSER' ; PARTIAL : 'PARTIAL' ; PARTITION : 'PARTITION' ; PASSING : 'PASSING' ; PASSWORD : 'PASSWORD' ; PLANS : 'PLANS' ; PRECEDING : 'PRECEDING' ; PREPARE : 'PREPARE' ; PREPARED : 'PREPARED' ; PRESERVE : 'PRESERVE' ; PRIOR : 'PRIOR' ; PRIVILEGES : 'PRIVILEGES' ; PROCEDURAL : 'PROCEDURAL' ; PROCEDURE : 'PROCEDURE' ; PROGRAM : 'PROGRAM' ; QUOTE : 'QUOTE' ; RANGE : 'RANGE' ; READ : 'READ' ; REASSIGN : 'REASSIGN' ; RECHECK : 'RECHECK' ; RECURSIVE : 'RECURSIVE' ; REF : 'REF' ; REFRESH : 'REFRESH' ; REINDEX : 'REINDEX' ; RELATIVE_P : 'RELATIVE' ; RELEASE : 'RELEASE' ; RENAME : 'RENAME' ; REPEATABLE : 'REPEATABLE' ; REPLACE : 'REPLACE' ; REPLICA : 'REPLICA' ; RESET : 'RESET' ; RESTART : 'RESTART' ; RESTRICT : 'RESTRICT' ; RETURNS : 'RETURNS' ; REVOKE : 'REVOKE' ; ROLE : 'ROLE' ; ROLLBACK : 'ROLLBACK' ; ROWS : 'ROWS' ; RULE : 'RULE' ; SAVEPOINT : 'SAVEPOINT' ; SCHEMA : 'SCHEMA' ; SCROLL : 'SCROLL' ; SEARCH : 'SEARCH' ; SECOND_P : 'SECOND' ; SECURITY : 'SECURITY' ; SEQUENCE : 'SEQUENCE' ; SEQUENCES : 'SEQUENCES' ; SERIALIZABLE : 'SERIALIZABLE' ; SERVER : 'SERVER' ; SESSION : 'SESSION' ; SET : 'SET' ; SHARE : 'SHARE' ; SHOW : 'SHOW' ; SIMPLE : 'SIMPLE' ; SNAPSHOT : 'SNAPSHOT' ; STABLE : 'STABLE' ; STANDALONE_P : 'STANDALONE' ; START : 'START' ; STATEMENT : 'STATEMENT' ; STATISTICS : 'STATISTICS' ; STDIN : 'STDIN' ; STDOUT : 'STDOUT' ; STORAGE : 'STORAGE' ; STRICT_P : 'STRICT' ; STRIP_P : 'STRIP' ; SYSID : 'SYSID' ; SYSTEM_P : 'SYSTEM' ; TABLES : 'TABLES' ; TABLESPACE : 'TABLESPACE' ; TEMP : 'TEMP' ; TEMPLATE : 'TEMPLATE' ; TEMPORARY : 'TEMPORARY' ; TEXT_P : 'TEXT' ; TRANSACTION : 'TRANSACTION' ; TRIGGER : 'TRIGGER' ; TRUNCATE : 'TRUNCATE' ; TRUSTED : 'TRUSTED' ; TYPE_P : 'TYPE' ; TYPES_P : 'TYPES' ; UNBOUNDED : 'UNBOUNDED' ; UNCOMMITTED : 'UNCOMMITTED' ; UNENCRYPTED : 'UNENCRYPTED' ; UNKNOWN : 'UNKNOWN' ; UNLISTEN : 'UNLISTEN' ; UNLOGGED : 'UNLOGGED' ; UNTIL : 'UNTIL' ; UPDATE : 'UPDATE' ; VACUUM : 'VACUUM' ; VALID : 'VALID' ; VALIDATE : 'VALIDATE' ; VALIDATOR : 'VALIDATOR' ; //VALUE : 'VALUE; VARYING : 'VARYING' ; VERSION_P : 'VERSION' ; VIEW : 'VIEW' ; VOLATILE : 'VOLATILE' ; WHITESPACE_P : 'WHITESPACE' ; WITHOUT : 'WITHOUT' ; WORK : 'WORK' ; WRAPPER : 'WRAPPER' ; WRITE : 'WRITE' ; XML_P : 'XML' ; YEAR_P : 'YEAR' ; YES_P : 'YES' ; ZONE : 'ZONE' ; // // non-reserved keywords (can not be function or type) // BETWEEN : 'BETWEEN' ; BIGINT : 'BIGINT' ; BIT : 'BIT' ; BOOLEAN_P : 'BOOLEAN' ; CHAR_P : 'CHAR' ; CHARACTER : 'CHARACTER' ; COALESCE : 'COALESCE' ; DEC : 'DEC' ; DECIMAL_P : 'DECIMAL' ; EXISTS : 'EXISTS' ; EXTRACT : 'EXTRACT' ; FLOAT_P : 'FLOAT' ; GREATEST : 'GREATEST' ; INOUT : 'INOUT' ; INT_P : 'INT' ; INTEGER : 'INTEGER' ; INTERVAL : 'INTERVAL' ; LEAST : 'LEAST' ; NATIONAL : 'NATIONAL' ; NCHAR : 'NCHAR' ; NONE : 'NONE' ; NULLIF : 'NULLIF' ; NUMERIC : 'NUMERIC' ; OVERLAY : 'OVERLAY' ; POSITION : 'POSITION' ; PRECISION : 'PRECISION' ; REAL : 'REAL' ; ROW : 'ROW' ; SETOF : 'SETOF' ; SMALLINT : 'SMALLINT' ; SUBSTRING : 'SUBSTRING' ; TIME : 'TIME' ; TIMESTAMP : 'TIMESTAMP' ; TREAT : 'TREAT' ; TRIM : 'TRIM' ; VALUES : 'VALUES' ; VARCHAR : 'VARCHAR' ; XMLATTRIBUTES : 'XMLATTRIBUTES' ; XMLCOMMENT : 'XMLCOMMENT' ; XMLAGG : 'XMLAGG' ; XML_IS_WELL_FORMED : 'XML_IS_WELL_FORMED' ; XML_IS_WELL_FORMED_DOCUMENT : 'XML_IS_WELL_FORMED_DOCUMENT' ; XML_IS_WELL_FORMED_CONTENT : 'XML_IS_WELL_FORMED_CONTENT' ; XPATH : 'XPATH' ; XPATH_EXISTS : 'XPATH_EXISTS' ; XMLCONCAT : 'XMLCONCAT' ; XMLELEMENT : 'XMLELEMENT' ; XMLEXISTS : 'XMLEXISTS' ; XMLFOREST : 'XMLFOREST' ; XMLPARSE : 'XMLPARSE' ; XMLPI : 'XMLPI' ; XMLROOT : 'XMLROOT' ; XMLSERIALIZE : 'XMLSERIALIZE' ; //MISSED CALL : 'CALL' ; CURRENT_P : 'CURRENT' ; ATTACH : 'ATTACH' ; DETACH : 'DETACH' ; EXPRESSION : 'EXPRESSION' ; GENERATED : 'GENERATED' ; LOGGED : 'LOGGED' ; STORED : 'STORED' ; INCLUDE : 'INCLUDE' ; ROUTINE : 'ROUTINE' ; TRANSFORM : 'TRANSFORM' ; IMPORT_P : 'IMPORT' ; POLICY : 'POLICY' ; METHOD : 'METHOD' ; REFERENCING : 'REFERENCING' ; NEW : 'NEW' ; OLD : 'OLD' ; VALUE_P : 'VALUE' ; SUBSCRIPTION : 'SUBSCRIPTION' ; PUBLICATION : 'PUBLICATION' ; OUT_P : 'OUT' ; END_P : 'END' ; ROUTINES : 'ROUTINES' ; SCHEMAS : 'SCHEMAS' ; PROCEDURES : 'PROCEDURES' ; INPUT_P : 'INPUT' ; SUPPORT : 'SUPPORT' ; PARALLEL : 'PARALLEL' ; SQL_P : 'SQL' ; DEPENDS : 'DEPENDS' ; OVERRIDING : 'OVERRIDING' ; // support gauss start-------------------------------- AUTOMAPPED : 'AUTOMAPPED' ; SAMPLE : 'SAMPLE' ; PERCENT_P : 'PERCENT' ; STAT : 'STAT' ; COLLECT : 'COLLECT' ; MULTISET : 'MULTISET' ; MINUS_P : 'MINUS' ; GROUPCONCAT : 'GROUP_CONCAT' ; SEPARATOR : 'SEPARATOR' ; IGNORE : 'IGNORE' ; OPEN_BRACE : '{' ; CLOSE_BRACE : '}' ; OVERWRITE : 'OVERWRITE' ; DISTRIBUTE : 'DISTRIBUTE' ; DISTRIBUTED : 'DISTRIBUTED' ; DISTRIBUTION : 'DISTRIBUTION' ; REPLICATION : 'REPLICATION' ; ROUNDROBIN : 'ROUNDROBIN' ; HASH : 'HASH' ; RANDOMLY : 'RANDOMLY' ; NODE_P : 'NODE' ; LIST_P : 'LIST' ; LESS : 'LESS' ; THAN : 'THAN' ; EVERY : 'EVERY' ; MOVEMENT : 'MOVEMENT' ; TSTag : 'TSTag' ; TSTime : 'TSTime' ; TSField : 'TSField' ; REPLICATED : 'REPLICATED' ; // support gauss end -------------------------------- CONFLICT : 'CONFLICT' ; SKIP_P : 'SKIP' ; LOCKED : 'LOCKED' ; TIES : 'TIES' ; ROLLUP : 'ROLLUP' ; CUBE : 'CUBE' ; GROUPING : 'GROUPING' ; SETS : 'SETS' ; TABLESAMPLE : 'TABLESAMPLE' ; ORDINALITY : 'ORDINALITY' ; XMLTABLE : 'XMLTABLE' ; COLUMNS : 'COLUMNS' ; XMLNAMESPACES : 'XMLNAMESPACES' ; ROWTYPE : 'ROWTYPE' ; NORMALIZED : 'NORMALIZED' ; WITHIN : 'WITHIN' ; FILTER : 'FILTER' ; GROUPS : 'GROUPS' ; OTHERS : 'OTHERS' ; NFC : 'NFC' ; NFD : 'NFD' ; NFKC : 'NFKC' ; NFKD : 'NFKD' ; UESCAPE : 'UESCAPE' ; VIEWS : 'VIEWS' ; NORMALIZE : 'NORMALIZE' ; DUMP : 'DUMP' ; PRINT_STRICT_PARAMS : 'PRINT_STRICT_PARAMS' ; VARIABLE_CONFLICT : 'VARIABLE_CONFLICT' ; ERROR : 'ERROR' ; USE_VARIABLE : 'USE_VARIABLE' ; USE_COLUMN : 'USE_COLUMN' ; ALIAS : 'ALIAS' ; CONSTANT : 'CONSTANT' ; PERFORM : 'PERFORM' ; GET : 'GET' ; DIAGNOSTICS : 'DIAGNOSTICS' ; STACKED : 'STACKED' ; ELSIF : 'ELSIF' ; WHILE : 'WHILE' ; REVERSE : 'REVERSE' ; FOREACH : 'FOREACH' ; SLICE : 'SLICE' ; EXIT : 'EXIT' ; RETURN : 'RETURN' ; QUERY : 'QUERY' ; RAISE : 'RAISE' ; SQLSTATE : 'SQLSTATE' ; DEBUG : 'DEBUG' ; LOG : 'LOG' ; INFO : 'INFO' ; NOTICE : 'NOTICE' ; WARNING : 'WARNING' ; EXCEPTION : 'EXCEPTION' ; ASSERT : 'ASSERT' ; LOOP : 'LOOP' ; OPEN : 'OPEN' ; // // IDENTIFIERS (4.1.1) // ABS : 'ABS' ; CBRT : 'CBRT' ; CEIL : 'CEIL' ; CEILING : 'CEILING' ; DEGREES : 'DEGREES' ; DIV : 'DIV' ; EXP : 'EXP' ; FACTORIAL : 'FACTORIAL' ; FLOOR : 'FLOOR' ; GCD : 'GCD' ; LCM : 'LCM' ; LN : 'LN' ; LOG10 : 'LOG10' ; MIN_SCALE : 'MIN_SCALE' ; MOD : 'MOD' ; PI : 'PI' ; POWER : 'POWER' ; RADIANS : 'RADIANS' ; ROUND : 'ROUND' ; SCALE : 'SCALE' ; SIGN : 'SIGN' ; SQRT : 'SQRT' ; TRIM_SCALE : 'TRIM_SCALE' ; TRUNC : 'TRUNC' ; WIDTH_BUCKET : 'WIDTH_BUCKET' ; RANDOM : 'RANDOM' ; SETSEED : 'SETSEED' ; ACOS : 'ACOS' ; ACOSD : 'ACOSD' ; ASIN : 'ASIN' ; ASIND : 'ASIND' ; ATAN : 'ATAN' ; ATAND : 'ATAND' ; ATAN2 : 'ATAN2' ; ATAN2D : 'ATAN2D' ; COS : 'COS' ; COSD : 'COSD' ; COT : 'COT' ; COTD : 'COTD' ; SIN : 'SIN' ; SIND : 'SIND' ; TAN : 'TAN' ; TAND : 'TAND' ; SINH : 'SINH' ; COSH : 'COSH' ; TANH : 'TANH' ; ASINH : 'ASINH' ; ACOSH : 'ACOSH' ; ATANH : 'ATANH' ; BIT_LENGTH : 'BIT_LENGTH' ; CHAR_LENGTH : 'CHAR_LENGTH' ; CHARACTER_LENGTH : 'CHARACTER_LENGTH' ; LOWER : 'LOWER' ; OCTET_LENGTH : 'OCTET_LENGTH' ; UPPER : 'UPPER' ; ASCII : 'ASCII' ; BTRIM : 'BTRIM' ; CHR : 'CHR' ; CONCAT : 'CONCAT' ; CONCAT_WS : 'CONCAT_WS' ; FORMAT : 'FORMAT' ; INITCAP : 'INITCAP' ; LENGTH : 'LENGTH' ; LPAD : 'LPAD' ; LTRIM : 'LTRIM' ; MD5 : 'MD5' ; PARSE_IDENT : 'PARSE_IDENT' ; PG_CLIENT_ENCODING : 'PG_CLIENT_ENCODING' ; QUOTE_IDENT : 'QUOTE_IDENT' ; QUOTE_LITERAL : 'QUOTE_LITERAL' ; QUOTE_NULLABLE : 'QUOTE_NULLABLE' ; REGEXP_COUNT : 'REGEXP_COUNT' ; REGEXP_INSTR : 'REGEXP_INSTR' ; REGEXP_LIKE : 'REGEXP_LIKE' ; REGEXP_MATCH : 'REGEXP_MATCH' ; REGEXP_MATCHES : 'REGEXP_MATCHES' ; REGEXP_REPLACE : 'REGEXP_REPLACE' ; REGEXP_SPLIT_TO_ARRAY : 'REGEXP_SPLIT_TO_ARRAY' ; REGEXP_SPLIT_TO_TABLE : 'REGEXP_SPLIT_TO_TABLE' ; REGEXP_SUBSTR : 'REGEXP_SUBSTR' ; REPEAT : 'REPEAT' ; RPAD : 'RPAD' ; RTRIM : 'RTRIM' ; SPLIT_PART : 'SPLIT_PART' ; STARTS_WITH : 'STARTS_WITH' ; STRING_TO_ARRAY : 'STRING_TO_ARRAY' ; STRING_TO_TABLE : 'STRING_TO_TABLE' ; STRPOS : 'STRPOS' ; SUBSTR : 'SUBSTR' ; TO_ASCII : 'TO_ASCII' ; TO_HEX : 'TO_HEX' ; TRANSLATE : 'TRANSLATE' ; UNISTR : 'UNISTR' ; AGE : 'AGE' ; CLOCK_TIMESTAMP : 'CLOCK_TIMESTAMP' ; DATE_BIN : 'DATE_BIN' ; DATE_PART : 'DATE_PART' ; DATE_TRUNC : 'DATE_TRUNC' ; ISFINITE : 'ISFINITE' ; JUSTIFY_DAYS : 'JUSTIFY_DAYS' ; JUSTIFY_HOURS : 'JUSTIFY_HOURS' ; JUSTIFY_INTERVAL : 'JUSTIFY_INTERVAL' ; MAKE_DATE : 'MAKE_DATE' ; MAKE_INTERVAL : 'MAKE_INTERVAL' ; MAKE_TIME : 'MAKE_TIME' ; MAKE_TIMESTAMP : 'MAKE_TIMESTAMP' ; MAKE_TIMESTAMPTZ : 'MAKE_TIMESTAMPTZ' ; NOW : 'NOW' ; STATEMENT_TIMESTAMP : 'STATEMENT_TIMESTAMP' ; TIMEOFDAY : 'TIMEOFDAY' ; TRANSACTION_TIMESTAMP : 'TRANSACTION_TIMESTAMP' ; TO_TIMESTAMP : 'TO_TIMESTAMP' ; TO_CHAR : 'TO_CHAR' ; TO_DATE : 'TO_DATE' ; TO_NUMBER : 'TO_NUMBER' ; Identifier : IdentifierStartChar IdentifierChar* ; fragment IdentifierStartChar : // these are the valid identifier start characters below 0x7F [a-zA-Z_] | // these are the valid characters from 0x80 to 0xFF [\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF] | // these are the letters above 0xFF which only need a single UTF-16 code unit [\u0100-\uD7FF\uE000-\uFFFF] {charIsLetter()}? | // letters which require multiple UTF-16 code units [\uD800-\uDBFF] [\uDC00-\uDFFF] { CheckIfUtf32Letter() }? ; fragment IdentifierChar : StrictIdentifierChar | '$' ; fragment StrictIdentifierChar : IdentifierStartChar | [0-9] ; /* Quoted Identifiers * * These are divided into four separate tokens, allowing distinction of valid quoted identifiers from invalid quoted * identifiers without sacrificing the ability of the lexer to reliably recover from lexical errors in the input. */ QuotedIdentifier : UnterminatedQuotedIdentifier '"' ; // This is a quoted identifier which only contains valid characters but is not terminated UnterminatedQuotedIdentifier : '"' ('""' | ~ [\u0000"])* ; // This is a quoted identifier which is terminated but contains a \u0000 character InvalidQuotedIdentifier : InvalidUnterminatedQuotedIdentifier '"' ; // This is a quoted identifier which is unterminated and contains a \u0000 character InvalidUnterminatedQuotedIdentifier : '"' ('""' | ~ '"')* ; /* Unicode Quoted Identifiers * * These are divided into four separate tokens, allowing distinction of valid Unicode quoted identifiers from invalid * Unicode quoted identifiers without sacrificing the ability of the lexer to reliably recover from lexical errors in * the input. Note that escape sequences are never checked as part of this determination due to the ability of users * to change the escape character with a UESCAPE clause following the Unicode quoted identifier. * * TODO: these rules assume "" is still a valid escape sequence within a Unicode quoted identifier. */ UnicodeQuotedIdentifier : 'U' '&' QuotedIdentifier ; // This is a Unicode quoted identifier which only contains valid characters but is not terminated UnterminatedUnicodeQuotedIdentifier : 'U' '&' UnterminatedQuotedIdentifier ; // This is a Unicode quoted identifier which is terminated but contains a \u0000 character InvalidUnicodeQuotedIdentifier : 'U' '&' InvalidQuotedIdentifier ; // This is a Unicode quoted identifier which is unterminated and contains a \u0000 character InvalidUnterminatedUnicodeQuotedIdentifier : 'U' '&' InvalidUnterminatedQuotedIdentifier ; // // CONSTANTS (4.1.2) // // String Constants (4.1.2.1) StringConstant : UnterminatedStringConstant '\'' ; UnterminatedStringConstant : '\'' ('\'\'' | ~ '\'')* ; // String Constants with C-style Escapes (4.1.2.2) BeginEscapeStringConstant : 'E' '\'' -> more , pushMode (EscapeStringConstantMode) ; // String Constants with Unicode Escapes (4.1.2.3) // // Note that escape sequences are never checked as part of this token due to the ability of users to change the escape // character with a UESCAPE clause following the Unicode string constant. // // TODO: these rules assume '' is still a valid escape sequence within a Unicode string constant. UnicodeEscapeStringConstant : UnterminatedUnicodeEscapeStringConstant '\'' ; UnterminatedUnicodeEscapeStringConstant : 'U' '&' UnterminatedStringConstant ; // Dollar-quoted String Constants (4.1.2.4) BeginDollarStringConstant : '$' Tag? '$' {pushTag();} -> pushMode (DollarQuotedStringMode) ; /* "The tag, if any, of a dollar-quoted string follows the same rules as an * unquoted identifier, except that it cannot contain a dollar sign." */ fragment Tag : IdentifierStartChar StrictIdentifierChar* ; // Bit-strings Constants (4.1.2.5) BinaryStringConstant : UnterminatedBinaryStringConstant '\'' ; UnterminatedBinaryStringConstant : 'B' '\'' [01]* ; InvalidBinaryStringConstant : InvalidUnterminatedBinaryStringConstant '\'' ; InvalidUnterminatedBinaryStringConstant : 'B' UnterminatedStringConstant ; HexadecimalStringConstant : UnterminatedHexadecimalStringConstant '\'' ; UnterminatedHexadecimalStringConstant : 'X' '\'' [0-9A-F]* ; InvalidHexadecimalStringConstant : InvalidUnterminatedHexadecimalStringConstant '\'' ; InvalidUnterminatedHexadecimalStringConstant : 'X' UnterminatedStringConstant ; // Numeric Constants (4.1.2.6) Integral : Digits ; NumericFail : Digits '..' {HandleNumericFail();} ; Numeric : Digits '.' Digits? /*? replaced with + to solve problem with DOT_DOT .. but this surely must be rewriten */ ('E' [+-]? Digits)? | '.' Digits ('E' [+-]? Digits)? | Digits 'E' [+-]? Digits ; fragment Digits : [0-9]+ ; PLSQLVARIABLENAME : ':' [A-Z_] [A-Z_0-9$]* ; PLSQLIDENTIFIER : ':"' ('\\' . | '""' | ~ ('"' | '\\'))* '"' ; // // WHITESPACE (4.1) // Whitespace : [ \t]+ -> channel (HIDDEN) ; Newline : ('\r' '\n'? | '\n') -> channel (HIDDEN) ; // // COMMENTS (4.1.5) // LineComment : '--' ~ [\r\n]* -> channel (HIDDEN) ; BlockComment : ('/*' ('/'* BlockComment | ~ [/*] | '/'+ ~ [/*] | '*'+ ~ [/*])* '*'* '*/') -> channel (HIDDEN) ; UnterminatedBlockComment : '/*' ('/'* BlockComment | // these characters are not part of special sequences in a block comment ~ [/*] | // handle / or * characters which are not part of /* or */ and do not appear at the end of the file ('/'+ ~ [/*] | '*'+ ~ [/*]))* // Handle the case of / or * characters at the end of the file, or a nested unterminated block comment ('/'+ | '*'+ | '/'* UnterminatedBlockComment)? // Optional assertion to make sure this rule is working as intended { UnterminatedBlockCommentDebugAssert(); } ; // // META-COMMANDS // // http://www.postgresql.org/docs/9.3/static/app-psql.html MetaCommand : '\\' (~ [\r\n\\"] | '"' ~ [\r\n"]* '"')* ('"' ~ [\r\n"]*)? ; EndMetaCommand : '\\\\' ; // // ERROR // // Any character which does not match one of the above rules will appear in the token stream as an ErrorCharacter token. // This ensures the lexer itself will never encounter a syntax error, so all error handling may be performed by the // parser. ErrorCharacter : . ; mode EscapeStringConstantMode; EscapeStringConstant : EscapeStringText '\'' -> mode (AfterEscapeStringConstantMode) ; UnterminatedEscapeStringConstant : EscapeStringText // Handle a final unmatched \ character appearing at the end of the file '\\'? EOF ; fragment EscapeStringText : ('\'\'' | '\\' ( // two-digit hex escapes are still valid when treated as single-digit escapes 'x' [0-9a-fA-F] | 'u' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] | 'U' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] | // Any character other than the Unicode escapes can follow a backslash. Some have special meaning, // but that doesn't affect the syntax. ~ [xuU]) | ~ ['\\])* ; InvalidEscapeStringConstant : InvalidEscapeStringText '\'' -> mode (AfterEscapeStringConstantMode) ; InvalidUnterminatedEscapeStringConstant : InvalidEscapeStringText // Handle a final unmatched \ character appearing at the end of the file '\\'? EOF ; fragment InvalidEscapeStringText : ('\'\'' | '\\' . | ~ ['\\])* ; mode AfterEscapeStringConstantMode; AfterEscapeStringConstantMode_Whitespace : Whitespace -> type (Whitespace) , channel (HIDDEN) ; AfterEscapeStringConstantMode_Newline : Newline -> type (Newline) , channel (HIDDEN) , mode (AfterEscapeStringConstantWithNewlineMode) ; AfterEscapeStringConstantMode_NotContinued : {} // intentionally empty -> skip , popMode ; mode AfterEscapeStringConstantWithNewlineMode; AfterEscapeStringConstantWithNewlineMode_Whitespace : Whitespace -> type (Whitespace) , channel (HIDDEN) ; AfterEscapeStringConstantWithNewlineMode_Newline : Newline -> type (Newline) , channel (HIDDEN) ; AfterEscapeStringConstantWithNewlineMode_Continued : '\'' -> more , mode (EscapeStringConstantMode) ; AfterEscapeStringConstantWithNewlineMode_NotContinued : {} // intentionally empty -> skip , popMode ; mode DollarQuotedStringMode; DollarText : ~ '$'+ //| '$'([0-9])+ | // this alternative improves the efficiency of handling $ characters within a dollar-quoted string which are // not part of the ending tag. '$' ~ '$'* ; EndDollarStringConstant : ('$' Tag? '$') {isTag()}? {popTag();} -> popMode ; ================================================ FILE: superior-redshift-parser/src/main/antlr4/io/github/melin/superior/parser/redshift/antlr4/RedshiftParser.g4 ================================================ parser grammar RedshiftParser; options { tokenVocab = RedshiftLexer; superClass = RedshiftParserBase; } @header { } @members { } root : stmtblock EOF ; sqlroot : pl_function ; stmtblock : stmtmulti ; stmtmulti : (stmt SEMI?)* ; stmt : altereventtrigstmt | altercollationstmt | alterdatabasestmt | alterdatabasesetstmt | alterdefaultprivilegesstmt | alterdomainstmt | alterenumstmt | alterextensionstmt | alterextensioncontentsstmt | alterfdwstmt | alterforeignserverstmt | alterfunctionstmt | altergroupstmt | alterobjectdependsstmt | alterobjectschemastmt | alterownerstmt | alteroperatorstmt | altertypestmt | alterpolicystmt | alterseqstmt | altersystemstmt | altertablestmt | altertblspcstmt | altercompositetypestmt | alterpublicationstmt | alterrolesetstmt | alterrolestmt | altersubscriptionstmt | alterstatsstmt | altertsconfigurationstmt | altertsdictionarystmt | alterusermappingstmt | analyzestmt | callstmt | checkpointstmt | closeportalstmt | clusterstmt | commentstmt | constraintssetstmt | copystmt | createamstmt | createasstmt | createassertionstmt | createcaststmt | createconversionstmt | createdomainstmt | createextensionstmt | createfdwstmt | createforeignserverstmt | createforeigntablestmt | createfunctionstmt | creategroupstmt | creatematviewstmt | createopclassstmt | createopfamilystmt | createpublicationstmt | alteropfamilystmt | createpolicystmt | createplangstmt | createschemastmt | createseqstmt | createstmt | createsubscriptionstmt | createstatsstmt | createtablespacestmt | createtransformstmt | createtrigstmt | createeventtrigstmt | createrolestmt | createuserstmt | createusermappingstmt | createdbstmt | deallocatestmt | declarecursorstmt | definestmt | deletestmt | discardstmt | dostmt | dropcaststmt | dropopclassstmt | dropopfamilystmt | dropownedstmt | dropstmt | dropsubscriptionstmt | droptablespacestmt | droptransformstmt | droprolestmt | dropusermappingstmt | dropdbstmt | executestmt | explainstmt | fetchstmt | grantstmt | grantrolestmt | importforeignschemastmt | indexstmt | insertstmt | mergestmt | listenstmt | refreshmatviewstmt | loadstmt | lockstmt | notifystmt | preparestmt | reassignownedstmt | reindexstmt | removeaggrstmt | removefuncstmt | removeoperstmt | renamestmt | revokestmt | revokerolestmt | rulestmt | seclabelstmt | selectstmt | transactionstmt | truncatestmt | unlistenstmt | updatestmt | vacuumstmt | variableresetstmt | variablesetstmt | variableshowstmt | showstmt | viewstmt | plsqlconsolecommand ; plsqlconsolecommand : MetaCommand EndMetaCommand? ; callstmt : CALL func_application ; createrolestmt : CREATE ROLE roleid opt_with optrolelist ; opt_with : WITH //| WITH_LA | ; optrolelist : createoptroleelem* ; alteroptrolelist : alteroptroleelem* ; alteroptroleelem : PASSWORD (sconst | NULL_P) | (ENCRYPTED | UNENCRYPTED) PASSWORD sconst | INHERIT | CONNECTION LIMIT signediconst | VALID UNTIL sconst | USER role_list | identifier ; createoptroleelem : alteroptroleelem | SYSID iconst | ADMIN role_list | ROLE role_list | IN_P (ROLE | GROUP_P) role_list ; createuserstmt : CREATE USER roleid opt_with optrolelist ; alterrolestmt : ALTER (ROLE | USER) rolespec opt_with alteroptrolelist ; opt_in_database : | IN_P DATABASE name ; alterrolesetstmt : ALTER (ROLE | USER) ALL? rolespec opt_in_database setresetclause ; droprolestmt : DROP (ROLE | USER | GROUP_P) (IF_P EXISTS)? role_list ; creategroupstmt : CREATE GROUP_P roleid opt_with optrolelist ; altergroupstmt : ALTER GROUP_P rolespec add_drop USER role_list ; add_drop : ADD_P | DROP ; createschemastmt : CREATE SCHEMA (IF_P NOT EXISTS)? (optschemaname AUTHORIZATION rolespec | colid) optschemaeltlist ; optschemaname : colid | ; optschemaeltlist : schema_stmt* ; schema_stmt : createstmt | indexstmt | createseqstmt | createtrigstmt | grantstmt | viewstmt ; variablesetstmt : SET (LOCAL | SESSION)? set_rest ; set_rest : TRANSACTION transaction_mode_list | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list | set_rest_more ; generic_set : var_name (TO | EQUAL) var_list ; set_rest_more : generic_set | var_name FROM CURRENT_P | TIME ZONE zone_value | CATALOG sconst | SCHEMA sconst | NAMES opt_encoding | ROLE nonreservedword_or_sconst | SESSION AUTHORIZATION nonreservedword_or_sconst | XML_P OPTION document_or_content | TRANSACTION SNAPSHOT sconst ; var_name : colid (DOT colid)* ; var_list : var_value (COMMA var_value)* ; var_value : opt_boolean_or_string | numericonly ; iso_level : READ (UNCOMMITTED | COMMITTED) | REPEATABLE READ | SERIALIZABLE ; opt_boolean_or_string : TRUE_P | FALSE_P | ON | nonreservedword_or_sconst ; zone_value : sconst | identifier | constinterval sconst opt_interval | constinterval OPEN_PAREN iconst CLOSE_PAREN sconst | numericonly | DEFAULT | LOCAL ; opt_encoding : sconst | DEFAULT | ; nonreservedword_or_sconst : nonreservedword | sconst ; variableresetstmt : RESET reset_rest ; reset_rest : generic_reset | TIME ZONE | TRANSACTION ISOLATION LEVEL | SESSION AUTHORIZATION ; generic_reset : var_name | ALL ; setresetclause : SET set_rest | variableresetstmt ; functionsetresetclause : SET set_rest_more | variableresetstmt ; variableshowstmt : SHOW (var_name | TIME ZONE | TRANSACTION ISOLATION LEVEL | SESSION AUTHORIZATION | ALL) ; // redshift show https://docs.aws.amazon.com/redshift/latest/dg/r_SHOW_COLUMNS.html start showstmt : SHOW COLUMNS FROM TABLE qualified_name (LIKE a_expr_qual_op)? (LIMIT select_limit_value)? | SHOW EXTERNAL TABLE qualified_name (PARTITION)? | SHOW SCHEMAS FROM DATABASE qualified_name (LIKE a_expr_qual_op)? (LIMIT select_limit_value)? | SHOW TABLE qualified_name | SHOW VIEW qualified_name | SHOW TABLES FROM SCHEMA qualified_name (LIKE a_expr_qual_op)? (LIMIT select_limit_value)? ; // end constraintssetstmt : SET CONSTRAINTS constraints_set_list constraints_set_mode ; constraints_set_list : ALL | qualified_name_list ; constraints_set_mode : DEFERRED | IMMEDIATE ; checkpointstmt : CHECKPOINT ; discardstmt : DISCARD (ALL | TEMP | TEMPORARY | PLANS | SEQUENCES) ; altertablestmt : ALTER TABLE (IF_P EXISTS)? relation_expr (alter_table_cmds | partition_cmd) | ALTER TABLE ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER INDEX (IF_P EXISTS)? qualified_name (alter_table_cmds | index_partition_cmd) | ALTER INDEX ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER SEQUENCE (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER VIEW (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER MATERIALIZED VIEW (IF_P EXISTS)? qualified_name alter_table_cmds | ALTER MATERIALIZED VIEW ALL IN_P TABLESPACE name (OWNED BY role_list)? SET TABLESPACE name opt_nowait | ALTER FOREIGN TABLE (IF_P EXISTS)? relation_expr alter_table_cmds ; alter_table_cmds : alter_table_cmd (COMMA alter_table_cmd)* ; partition_cmd : ATTACH PARTITION qualified_name partitionboundspec | DETACH PARTITION qualified_name ; index_partition_cmd : ATTACH PARTITION qualified_name ; alter_table_cmd : ADD_P columnDef | ADD_P IF_P NOT EXISTS columnDef | ADD_P COLUMN columnDef | ADD_P COLUMN IF_P NOT EXISTS columnDef | ALTER opt_column colid alter_column_default | ALTER opt_column colid DROP NOT NULL_P | ALTER opt_column colid SET NOT NULL_P | ALTER opt_column colid DROP EXPRESSION | ALTER opt_column colid DROP EXPRESSION IF_P EXISTS | ALTER opt_column colid SET STATISTICS signediconst | ALTER opt_column iconst SET STATISTICS signediconst | ALTER opt_column colid SET reloptions | ALTER opt_column colid RESET reloptions | ALTER opt_column colid SET STORAGE colid | ALTER opt_column colid ADD_P GENERATED generated_when AS IDENTITY_P optparenthesizedseqoptlist | ALTER opt_column colid alter_identity_column_option_list | ALTER opt_column colid DROP IDENTITY_P | ALTER opt_column colid DROP IDENTITY_P IF_P EXISTS | DROP opt_column IF_P EXISTS colid opt_drop_behavior | DROP opt_column colid opt_drop_behavior | ALTER opt_column colid opt_set_data TYPE_P typename opt_collate_clause alter_using | ALTER opt_column colid alter_generic_options | ADD_P tableconstraint | ALTER CONSTRAINT name constraintattributespec | VALIDATE CONSTRAINT name | DROP CONSTRAINT IF_P EXISTS name opt_drop_behavior | DROP CONSTRAINT name opt_drop_behavior | SET WITHOUT OIDS | CLUSTER ON name | SET WITHOUT CLUSTER | SET LOGGED | SET UNLOGGED | ENABLE_P TRIGGER name | ENABLE_P ALWAYS TRIGGER name | ENABLE_P REPLICA TRIGGER name | ENABLE_P TRIGGER ALL | ENABLE_P TRIGGER USER | DISABLE_P TRIGGER name | DISABLE_P TRIGGER ALL | DISABLE_P TRIGGER USER | ENABLE_P RULE name | ENABLE_P ALWAYS RULE name | ENABLE_P REPLICA RULE name | DISABLE_P RULE name | INHERIT qualified_name | NO INHERIT qualified_name | OF any_name | NOT OF | OWNER TO rolespec | SET TABLESPACE name | SET reloptions | RESET reloptions | REPLICA IDENTITY_P replica_identity | ENABLE_P ROW LEVEL SECURITY | DISABLE_P ROW LEVEL SECURITY | FORCE ROW LEVEL SECURITY | NO FORCE ROW LEVEL SECURITY | alter_generic_options ; alter_column_default : SET DEFAULT a_expr | DROP DEFAULT ; opt_drop_behavior : CASCADE | RESTRICT | ; opt_collate_clause : COLLATE any_name | ; alter_using : USING a_expr | ; replica_identity : NOTHING | FULL | DEFAULT | USING INDEX name ; reloptions : OPEN_PAREN reloption_list CLOSE_PAREN ; opt_reloptions : WITH reloptions | ; reloption_list : reloption_elem (COMMA reloption_elem)* ; reloption_elem : collabel (EQUAL def_arg | DOT collabel (EQUAL def_arg)?)? ; alter_identity_column_option_list : alter_identity_column_option+ ; alter_identity_column_option : RESTART (opt_with numericonly)? | SET (seqoptelem | GENERATED generated_when) ; partitionboundspec : FOR VALUES WITH OPEN_PAREN hash_partbound CLOSE_PAREN | FOR VALUES IN_P OPEN_PAREN expr_list CLOSE_PAREN | FOR VALUES FROM OPEN_PAREN expr_list CLOSE_PAREN TO OPEN_PAREN expr_list CLOSE_PAREN | DEFAULT ; hash_partbound_elem : nonreservedword iconst ; hash_partbound : hash_partbound_elem (COMMA hash_partbound_elem)* ; altercompositetypestmt : ALTER TYPE_P any_name alter_type_cmds ; alter_type_cmds : alter_type_cmd (COMMA alter_type_cmd)* ; alter_type_cmd : ADD_P ATTRIBUTE tablefuncelement opt_drop_behavior | DROP ATTRIBUTE (IF_P EXISTS)? colid opt_drop_behavior | ALTER ATTRIBUTE colid opt_set_data TYPE_P typename opt_collate_clause opt_drop_behavior ; closeportalstmt : CLOSE (cursor_name | ALL) ; copystmt : COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause | COPY OPEN_PAREN preparablestmt CLOSE_PAREN TO opt_program copy_file_name opt_with copy_options ; copy_from : FROM | TO ; opt_program : PROGRAM | ; copy_file_name : sconst | STDIN | STDOUT ; copy_options : copy_opt_list | OPEN_PAREN copy_generic_opt_list CLOSE_PAREN ; copy_opt_list : copy_opt_item* ; copy_opt_item : BINARY | FREEZE | DELIMITER opt_as sconst | NULL_P opt_as sconst | CSV | HEADER_P | QUOTE opt_as sconst | ESCAPE opt_as sconst | FORCE QUOTE columnlist | FORCE QUOTE STAR | FORCE NOT NULL_P columnlist | FORCE NULL_P columnlist | ENCODING sconst ; opt_binary : BINARY | ; copy_delimiter : opt_using DELIMITERS sconst | ; opt_using : USING | ; copy_generic_opt_list : copy_generic_opt_elem (COMMA copy_generic_opt_elem)* ; copy_generic_opt_elem : collabel copy_generic_opt_arg ; copy_generic_opt_arg : opt_boolean_or_string | numericonly | STAR | OPEN_PAREN copy_generic_opt_arg_list CLOSE_PAREN | ; copy_generic_opt_arg_list : copy_generic_opt_arg_list_item (COMMA copy_generic_opt_arg_list_item)* ; copy_generic_opt_arg_list_item : opt_boolean_or_string ; createstmt : CREATE opttemp TABLE (IF_P NOT EXISTS)? qualified_name ( OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit optpartitionspec table_access_method_clause gaussprimayindex optwith oncommitoption opttablespace gaussextension | OF any_name opttypedtableelementlist optpartitionspec table_access_method_clause optwith oncommitoption opttablespace | PARTITION OF qualified_name opttypedtableelementlist partitionboundspec optpartitionspec table_access_method_clause optwith oncommitoption opttablespace ) ; // -------- support gauss gaussprimayindex : PRIMARY INDEX OPEN_PAREN colid CLOSE_PAREN | ; gaussextension : distributeby toGroupOrNode tablePartition? | ; distributeby : DISTRIBUTE BY (REPLICATION | ROUNDROBIN | HASH OPEN_PAREN distributebyhashlist CLOSE_PAREN) | DISTRIBUTED BY OPEN_PAREN distributebyhashlist CLOSE_PAREN | DISTRIBUTED (RANDOMLY | REPLICATED) | ; distributebyhashlist : distributebyhashitem (COMMA distributebyhashitem)* ; distributebyhashitem : collabel ; toGroupOrNode : TO GROUP_P collabel | TO NODE_P OPEN_PAREN collabel (COMMA collabel)* CLOSE_PAREN | ; tablePartition : PARTITION BY partition_list ((ENABLE_P | DISABLE_P) ROW MOVEMENT)? ; partition_list : value_partition_stmt | range_partition_stmt | list_partition_stmt | normal_partition_stmt ; normal_partition_stmt : OPEN_PAREN list_partition_value CLOSE_PAREN AUTOMAPPED? ; list_partition_stmt : LIST_P OPEN_PAREN partition_key CLOSE_PAREN OPEN_PAREN list_partition_items CLOSE_PAREN ; list_partition_items : list_partition_item (COMMA list_partition_item)* ; list_partition_item : PARTITION partition_name VALUES LESS THAN OPEN_PAREN list_partition_value CLOSE_PAREN table_space_item? ; list_partition_value : partition_name (COMMA partition_name)* | DEFAULT ; value_partition_stmt : VALUES OPEN_PAREN partition_key CLOSE_PAREN ; range_partition_stmt : RANGE OPEN_PAREN partition_key CLOSE_PAREN OPEN_PAREN (partition_less_than_items | partition_start_end_items) CLOSE_PAREN ; partition_less_than_items : partition_less_than_item (COMMA partition_less_than_item)* ; partition_start_end_items : partition_start_end_item (COMMA partition_start_end_item)* ; partition_less_than_item : PARTITION partition_name VALUES LESS THAN OPEN_PAREN (partition_value | MAXVALUE) CLOSE_PAREN table_space_item? ; partition_start_end_item : PARTITION partition_name start_end_item table_space_item? ; start_end_item : start_item | end_item | start_item end_item (EVERY OPEN_PAREN aexprconst CLOSE_PAREN)? ; start_item : START OPEN_PAREN partition_value CLOSE_PAREN ; end_item : END_P OPEN_PAREN (partition_value | MAXVALUE) CLOSE_PAREN ; partition_key : colid ; partition_name : colid ; partition_value : a_expr ; table_space_item : TABLESPACE table_space_name ; table_space_name : qualified_name ; // -------- support gauss opttemp : TEMPORARY | TEMP | LOCAL (TEMPORARY | TEMP) | GLOBAL (TEMPORARY | TEMP) | UNLOGGED | ; opttableelementlist : tableelementlist | ; opttypedtableelementlist : OPEN_PAREN typedtableelementlist CLOSE_PAREN | ; tableelementlist : tableelement (COMMA tableelement)* ; typedtableelementlist : typedtableelement (COMMA typedtableelement)* ; tableelement : tableconstraint | tablelikeclause | columnDef ; typedtableelement : columnOptions | tableconstraint ; columnDef : colid typename create_generic_options colquallist ; columnOptions : colid (WITH OPTIONS)? colquallist ; colquallist : colconstraint* ; colconstraint : CONSTRAINT name colconstraintelem | colconstraintelem | constraintattr | COLLATE any_name ; colconstraintelem : NOT NULL_P | NULL_P | UNIQUE opt_definition optconstablespace | PRIMARY KEY opt_definition optconstablespace | CHECK OPEN_PAREN a_expr CLOSE_PAREN opt_no_inherit | DEFAULT b_expr | GENERATED generated_when AS (IDENTITY_P optparenthesizedseqoptlist | OPEN_PAREN a_expr CLOSE_PAREN STORED) | REFERENCES qualified_name opt_column_list key_match key_actions ; generated_when : ALWAYS | BY DEFAULT ; constraintattr : DEFERRABLE | NOT DEFERRABLE | INITIALLY (DEFERRED | IMMEDIATE) ; tablelikeclause : LIKE qualified_name tablelikeoptionlist ; tablelikeoptionlist : ((INCLUDING | EXCLUDING) tablelikeoption)* ; tablelikeoption : COMMENTS | CONSTRAINTS | DEFAULTS | IDENTITY_P | GENERATED | INDEXES | STATISTICS | STORAGE | ALL ; tableconstraint : CONSTRAINT name constraintelem | constraintelem ; constraintelem : CHECK OPEN_PAREN a_expr CLOSE_PAREN constraintattributespec | UNIQUE (OPEN_PAREN columnlist CLOSE_PAREN opt_c_include opt_definition optconstablespace constraintattributespec | existingindex constraintattributespec) | PRIMARY KEY (OPEN_PAREN columnlist CLOSE_PAREN opt_c_include opt_definition optconstablespace constraintattributespec | existingindex constraintattributespec) | EXCLUDE access_method_clause OPEN_PAREN exclusionconstraintlist CLOSE_PAREN opt_c_include opt_definition optconstablespace exclusionwhereclause constraintattributespec | FOREIGN KEY OPEN_PAREN columnlist CLOSE_PAREN REFERENCES qualified_name opt_column_list key_match key_actions constraintattributespec ; opt_no_inherit : NO INHERIT | ; opt_column_list : OPEN_PAREN columnlist CLOSE_PAREN | ; columnlist : columnElem (COMMA columnElem)* ; columnElem : colid ; opt_c_include : INCLUDE OPEN_PAREN columnlist CLOSE_PAREN | ; key_match : MATCH (FULL | PARTIAL | SIMPLE) | ; exclusionconstraintlist : exclusionconstraintelem (COMMA exclusionconstraintelem)* ; exclusionconstraintelem : index_elem WITH (any_operator | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN) ; exclusionwhereclause : WHERE OPEN_PAREN a_expr CLOSE_PAREN | ; key_actions : key_update | key_delete | key_update key_delete | key_delete key_update | ; key_update : ON UPDATE key_action ; key_delete : ON DELETE_P key_action ; key_action : NO ACTION | RESTRICT | CASCADE | SET (NULL_P | DEFAULT) ; optinherit : INHERITS OPEN_PAREN qualified_name_list CLOSE_PAREN | ; optpartitionspec : partitionspec | ; partitionspec : PARTITION BY colid OPEN_PAREN part_params CLOSE_PAREN ; part_params : part_elem (COMMA part_elem)* ; part_elem : colid opt_collate opt_class | func_expr_windowless opt_collate opt_class | OPEN_PAREN a_expr CLOSE_PAREN opt_collate opt_class ; table_access_method_clause : USING name | ; optwith : WITH reloptions | WITHOUT OIDS | ; oncommitoption : ON COMMIT (DROP | DELETE_P ROWS | PRESERVE ROWS) | ; opttablespace : TABLESPACE name | ; optconstablespace : USING INDEX TABLESPACE name | ; existingindex : USING INDEX name ; createstatsstmt : CREATE STATISTICS (IF_P NOT EXISTS)? any_name opt_name_list ON expr_list FROM from_list ; alterstatsstmt : ALTER STATISTICS (IF_P EXISTS)? any_name SET STATISTICS signediconst ; createasstmt : CREATE opttemp TABLE (IF_P NOT EXISTS)? create_as_target AS selectstmt opt_with_data ; create_as_target : qualified_name opt_column_list table_access_method_clause optwith oncommitoption opttablespace ; opt_with_data : WITH (DATA_P | NO DATA_P) | ; creatematviewstmt : CREATE optnolog MATERIALIZED VIEW (IF_P NOT EXISTS)? create_mv_target AS selectstmt opt_with_data ; create_mv_target : qualified_name opt_column_list table_access_method_clause opt_reloptions opttablespace ; optnolog : UNLOGGED | ; refreshmatviewstmt : REFRESH MATERIALIZED VIEW opt_concurrently qualified_name opt_with_data ; createseqstmt : CREATE opttemp SEQUENCE (IF_P NOT EXISTS)? qualified_name optseqoptlist ; alterseqstmt : ALTER SEQUENCE (IF_P EXISTS)? qualified_name seqoptlist ; optseqoptlist : seqoptlist | ; optparenthesizedseqoptlist : OPEN_PAREN seqoptlist CLOSE_PAREN | ; seqoptlist : seqoptelem+ ; seqoptelem : AS simpletypename | CACHE numericonly | CYCLE | INCREMENT opt_by numericonly | MAXVALUE numericonly | MINVALUE numericonly | NO (MAXVALUE | MINVALUE | CYCLE) | OWNED BY any_name | SEQUENCE NAME_P any_name | START opt_with numericonly | RESTART opt_with numericonly? ; opt_by : BY | ; numericonly : fconst | PLUS fconst | MINUS fconst | signediconst ; numericonly_list : numericonly (COMMA numericonly)* ; createplangstmt : CREATE opt_or_replace opt_trusted opt_procedural LANGUAGE name (HANDLER handler_name opt_inline_handler opt_validator)? ; opt_trusted : TRUSTED | ; handler_name : name attrs? ; opt_inline_handler : INLINE_P handler_name | ; validator_clause : VALIDATOR handler_name | NO VALIDATOR ; opt_validator : validator_clause | ; opt_procedural : PROCEDURAL | ; createtablespacestmt : CREATE TABLESPACE name opttablespaceowner LOCATION sconst opt_reloptions ; opttablespaceowner : OWNER rolespec | ; droptablespacestmt : DROP TABLESPACE (IF_P EXISTS)? name ; createextensionstmt : CREATE EXTENSION (IF_P NOT EXISTS)? name opt_with create_extension_opt_list ; create_extension_opt_list : create_extension_opt_item* ; create_extension_opt_item : SCHEMA name | VERSION_P nonreservedword_or_sconst | FROM nonreservedword_or_sconst | CASCADE ; alterextensionstmt : ALTER EXTENSION name UPDATE alter_extension_opt_list ; alter_extension_opt_list : alter_extension_opt_item* ; alter_extension_opt_item : TO nonreservedword_or_sconst ; alterextensioncontentsstmt : ALTER EXTENSION name add_drop object_type_name name | ALTER EXTENSION name add_drop object_type_any_name any_name | ALTER EXTENSION name add_drop AGGREGATE aggregate_with_argtypes | ALTER EXTENSION name add_drop CAST OPEN_PAREN typename AS typename CLOSE_PAREN | ALTER EXTENSION name add_drop DOMAIN_P typename | ALTER EXTENSION name add_drop FUNCTION function_with_argtypes | ALTER EXTENSION name add_drop OPERATOR operator_with_argtypes | ALTER EXTENSION name add_drop OPERATOR CLASS any_name USING name | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING name | ALTER EXTENSION name add_drop PROCEDURE function_with_argtypes | ALTER EXTENSION name add_drop ROUTINE function_with_argtypes | ALTER EXTENSION name add_drop TRANSFORM FOR typename LANGUAGE name | ALTER EXTENSION name add_drop TYPE_P typename ; createfdwstmt : CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options ; fdw_option : HANDLER handler_name | NO HANDLER | VALIDATOR handler_name | NO VALIDATOR ; fdw_options : fdw_option+ ; opt_fdw_options : fdw_options | ; alterfdwstmt : ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options | ALTER FOREIGN DATA_P WRAPPER name fdw_options ; create_generic_options : OPTIONS OPEN_PAREN generic_option_list CLOSE_PAREN | ; generic_option_list : generic_option_elem (COMMA generic_option_elem)* ; alter_generic_options : OPTIONS OPEN_PAREN alter_generic_option_list CLOSE_PAREN ; alter_generic_option_list : alter_generic_option_elem (COMMA alter_generic_option_elem)* ; alter_generic_option_elem : generic_option_elem | SET generic_option_elem | ADD_P generic_option_elem | DROP generic_option_name ; generic_option_elem : generic_option_name generic_option_arg ; generic_option_name : collabel ; generic_option_arg : sconst ; createforeignserverstmt : CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options | CREATE SERVER IF_P NOT EXISTS name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER name create_generic_options ; opt_type : TYPE_P sconst | ; foreign_server_version : VERSION_P (sconst | NULL_P) ; opt_foreign_server_version : foreign_server_version | ; alterforeignserverstmt : ALTER SERVER name (alter_generic_options | foreign_server_version alter_generic_options?) ; createforeigntablestmt : CREATE FOREIGN TABLE qualified_name OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit SERVER name create_generic_options | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name OPEN_PAREN opttableelementlist CLOSE_PAREN optinherit SERVER name create_generic_options | CREATE FOREIGN TABLE qualified_name PARTITION OF qualified_name opttypedtableelementlist partitionboundspec SERVER name create_generic_options | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name PARTITION OF qualified_name opttypedtableelementlist partitionboundspec SERVER name create_generic_options ; importforeignschemastmt : IMPORT_P FOREIGN SCHEMA name import_qualification FROM SERVER name INTO name create_generic_options ; import_qualification_type : LIMIT TO | EXCEPT ; import_qualification : import_qualification_type OPEN_PAREN relation_expr_list CLOSE_PAREN | ; createusermappingstmt : CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options | CREATE USER MAPPING IF_P NOT EXISTS FOR auth_ident SERVER name create_generic_options ; auth_ident : rolespec | USER ; dropusermappingstmt : DROP USER MAPPING FOR auth_ident SERVER name | DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name ; alterusermappingstmt : ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options ; createpolicystmt : CREATE POLICY name ON qualified_name rowsecuritydefaultpermissive rowsecuritydefaultforcmd rowsecuritydefaulttorole rowsecurityoptionalexpr rowsecurityoptionalwithcheck ; alterpolicystmt : ALTER POLICY name ON qualified_name rowsecurityoptionaltorole rowsecurityoptionalexpr rowsecurityoptionalwithcheck ; rowsecurityoptionalexpr : USING OPEN_PAREN a_expr CLOSE_PAREN | ; rowsecurityoptionalwithcheck : WITH CHECK OPEN_PAREN a_expr CLOSE_PAREN | ; rowsecuritydefaulttorole : TO role_list | ; rowsecurityoptionaltorole : TO role_list | ; rowsecuritydefaultpermissive : AS identifier | ; rowsecuritydefaultforcmd : FOR row_security_cmd | ; row_security_cmd : ALL | SELECT | INSERT | UPDATE | DELETE_P ; createamstmt : CREATE ACCESS METHOD name TYPE_P am_type HANDLER handler_name ; am_type : INDEX | TABLE ; createtrigstmt : CREATE TRIGGER name triggeractiontime triggerevents ON qualified_name triggerreferencing triggerforspec triggerwhen EXECUTE function_or_procedure func_name OPEN_PAREN triggerfuncargs CLOSE_PAREN | CREATE CONSTRAINT TRIGGER name AFTER triggerevents ON qualified_name optconstrfromtable constraintattributespec FOR EACH ROW triggerwhen EXECUTE function_or_procedure func_name OPEN_PAREN triggerfuncargs CLOSE_PAREN ; triggeractiontime : BEFORE | AFTER | INSTEAD OF ; triggerevents : triggeroneevent (OR triggeroneevent)* ; triggeroneevent : INSERT | DELETE_P | UPDATE | UPDATE OF columnlist | TRUNCATE ; triggerreferencing : REFERENCING triggertransitions | ; triggertransitions : triggertransition+ ; triggertransition : transitionoldornew transitionrowortable opt_as transitionrelname ; transitionoldornew : NEW | OLD ; transitionrowortable : TABLE | ROW ; transitionrelname : colid ; triggerforspec : FOR triggerforopteach triggerfortype | ; triggerforopteach : EACH | ; triggerfortype : ROW | STATEMENT ; triggerwhen : WHEN OPEN_PAREN a_expr CLOSE_PAREN | ; function_or_procedure : FUNCTION | PROCEDURE ; triggerfuncargs : (triggerfuncarg |) (COMMA triggerfuncarg)* ; triggerfuncarg : iconst | fconst | sconst | collabel ; optconstrfromtable : FROM qualified_name | ; constraintattributespec : constraintattributeElem* ; constraintattributeElem : NOT DEFERRABLE | DEFERRABLE | INITIALLY IMMEDIATE | INITIALLY DEFERRED | NOT VALID | NO INHERIT ; createeventtrigstmt : CREATE EVENT TRIGGER name ON collabel EXECUTE function_or_procedure func_name OPEN_PAREN CLOSE_PAREN | CREATE EVENT TRIGGER name ON collabel WHEN event_trigger_when_list EXECUTE function_or_procedure func_name OPEN_PAREN CLOSE_PAREN ; event_trigger_when_list : event_trigger_when_item (AND event_trigger_when_item)* ; event_trigger_when_item : colid IN_P OPEN_PAREN event_trigger_value_list CLOSE_PAREN ; event_trigger_value_list : sconst (COMMA sconst)* ; altereventtrigstmt : ALTER EVENT TRIGGER name enable_trigger ; enable_trigger : ENABLE_P | ENABLE_P REPLICA | ENABLE_P ALWAYS | DISABLE_P ; createassertionstmt : CREATE ASSERTION any_name CHECK OPEN_PAREN a_expr CLOSE_PAREN constraintattributespec ; definestmt : CREATE opt_or_replace AGGREGATE func_name aggr_args definition | CREATE opt_or_replace AGGREGATE func_name old_aggr_definition | CREATE OPERATOR any_operator definition | CREATE TYPE_P any_name definition | CREATE TYPE_P any_name | CREATE TYPE_P any_name AS OPEN_PAREN opttablefuncelementlist CLOSE_PAREN | CREATE TYPE_P any_name AS ENUM_P OPEN_PAREN opt_enum_val_list CLOSE_PAREN | CREATE TYPE_P any_name AS RANGE definition | CREATE TEXT_P SEARCH PARSER any_name definition | CREATE TEXT_P SEARCH DICTIONARY any_name definition | CREATE TEXT_P SEARCH TEMPLATE any_name definition | CREATE TEXT_P SEARCH CONFIGURATION any_name definition | CREATE COLLATION any_name definition | CREATE COLLATION IF_P NOT EXISTS any_name definition | CREATE COLLATION any_name FROM any_name | CREATE COLLATION IF_P NOT EXISTS any_name FROM any_name ; definition : OPEN_PAREN def_list CLOSE_PAREN ; def_list : def_elem (COMMA def_elem)* ; def_elem : collabel (EQUAL def_arg)? ; def_arg : func_type | reserved_keyword | qual_all_op | numericonly | sconst | NONE ; old_aggr_definition : OPEN_PAREN old_aggr_list CLOSE_PAREN ; old_aggr_list : old_aggr_elem (COMMA old_aggr_elem)* ; old_aggr_elem : identifier EQUAL def_arg ; opt_enum_val_list : enum_val_list | ; enum_val_list : sconst (COMMA sconst)* ; alterenumstmt : ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst BEFORE sconst | ALTER TYPE_P any_name ADD_P VALUE_P opt_if_not_exists sconst AFTER sconst | ALTER TYPE_P any_name RENAME VALUE_P sconst TO sconst ; opt_if_not_exists : IF_P NOT EXISTS | ; createopclassstmt : CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P typename USING name opt_opfamily AS opclass_item_list ; opclass_item_list : opclass_item (COMMA opclass_item)* ; opclass_item : OPERATOR iconst any_operator opclass_purpose opt_recheck | OPERATOR iconst operator_with_argtypes opclass_purpose opt_recheck | FUNCTION iconst function_with_argtypes | FUNCTION iconst OPEN_PAREN type_list CLOSE_PAREN function_with_argtypes | STORAGE typename ; opt_default : DEFAULT | ; opt_opfamily : FAMILY any_name | ; opclass_purpose : FOR SEARCH | FOR ORDER BY any_name | ; opt_recheck : RECHECK | ; createopfamilystmt : CREATE OPERATOR FAMILY any_name USING name ; alteropfamilystmt : ALTER OPERATOR FAMILY any_name USING name ADD_P opclass_item_list | ALTER OPERATOR FAMILY any_name USING name DROP opclass_drop_list ; opclass_drop_list : opclass_drop (COMMA opclass_drop)* ; opclass_drop : OPERATOR iconst OPEN_PAREN type_list CLOSE_PAREN | FUNCTION iconst OPEN_PAREN type_list CLOSE_PAREN ; dropopclassstmt : DROP OPERATOR CLASS any_name USING name opt_drop_behavior | DROP OPERATOR CLASS IF_P EXISTS any_name USING name opt_drop_behavior ; dropopfamilystmt : DROP OPERATOR FAMILY any_name USING name opt_drop_behavior | DROP OPERATOR FAMILY IF_P EXISTS any_name USING name opt_drop_behavior ; dropownedstmt : DROP OWNED BY role_list opt_drop_behavior ; reassignownedstmt : REASSIGN OWNED BY role_list TO rolespec ; dropstmt : DROP object_type_any_name IF_P EXISTS any_name_list opt_drop_behavior | DROP object_type_any_name any_name_list opt_drop_behavior | DROP drop_type_name IF_P EXISTS name_list opt_drop_behavior | DROP drop_type_name name_list opt_drop_behavior | DROP object_type_name_on_any_name name ON any_name opt_drop_behavior | DROP object_type_name_on_any_name IF_P EXISTS name ON any_name opt_drop_behavior | DROP TYPE_P type_name_list opt_drop_behavior | DROP TYPE_P IF_P EXISTS type_name_list opt_drop_behavior | DROP DOMAIN_P type_name_list opt_drop_behavior | DROP DOMAIN_P IF_P EXISTS type_name_list opt_drop_behavior | DROP INDEX CONCURRENTLY any_name_list opt_drop_behavior | DROP INDEX CONCURRENTLY IF_P EXISTS any_name_list opt_drop_behavior ; object_type_any_name : TABLE | SEQUENCE | VIEW | MATERIALIZED VIEW | INDEX | FOREIGN TABLE | COLLATION | CONVERSION_P | STATISTICS | TEXT_P SEARCH PARSER | TEXT_P SEARCH DICTIONARY | TEXT_P SEARCH TEMPLATE | TEXT_P SEARCH CONFIGURATION ; object_type_name : drop_type_name | DATABASE | ROLE | SUBSCRIPTION | TABLESPACE ; drop_type_name : ACCESS METHOD | EVENT TRIGGER | EXTENSION | FOREIGN DATA_P WRAPPER | opt_procedural LANGUAGE | PUBLICATION | SCHEMA | SERVER ; object_type_name_on_any_name : POLICY | RULE | TRIGGER ; any_name_list : any_name (COMMA any_name)* ; any_name : colid attrs? ; attrs :(DOT attr_name)+ ; type_name_list : typename (COMMA typename)* ; truncatestmt : TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior ; opt_restart_seqs : CONTINUE_P IDENTITY_P | RESTART IDENTITY_P | ; commentstmt : COMMENT ON object_type_any_name any_name IS comment_text | COMMENT ON COLUMN any_name IS comment_text | COMMENT ON object_type_name name IS comment_text | COMMENT ON TYPE_P typename IS comment_text | COMMENT ON DOMAIN_P typename IS comment_text | COMMENT ON AGGREGATE aggregate_with_argtypes IS comment_text | COMMENT ON FUNCTION function_with_argtypes IS comment_text | COMMENT ON OPERATOR operator_with_argtypes IS comment_text | COMMENT ON CONSTRAINT name ON any_name IS comment_text | COMMENT ON CONSTRAINT name ON DOMAIN_P any_name IS comment_text | COMMENT ON object_type_name_on_any_name name ON any_name IS comment_text | COMMENT ON PROCEDURE function_with_argtypes IS comment_text | COMMENT ON ROUTINE function_with_argtypes IS comment_text | COMMENT ON TRANSFORM FOR typename LANGUAGE name IS comment_text | COMMENT ON OPERATOR CLASS any_name USING name IS comment_text | COMMENT ON OPERATOR FAMILY any_name USING name IS comment_text | COMMENT ON LARGE_P OBJECT_P numericonly IS comment_text | COMMENT ON CAST OPEN_PAREN typename AS typename CLOSE_PAREN IS comment_text ; comment_text : sconst | NULL_P ; seclabelstmt : SECURITY LABEL opt_provider ON object_type_any_name any_name IS security_label | SECURITY LABEL opt_provider ON COLUMN any_name IS security_label | SECURITY LABEL opt_provider ON object_type_name name IS security_label | SECURITY LABEL opt_provider ON TYPE_P typename IS security_label | SECURITY LABEL opt_provider ON DOMAIN_P typename IS security_label | SECURITY LABEL opt_provider ON AGGREGATE aggregate_with_argtypes IS security_label | SECURITY LABEL opt_provider ON FUNCTION function_with_argtypes IS security_label | SECURITY LABEL opt_provider ON LARGE_P OBJECT_P numericonly IS security_label | SECURITY LABEL opt_provider ON PROCEDURE function_with_argtypes IS security_label | SECURITY LABEL opt_provider ON ROUTINE function_with_argtypes IS security_label ; opt_provider : FOR nonreservedword_or_sconst | ; security_label : sconst | NULL_P ; fetchstmt : FETCH fetch_args | MOVE fetch_args ; fetch_args : cursor_name | from_in cursor_name | NEXT opt_from_in cursor_name | PRIOR opt_from_in cursor_name | FIRST_P opt_from_in cursor_name | LAST_P opt_from_in cursor_name | ABSOLUTE_P signediconst opt_from_in cursor_name | RELATIVE_P signediconst opt_from_in cursor_name | signediconst opt_from_in cursor_name | ALL opt_from_in cursor_name | FORWARD opt_from_in cursor_name | FORWARD signediconst opt_from_in cursor_name | FORWARD ALL opt_from_in cursor_name | BACKWARD opt_from_in cursor_name | BACKWARD signediconst opt_from_in cursor_name | BACKWARD ALL opt_from_in cursor_name ; from_in : FROM | IN_P ; opt_from_in : from_in | ; grantstmt : GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option ; revokestmt : REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior ; privileges : privilege_list | ALL | ALL PRIVILEGES | ALL OPEN_PAREN columnlist CLOSE_PAREN | ALL PRIVILEGES OPEN_PAREN columnlist CLOSE_PAREN ; privilege_list : privilege (COMMA privilege)* ; privilege : SELECT opt_column_list | REFERENCES opt_column_list | CREATE opt_column_list | colid opt_column_list ; privilege_target : qualified_name_list | TABLE qualified_name_list | SEQUENCE qualified_name_list | FOREIGN DATA_P WRAPPER name_list | FOREIGN SERVER name_list | FUNCTION function_with_argtypes_list | PROCEDURE function_with_argtypes_list | ROUTINE function_with_argtypes_list | DATABASE name_list | DOMAIN_P any_name_list | LANGUAGE name_list | LARGE_P OBJECT_P numericonly_list | SCHEMA name_list | TABLESPACE name_list | TYPE_P any_name_list | ALL TABLES IN_P SCHEMA name_list | ALL SEQUENCES IN_P SCHEMA name_list | ALL FUNCTIONS IN_P SCHEMA name_list | ALL PROCEDURES IN_P SCHEMA name_list | ALL ROUTINES IN_P SCHEMA name_list ; grantee_list : grantee (COMMA grantee)* ; grantee : rolespec | GROUP_P rolespec ; opt_grant_grant_option : WITH GRANT OPTION | ; grantrolestmt : GRANT privilege_list TO role_list opt_grant_admin_option opt_granted_by ; revokerolestmt : REVOKE privilege_list FROM role_list opt_granted_by opt_drop_behavior | REVOKE ADMIN OPTION FOR privilege_list FROM role_list opt_granted_by opt_drop_behavior ; opt_grant_admin_option : WITH ADMIN OPTION | ; opt_granted_by : GRANTED BY rolespec | ; alterdefaultprivilegesstmt : ALTER DEFAULT PRIVILEGES defacloptionlist defaclaction ; defacloptionlist : defacloption* ; defacloption : IN_P SCHEMA name_list | FOR ROLE role_list | FOR USER role_list ; defaclaction : GRANT privileges ON defacl_privilege_target TO grantee_list opt_grant_grant_option | REVOKE privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior | REVOKE GRANT OPTION FOR privileges ON defacl_privilege_target FROM grantee_list opt_drop_behavior ; defacl_privilege_target : TABLES | FUNCTIONS | ROUTINES | SEQUENCES | TYPES_P | SCHEMAS ; //create index indexstmt : CREATE opt_unique INDEX opt_concurrently opt_index_name ON relation_expr access_method_clause OPEN_PAREN index_params CLOSE_PAREN opt_include opt_reloptions opttablespace where_clause | CREATE opt_unique INDEX opt_concurrently IF_P NOT EXISTS name ON relation_expr access_method_clause OPEN_PAREN index_params CLOSE_PAREN opt_include opt_reloptions opttablespace where_clause ; opt_unique : UNIQUE | ; opt_concurrently : CONCURRENTLY | ; opt_index_name : name | ; access_method_clause : USING name | ; index_params : index_elem (COMMA index_elem)* ; index_elem_options : opt_collate opt_class opt_asc_desc opt_nulls_order | opt_collate any_name reloptions opt_asc_desc opt_nulls_order ; index_elem : colid index_elem_options | func_expr_windowless index_elem_options | OPEN_PAREN a_expr CLOSE_PAREN index_elem_options ; opt_include : INCLUDE OPEN_PAREN index_including_params CLOSE_PAREN | ; index_including_params : index_elem (COMMA index_elem)* ; opt_collate : COLLATE any_name | ; opt_class : any_name | ; opt_asc_desc : ASC | DESC | ; //TOD NULLS_LA was used opt_nulls_order : NULLS_P FIRST_P | NULLS_P LAST_P | ; createfunctionstmt : CREATE opt_or_replace (FUNCTION | PROCEDURE) func_name func_args_with_defaults ( RETURNS (func_return | TABLE OPEN_PAREN table_func_column_list CLOSE_PAREN) )? createfunc_opt_list ; opt_or_replace : OR REPLACE | ; func_args : OPEN_PAREN func_args_list? CLOSE_PAREN ; func_args_list : func_arg (COMMA func_arg)* ; function_with_argtypes_list : function_with_argtypes (COMMA function_with_argtypes)* ; function_with_argtypes : func_name func_args | type_func_name_keyword | colid indirection? ; func_args_with_defaults : OPEN_PAREN func_args_with_defaults_list? CLOSE_PAREN ; func_args_with_defaults_list : func_arg_with_default (COMMA func_arg_with_default)* ; func_arg : arg_class param_name? func_type | param_name arg_class? func_type | func_type ; arg_class : IN_P OUT_P? | OUT_P | INOUT | VARIADIC ; param_name : type_function_name | builtin_function_name | LEFT | RIGHT ; func_return : func_type ; func_type : typename | SETOF? (builtin_function_name | type_function_name | LEFT | RIGHT) attrs PERCENT TYPE_P ; func_arg_with_default : func_arg ((DEFAULT | EQUAL) a_expr)? ; aggr_arg : func_arg ; aggr_args : OPEN_PAREN (STAR | aggr_args_list | ORDER BY aggr_args_list | aggr_args_list ORDER BY aggr_args_list) CLOSE_PAREN ; aggr_args_list : aggr_arg (COMMA aggr_arg)* ; aggregate_with_argtypes : func_name aggr_args ; aggregate_with_argtypes_list : aggregate_with_argtypes (COMMA aggregate_with_argtypes)* ; createfunc_opt_list : createfunc_opt_item+ { ParseRoutineBody(_localctx); } // | createfunc_opt_list createfunc_opt_item ; common_func_opt_item : CALLED ON NULL_P INPUT_P | RETURNS NULL_P ON NULL_P INPUT_P | STRICT_P | IMMUTABLE | STABLE | VOLATILE | EXTERNAL SECURITY DEFINER | EXTERNAL SECURITY INVOKER | SECURITY DEFINER | SECURITY INVOKER | LEAKPROOF | NOT LEAKPROOF | COST numericonly | ROWS numericonly | SUPPORT any_name | functionsetresetclause | PARALLEL colid ; createfunc_opt_item : AS func_as | LANGUAGE nonreservedword_or_sconst | TRANSFORM transform_type_list | WINDOW | common_func_opt_item ; //https://www.postgresql.org/docs/9.1/sql-createfunction.html // | AS 'definition' // | AS 'obj_file', 'link_symbol' func_as locals[ParserRuleContext Definition] : /* |AS 'definition'*/ def = sconst /*| AS 'obj_file', 'link_symbol'*/ | sconst COMMA sconst ; transform_type_list :FOR TYPE_P typename (COMMA FOR TYPE_P typename)* ; opt_definition : WITH definition | ; table_func_column : param_name func_type ; table_func_column_list : table_func_column (COMMA table_func_column)* ; alterfunctionstmt : ALTER (FUNCTION | PROCEDURE | ROUTINE) function_with_argtypes alterfunc_opt_list opt_restrict ; alterfunc_opt_list : common_func_opt_item+ ; opt_restrict : RESTRICT | ; removefuncstmt : DROP FUNCTION function_with_argtypes_list opt_drop_behavior | DROP FUNCTION IF_P EXISTS function_with_argtypes_list opt_drop_behavior | DROP PROCEDURE function_with_argtypes_list opt_drop_behavior | DROP PROCEDURE IF_P EXISTS function_with_argtypes_list opt_drop_behavior | DROP ROUTINE function_with_argtypes_list opt_drop_behavior | DROP ROUTINE IF_P EXISTS function_with_argtypes_list opt_drop_behavior ; removeaggrstmt : DROP AGGREGATE aggregate_with_argtypes_list opt_drop_behavior | DROP AGGREGATE IF_P EXISTS aggregate_with_argtypes_list opt_drop_behavior ; removeoperstmt : DROP OPERATOR operator_with_argtypes_list opt_drop_behavior | DROP OPERATOR IF_P EXISTS operator_with_argtypes_list opt_drop_behavior ; oper_argtypes : OPEN_PAREN typename CLOSE_PAREN | OPEN_PAREN typename COMMA typename CLOSE_PAREN | OPEN_PAREN NONE COMMA typename CLOSE_PAREN | OPEN_PAREN typename COMMA NONE CLOSE_PAREN ; any_operator : (colid DOT)* all_op ; operator_with_argtypes_list : operator_with_argtypes (COMMA operator_with_argtypes)* ; operator_with_argtypes : any_operator oper_argtypes ; dostmt : DO dostmt_opt_list ; dostmt_opt_list : dostmt_opt_item+ ; dostmt_opt_item : sconst | LANGUAGE nonreservedword_or_sconst ; createcaststmt : CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITH FUNCTION function_with_argtypes cast_context | CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITHOUT FUNCTION cast_context | CREATE CAST OPEN_PAREN typename AS typename CLOSE_PAREN WITH INOUT cast_context ; cast_context : AS IMPLICIT_P | AS ASSIGNMENT | ; dropcaststmt : DROP CAST opt_if_exists OPEN_PAREN typename AS typename CLOSE_PAREN opt_drop_behavior ; opt_if_exists : IF_P EXISTS | ; createtransformstmt : CREATE opt_or_replace TRANSFORM FOR typename LANGUAGE name OPEN_PAREN transform_element_list CLOSE_PAREN ; transform_element_list : FROM SQL_P WITH FUNCTION function_with_argtypes COMMA TO SQL_P WITH FUNCTION function_with_argtypes | TO SQL_P WITH FUNCTION function_with_argtypes COMMA FROM SQL_P WITH FUNCTION function_with_argtypes | FROM SQL_P WITH FUNCTION function_with_argtypes | TO SQL_P WITH FUNCTION function_with_argtypes ; droptransformstmt : DROP TRANSFORM opt_if_exists FOR typename LANGUAGE name opt_drop_behavior ; reindexstmt : REINDEX reindex_target_type opt_concurrently qualified_name | REINDEX reindex_target_multitable opt_concurrently name | REINDEX OPEN_PAREN reindex_option_list CLOSE_PAREN reindex_target_type opt_concurrently qualified_name | REINDEX OPEN_PAREN reindex_option_list CLOSE_PAREN reindex_target_multitable opt_concurrently name ; reindex_target_type : INDEX | TABLE | SCHEMA | DATABASE | SYSTEM_P ; reindex_target_multitable : SCHEMA | SYSTEM_P | DATABASE ; reindex_option_list : reindex_option_elem (COMMA reindex_option_elem)* ; reindex_option_elem : VERBOSE | TABLESPACE | CONCURRENTLY ; altertblspcstmt : ALTER TABLESPACE name SET reloptions | ALTER TABLESPACE name RESET reloptions ; renamestmt : ALTER AGGREGATE aggregate_with_argtypes RENAME TO name | ALTER COLLATION any_name RENAME TO name | ALTER CONVERSION_P any_name RENAME TO name | ALTER DATABASE name RENAME TO name | ALTER DOMAIN_P any_name RENAME TO name | ALTER DOMAIN_P any_name RENAME CONSTRAINT name TO name | ALTER FOREIGN DATA_P WRAPPER name RENAME TO name | ALTER FUNCTION function_with_argtypes RENAME TO name | ALTER GROUP_P roleid RENAME TO roleid | ALTER opt_procedural LANGUAGE name RENAME TO name | ALTER OPERATOR CLASS any_name USING name RENAME TO name | ALTER OPERATOR FAMILY any_name USING name RENAME TO name | ALTER POLICY name ON qualified_name RENAME TO name | ALTER POLICY IF_P EXISTS name ON qualified_name RENAME TO name | ALTER PROCEDURE function_with_argtypes RENAME TO name | ALTER PUBLICATION name RENAME TO name | ALTER ROUTINE function_with_argtypes RENAME TO name | ALTER SCHEMA name RENAME TO name | ALTER SERVER name RENAME TO name | ALTER SUBSCRIPTION name RENAME TO name | ALTER TABLE relation_expr RENAME TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME TO name | ALTER SEQUENCE qualified_name RENAME TO name | ALTER SEQUENCE IF_P EXISTS qualified_name RENAME TO name | ALTER VIEW qualified_name RENAME TO name | ALTER VIEW IF_P EXISTS qualified_name RENAME TO name | ALTER MATERIALIZED VIEW qualified_name RENAME TO name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME TO name | ALTER INDEX qualified_name RENAME TO name | ALTER INDEX IF_P EXISTS qualified_name RENAME TO name | ALTER FOREIGN TABLE relation_expr RENAME TO name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME TO name | ALTER TABLE relation_expr RENAME opt_column name TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name | ALTER VIEW qualified_name RENAME opt_column name TO name | ALTER VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name | ALTER MATERIALIZED VIEW qualified_name RENAME opt_column name TO name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name RENAME opt_column name TO name | ALTER TABLE relation_expr RENAME CONSTRAINT name TO name | ALTER TABLE IF_P EXISTS relation_expr RENAME CONSTRAINT name TO name | ALTER FOREIGN TABLE relation_expr RENAME opt_column name TO name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr RENAME opt_column name TO name | ALTER RULE name ON qualified_name RENAME TO name | ALTER TRIGGER name ON qualified_name RENAME TO name | ALTER EVENT TRIGGER name RENAME TO name | ALTER ROLE roleid RENAME TO roleid | ALTER USER roleid RENAME TO roleid | ALTER TABLESPACE name RENAME TO name | ALTER STATISTICS any_name RENAME TO name | ALTER TEXT_P SEARCH PARSER any_name RENAME TO name | ALTER TEXT_P SEARCH DICTIONARY any_name RENAME TO name | ALTER TEXT_P SEARCH TEMPLATE any_name RENAME TO name | ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name | ALTER TYPE_P any_name RENAME TO name | ALTER TYPE_P any_name RENAME ATTRIBUTE name TO name opt_drop_behavior ; opt_column : COLUMN | ; opt_set_data : SET DATA_P | ; alterobjectdependsstmt : ALTER FUNCTION function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER PROCEDURE function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER ROUTINE function_with_argtypes opt_no DEPENDS ON EXTENSION name | ALTER TRIGGER name ON qualified_name opt_no DEPENDS ON EXTENSION name | ALTER MATERIALIZED VIEW qualified_name opt_no DEPENDS ON EXTENSION name | ALTER INDEX qualified_name opt_no DEPENDS ON EXTENSION name ; opt_no : NO | ; alterobjectschemastmt : ALTER AGGREGATE aggregate_with_argtypes SET SCHEMA name | ALTER COLLATION any_name SET SCHEMA name | ALTER CONVERSION_P any_name SET SCHEMA name | ALTER DOMAIN_P any_name SET SCHEMA name | ALTER EXTENSION name SET SCHEMA name | ALTER FUNCTION function_with_argtypes SET SCHEMA name | ALTER OPERATOR operator_with_argtypes SET SCHEMA name | ALTER OPERATOR CLASS any_name USING name SET SCHEMA name | ALTER OPERATOR FAMILY any_name USING name SET SCHEMA name | ALTER PROCEDURE function_with_argtypes SET SCHEMA name | ALTER ROUTINE function_with_argtypes SET SCHEMA name | ALTER TABLE relation_expr SET SCHEMA name | ALTER TABLE IF_P EXISTS relation_expr SET SCHEMA name | ALTER STATISTICS any_name SET SCHEMA name | ALTER TEXT_P SEARCH PARSER any_name SET SCHEMA name | ALTER TEXT_P SEARCH DICTIONARY any_name SET SCHEMA name | ALTER TEXT_P SEARCH TEMPLATE any_name SET SCHEMA name | ALTER TEXT_P SEARCH CONFIGURATION any_name SET SCHEMA name | ALTER SEQUENCE qualified_name SET SCHEMA name | ALTER SEQUENCE IF_P EXISTS qualified_name SET SCHEMA name | ALTER VIEW qualified_name SET SCHEMA name | ALTER VIEW IF_P EXISTS qualified_name SET SCHEMA name | ALTER MATERIALIZED VIEW qualified_name SET SCHEMA name | ALTER MATERIALIZED VIEW IF_P EXISTS qualified_name SET SCHEMA name | ALTER FOREIGN TABLE relation_expr SET SCHEMA name | ALTER FOREIGN TABLE IF_P EXISTS relation_expr SET SCHEMA name | ALTER TYPE_P any_name SET SCHEMA name ; alteroperatorstmt : ALTER OPERATOR operator_with_argtypes SET OPEN_PAREN operator_def_list CLOSE_PAREN ; operator_def_list : operator_def_elem (COMMA operator_def_elem)* ; operator_def_elem : collabel EQUAL NONE | collabel EQUAL operator_def_arg ; operator_def_arg : func_type | reserved_keyword | qual_all_op | numericonly | sconst ; altertypestmt : ALTER TYPE_P any_name SET OPEN_PAREN operator_def_list CLOSE_PAREN ; alterownerstmt : ALTER AGGREGATE aggregate_with_argtypes OWNER TO rolespec | ALTER COLLATION any_name OWNER TO rolespec | ALTER CONVERSION_P any_name OWNER TO rolespec | ALTER DATABASE name OWNER TO rolespec | ALTER DOMAIN_P any_name OWNER TO rolespec | ALTER FUNCTION function_with_argtypes OWNER TO rolespec | ALTER opt_procedural LANGUAGE name OWNER TO rolespec | ALTER LARGE_P OBJECT_P numericonly OWNER TO rolespec | ALTER OPERATOR operator_with_argtypes OWNER TO rolespec | ALTER OPERATOR CLASS any_name USING name OWNER TO rolespec | ALTER OPERATOR FAMILY any_name USING name OWNER TO rolespec | ALTER PROCEDURE function_with_argtypes OWNER TO rolespec | ALTER ROUTINE function_with_argtypes OWNER TO rolespec | ALTER SCHEMA name OWNER TO rolespec | ALTER TYPE_P any_name OWNER TO rolespec | ALTER TABLESPACE name OWNER TO rolespec | ALTER STATISTICS any_name OWNER TO rolespec | ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO rolespec | ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO rolespec | ALTER FOREIGN DATA_P WRAPPER name OWNER TO rolespec | ALTER SERVER name OWNER TO rolespec | ALTER EVENT TRIGGER name OWNER TO rolespec | ALTER PUBLICATION name OWNER TO rolespec | ALTER SUBSCRIPTION name OWNER TO rolespec ; createpublicationstmt : CREATE PUBLICATION name opt_publication_for_tables opt_definition ; opt_publication_for_tables : publication_for_tables | ; publication_for_tables : FOR TABLE relation_expr_list | FOR ALL TABLES ; alterpublicationstmt : ALTER PUBLICATION name SET definition | ALTER PUBLICATION name ADD_P TABLE relation_expr_list | ALTER PUBLICATION name SET TABLE relation_expr_list | ALTER PUBLICATION name DROP TABLE relation_expr_list ; createsubscriptionstmt : CREATE SUBSCRIPTION name CONNECTION sconst PUBLICATION publication_name_list opt_definition ; publication_name_list : publication_name_item (COMMA publication_name_item)* ; publication_name_item : collabel ; altersubscriptionstmt : ALTER SUBSCRIPTION name SET definition | ALTER SUBSCRIPTION name CONNECTION sconst | ALTER SUBSCRIPTION name REFRESH PUBLICATION opt_definition | ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list opt_definition | ALTER SUBSCRIPTION name ENABLE_P | ALTER SUBSCRIPTION name DISABLE_P ; dropsubscriptionstmt : DROP SUBSCRIPTION name opt_drop_behavior | DROP SUBSCRIPTION IF_P EXISTS name opt_drop_behavior ; rulestmt : CREATE opt_or_replace RULE name AS ON event TO qualified_name where_clause DO opt_instead ruleactionlist ; ruleactionlist : NOTHING | ruleactionstmt | OPEN_PAREN ruleactionmulti CLOSE_PAREN ; ruleactionmulti : ruleactionstmtOrEmpty (SEMI ruleactionstmtOrEmpty)* ; ruleactionstmt : selectstmt | insertstmt | updatestmt | deletestmt | notifystmt ; ruleactionstmtOrEmpty : ruleactionstmt | ; event : SELECT | UPDATE | DELETE_P | INSERT ; opt_instead : INSTEAD | ALSO | ; notifystmt : NOTIFY colid notify_payload ; notify_payload : COMMA sconst | ; listenstmt : LISTEN colid ; unlistenstmt : UNLISTEN colid | UNLISTEN STAR ; transactionstmt : ABORT_P opt_transaction opt_transaction_chain | BEGIN_P opt_transaction transaction_mode_list_or_empty | START TRANSACTION transaction_mode_list_or_empty | COMMIT opt_transaction opt_transaction_chain | END_P opt_transaction opt_transaction_chain | ROLLBACK opt_transaction opt_transaction_chain | SAVEPOINT colid | RELEASE SAVEPOINT colid | RELEASE colid | ROLLBACK opt_transaction TO SAVEPOINT colid | ROLLBACK opt_transaction TO colid | PREPARE TRANSACTION sconst | COMMIT PREPARED sconst | ROLLBACK PREPARED sconst ; opt_transaction : WORK | TRANSACTION | ; transaction_mode_item : ISOLATION LEVEL iso_level | READ ONLY | READ WRITE | DEFERRABLE | NOT DEFERRABLE ; transaction_mode_list : transaction_mode_item (COMMA? transaction_mode_item)* ; transaction_mode_list_or_empty : transaction_mode_list | ; opt_transaction_chain : AND NO? CHAIN | ; viewstmt : CREATE (OR REPLACE)? opttemp ( VIEW qualified_name opt_column_list opt_reloptions | RECURSIVE VIEW qualified_name OPEN_PAREN columnlist CLOSE_PAREN opt_reloptions ) AS selectstmt opt_check_option ; opt_check_option : WITH (CASCADED | LOCAL)? CHECK OPTION | ; loadstmt : LOAD file_name ; createdbstmt : CREATE DATABASE name opt_with createdb_opt_list ; createdb_opt_list : createdb_opt_items | ; createdb_opt_items : createdb_opt_item+ ; createdb_opt_item : createdb_opt_name opt_equal (signediconst | opt_boolean_or_string | DEFAULT) ; createdb_opt_name : identifier | CONNECTION LIMIT | ENCODING | LOCATION | OWNER | TABLESPACE | TEMPLATE ; opt_equal : EQUAL | ; alterdatabasestmt : ALTER DATABASE name (WITH createdb_opt_list | createdb_opt_list | SET TABLESPACE name) ; alterdatabasesetstmt : ALTER DATABASE name setresetclause ; dropdbstmt : DROP DATABASE (IF_P EXISTS)? name (opt_with OPEN_PAREN drop_option_list CLOSE_PAREN)? ; drop_option_list : drop_option (COMMA drop_option)* ; drop_option : FORCE ; altercollationstmt : ALTER COLLATION any_name REFRESH VERSION_P ; altersystemstmt : ALTER SYSTEM_P (SET | RESET) generic_set ; createdomainstmt : CREATE DOMAIN_P any_name opt_as typename colquallist ; alterdomainstmt : ALTER DOMAIN_P any_name (alter_column_default | DROP NOT NULL_P | SET NOT NULL_P | ADD_P tableconstraint | DROP CONSTRAINT (IF_P EXISTS)? name opt_drop_behavior | VALIDATE CONSTRAINT name) ; opt_as : AS | ; altertsdictionarystmt : ALTER TEXT_P SEARCH DICTIONARY any_name definition ; altertsconfigurationstmt : ALTER TEXT_P SEARCH CONFIGURATION any_name ADD_P MAPPING FOR name_list any_with any_name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list any_with any_name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING REPLACE any_name any_with any_name | ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list REPLACE any_name any_with any_name | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING FOR name_list | ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING IF_P EXISTS FOR name_list ; any_with : WITH //TODO // | WITH_LA ; createconversionstmt : CREATE opt_default CONVERSION_P any_name FOR sconst TO sconst FROM any_name ; clusterstmt : CLUSTER opt_verbose qualified_name cluster_index_specification | CLUSTER opt_verbose | CLUSTER opt_verbose name ON qualified_name ; cluster_index_specification : USING name | ; vacuumstmt : VACUUM opt_full opt_freeze opt_verbose opt_analyze opt_vacuum_relation_list | VACUUM OPEN_PAREN vac_analyze_option_list CLOSE_PAREN opt_vacuum_relation_list ; analyzestmt : analyze_keyword opt_verbose opt_vacuum_relation_list | analyze_keyword OPEN_PAREN vac_analyze_option_list CLOSE_PAREN opt_vacuum_relation_list ; vac_analyze_option_list : vac_analyze_option_elem (COMMA vac_analyze_option_elem)* ; analyze_keyword : ANALYZE | ANALYSE ; vac_analyze_option_elem : vac_analyze_option_name vac_analyze_option_arg ; vac_analyze_option_name : nonreservedword | analyze_keyword ; vac_analyze_option_arg : opt_boolean_or_string | numericonly | ; opt_analyze : analyze_keyword | ; opt_verbose : VERBOSE | ; opt_full : FULL | ; opt_freeze : FREEZE | ; opt_name_list : OPEN_PAREN name_list CLOSE_PAREN | ; vacuum_relation : qualified_name opt_name_list ; vacuum_relation_list : vacuum_relation (COMMA vacuum_relation)* ; opt_vacuum_relation_list : vacuum_relation_list | ; explainstmt : EXPLAIN explainablestmt | EXPLAIN analyze_keyword opt_verbose explainablestmt | EXPLAIN VERBOSE explainablestmt | EXPLAIN OPEN_PAREN explain_option_list CLOSE_PAREN explainablestmt ; explainablestmt : selectstmt | insertstmt | updatestmt | deletestmt | declarecursorstmt | createasstmt | creatematviewstmt | refreshmatviewstmt | executestmt ; explain_option_list : explain_option_elem (COMMA explain_option_elem)* ; explain_option_elem : explain_option_name explain_option_arg ; explain_option_name : nonreservedword | analyze_keyword ; explain_option_arg : opt_boolean_or_string | numericonly | ; preparestmt : PREPARE name prep_type_clause AS preparablestmt ; prep_type_clause : OPEN_PAREN type_list CLOSE_PAREN | ; preparablestmt : selectstmt | insertstmt | updatestmt | deletestmt ; executestmt : EXECUTE name execute_param_clause | CREATE opttemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data | CREATE opttemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data ; execute_param_clause : OPEN_PAREN expr_list CLOSE_PAREN | ; deallocatestmt : DEALLOCATE name | DEALLOCATE PREPARE name | DEALLOCATE ALL | DEALLOCATE PREPARE ALL ; insertstmt : opt_with_clause INSERT INTO insert_target insert_rest opt_on_conflict returning_clause ; insert_target : qualified_name (AS colid)? ; insert_rest : selectstmt | OVERRIDING override_kind VALUE_P selectstmt | OPEN_PAREN insert_column_list CLOSE_PAREN (OVERRIDING override_kind VALUE_P)? selectstmt | DEFAULT VALUES ; override_kind : USER | SYSTEM_P ; insert_column_list : insert_column_item (COMMA insert_column_item)* ; insert_column_item : colid opt_indirection ; opt_on_conflict : ON CONFLICT opt_conf_expr DO (UPDATE SET set_clause_list where_clause | NOTHING) | ; opt_conf_expr : OPEN_PAREN index_params CLOSE_PAREN where_clause | ON CONSTRAINT name | ; returning_clause : RETURNING target_list | ; // https://www.postgresql.org/docs/current/sql-merge.html mergestmt : MERGE INTO? qualified_name alias_clause? USING (select_with_parens|qualified_name) alias_clause? ON a_expr (merge_insert_clause merge_update_clause? | merge_update_clause merge_insert_clause?) merge_delete_clause? ; merge_insert_clause : WHEN NOT MATCHED (AND a_expr)? THEN? INSERT (OPEN_PAREN insert_column_list CLOSE_PAREN)? values_clause ; merge_update_clause : WHEN MATCHED (AND a_expr)? THEN? UPDATE SET set_clause_list ; merge_delete_clause : WHEN MATCHED THEN? DELETE_P ; deletestmt : opt_with_clause DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause ; using_clause : USING from_list | ; lockstmt : LOCK_P opt_table relation_expr_list opt_lock opt_nowait ; opt_lock : IN_P lock_type MODE | ; lock_type : ACCESS (SHARE | EXCLUSIVE) | ROW (SHARE | EXCLUSIVE) | SHARE (UPDATE EXCLUSIVE | ROW EXCLUSIVE)? | EXCLUSIVE ; opt_nowait : NOWAIT | ; opt_nowait_or_skip : NOWAIT | SKIP_P LOCKED | ; updatestmt : opt_with_clause UPDATE relation_expr_opt_alias SET set_clause_list from_clause where_or_current_clause returning_clause ; set_clause_list : set_clause (COMMA set_clause)* ; set_clause : set_target EQUAL a_expr | OPEN_PAREN set_target_list CLOSE_PAREN EQUAL a_expr ; set_target : colid opt_indirection ; set_target_list : set_target (COMMA set_target)* ; declarecursorstmt : DECLARE cursor_name cursor_options CURSOR opt_hold FOR selectstmt ; cursor_name : name ; cursor_options : (NO SCROLL | SCROLL | BINARY | INSENSITIVE)* ; opt_hold : | WITH HOLD | WITHOUT HOLD ; /* TODO: why select_with_parens alternative is needed at all? i guess it because original byson grammar can choose selectstmt(2)->select_with_parens on only OPEN_PARENT/SELECT kewords at the begining of statement; (select * from tab); parse can go through selectstmt( )->select_no_parens(1)->select_clause(2)->select_with_parens(1)->select_no_parens(1)->select_clause(1)->simple_select instead of selectstmt(1)->select_no_parens(1)->select_clause(2)->select_with_parens(1)->select_no_parens(1)->select_clause(1)->simple_select all standard tests passed on both variants */ selectstmt : select_no_parens | select_with_parens ; select_with_parens : OPEN_PAREN select_no_parens CLOSE_PAREN | OPEN_PAREN select_with_parens CLOSE_PAREN ; select_no_parens : select_clause opt_sort_clause (for_locking_clause opt_select_limit | select_limit opt_for_locking_clause)? | with_clause select_clause opt_sort_clause (for_locking_clause opt_select_limit | select_limit opt_for_locking_clause)? ; select_clause : simple_select_intersect ((UNION | EXCEPT) all_or_distinct simple_select_intersect)* ; simple_select_intersect : simple_select_pramary (INTERSECT all_or_distinct simple_select_pramary)* ; simple_select_pramary : ( SELECT (opt_all_clause into_clause opt_target_list | distinct_clause target_list) into_clause from_clause where_clause group_clause having_clause window_clause ) | values_clause | TABLE relation_expr | select_with_parens ; with_clause : WITH RECURSIVE? cte_list ; cte_list : common_table_expr (COMMA common_table_expr)* ; common_table_expr : name opt_name_list AS opt_materialized OPEN_PAREN preparablestmt CLOSE_PAREN ; opt_materialized : MATERIALIZED | NOT MATERIALIZED | ; opt_with_clause : with_clause | ; into_clause : INTO (opt_strict opttempTableName | into_target) | ; opt_strict : | STRICT_P ; opttempTableName : (LOCAL|GLOBAL)? (TEMPORARY | TEMP) opt_table qualified_name | UNLOGGED opt_table qualified_name | TABLE qualified_name | qualified_name ; opt_table : TABLE | ; all_or_distinct : ALL | DISTINCT | ; distinct_clause : DISTINCT (ON OPEN_PAREN expr_list CLOSE_PAREN)? ; opt_all_clause : ALL | ; opt_sort_clause : sort_clause | ; sort_clause : ORDER BY sortby_list ; sortby_list : sortby (COMMA sortby)* ; sortby : a_expr (USING qual_all_op | opt_asc_desc) opt_nulls_order ; select_limit : limit_clause offset_clause? | offset_clause limit_clause? ; opt_select_limit : select_limit | ; limit_clause : LIMIT select_limit_value (COMMA select_offset_value)? | FETCH first_or_next (select_fetch_first_value row_or_rows (ONLY | WITH TIES) | row_or_rows (ONLY | WITH TIES)) ; offset_clause : OFFSET (select_offset_value | select_fetch_first_value row_or_rows) ; select_limit_value : a_expr | ALL ; select_offset_value : a_expr ; select_fetch_first_value : c_expr | PLUS i_or_f_const | MINUS i_or_f_const ; i_or_f_const : iconst | fconst ; row_or_rows : ROW | ROWS ; first_or_next : FIRST_P | NEXT ; group_clause : GROUP_P BY group_by_list | ; group_by_list : group_by_item (COMMA group_by_item)* ; group_by_item : empty_grouping_set | cube_clause | rollup_clause | grouping_sets_clause | a_expr ; empty_grouping_set : OPEN_PAREN CLOSE_PAREN ; rollup_clause : ROLLUP OPEN_PAREN expr_list CLOSE_PAREN ; cube_clause : CUBE OPEN_PAREN expr_list CLOSE_PAREN ; grouping_sets_clause : GROUPING SETS OPEN_PAREN group_by_list CLOSE_PAREN ; having_clause : HAVING a_expr | ; for_locking_clause : for_locking_items | FOR READ ONLY ; opt_for_locking_clause : for_locking_clause | ; for_locking_items : for_locking_item+ ; for_locking_item : for_locking_strength locked_rels_list opt_nowait_or_skip ; for_locking_strength : FOR ((NO KEY)? UPDATE | KEY? SHARE) ; locked_rels_list : OF qualified_name_list | ; values_clause : VALUES OPEN_PAREN expr_list CLOSE_PAREN (COMMA OPEN_PAREN expr_list CLOSE_PAREN)* ; from_clause : FROM from_list | ; from_list : non_ansi_join | table_ref (COMMA table_ref)* ; non_ansi_join : table_ref (COMMA table_ref)+ ; table_ref : (relation_expr opt_alias_clause tablesample_clause? | func_table func_alias_clause | xmltable opt_alias_clause | select_with_parens opt_alias_clause | LATERAL_P ( xmltable opt_alias_clause | func_table func_alias_clause | select_with_parens opt_alias_clause ) | OPEN_PAREN table_ref ( CROSS JOIN table_ref | NATURAL join_type? JOIN table_ref | join_type? JOIN table_ref join_qual )? CLOSE_PAREN opt_alias_clause ) (CROSS JOIN table_ref | NATURAL join_type? JOIN table_ref | join_type? JOIN table_ref join_qual)* ; alias_clause : AS? colid (OPEN_PAREN name_list CLOSE_PAREN)? ; opt_alias_clause : table_alias_clause | ; table_alias_clause : AS? table_alias (OPEN_PAREN name_list CLOSE_PAREN)? ; func_alias_clause : alias_clause | (AS colid? | colid) OPEN_PAREN tablefuncelementlist CLOSE_PAREN | ; join_type : (FULL | LEFT | RIGHT | INNER_P) OUTER_P? ; join_qual : USING OPEN_PAREN name_list CLOSE_PAREN | ON a_expr ; relation_expr : qualified_name STAR? | ONLY (qualified_name | OPEN_PAREN qualified_name CLOSE_PAREN) ; relation_expr_list : relation_expr (COMMA relation_expr)* ; relation_expr_opt_alias : relation_expr (AS? colid)? ; tablesample_clause : TABLESAMPLE func_name OPEN_PAREN expr_list CLOSE_PAREN opt_repeatable_clause ; opt_repeatable_clause : REPEATABLE OPEN_PAREN a_expr CLOSE_PAREN | ; func_table : func_expr_windowless opt_ordinality | ROWS FROM OPEN_PAREN rowsfrom_list CLOSE_PAREN opt_ordinality ; rowsfrom_item : func_expr_windowless opt_col_def_list ; rowsfrom_list : rowsfrom_item (COMMA rowsfrom_item)* ; opt_col_def_list : AS OPEN_PAREN tablefuncelementlist CLOSE_PAREN | ; //TODO WITH_LA was used opt_ordinality : WITH ORDINALITY | ; where_clause : WHERE a_expr | ; where_or_current_clause : WHERE (CURRENT_P OF cursor_name | a_expr) | ; opttablefuncelementlist : tablefuncelementlist | ; tablefuncelementlist : tablefuncelement (COMMA tablefuncelement)* ; tablefuncelement : colid typename opt_collate_clause ; xmltable : XMLTABLE OPEN_PAREN (c_expr xmlexists_argument COLUMNS xmltable_column_list | XMLNAMESPACES OPEN_PAREN xml_namespace_list CLOSE_PAREN COMMA c_expr xmlexists_argument COLUMNS xmltable_column_list) CLOSE_PAREN ; xmltable_column_list : xmltable_column_el (COMMA xmltable_column_el)* ; xmltable_column_el : colid (typename xmltable_column_option_list? | FOR ORDINALITY) ; xmltable_column_option_list : xmltable_column_option_el+ ; xmltable_column_option_el : DEFAULT a_expr | identifier a_expr | NOT NULL_P | NULL_P ; xml_namespace_list : xml_namespace_el (COMMA xml_namespace_el)* ; xml_namespace_el : b_expr AS collabel | DEFAULT b_expr ; typename : SETOF? simpletypename (opt_array_bounds | ARRAY (OPEN_BRACKET iconst CLOSE_BRACKET)?) | qualified_name PERCENT (ROWTYPE | TYPE_P) ; opt_array_bounds : (OPEN_BRACKET iconst? CLOSE_BRACKET)* ; simpletypename : generictype | numeric | bit | character | constdatetime | constinterval (opt_interval | OPEN_PAREN iconst CLOSE_PAREN) ; consttypename : numeric | constbit | constcharacter | constdatetime ; generictype : (builtin_function_name | type_function_name | LEFT | RIGHT) attrs? opt_type_modifiers ; opt_type_modifiers : OPEN_PAREN expr_list CLOSE_PAREN | ; numeric : INT_P | INTEGER | SMALLINT | BIGINT | REAL | FLOAT_P opt_float | DOUBLE_P PRECISION | DECIMAL_P opt_type_modifiers | DEC opt_type_modifiers | NUMERIC opt_type_modifiers | BOOLEAN_P ; opt_float : OPEN_PAREN iconst CLOSE_PAREN | ; //todo: merge alts bit : bitwithlength | bitwithoutlength ; constbit : bitwithlength | bitwithoutlength ; bitwithlength : BIT opt_varying OPEN_PAREN expr_list CLOSE_PAREN ; bitwithoutlength : BIT opt_varying ; character : character_c (OPEN_PAREN iconst CLOSE_PAREN)? ; constcharacter : character_c (OPEN_PAREN iconst CLOSE_PAREN)? ; character_c : (CHARACTER | CHAR_P | NCHAR) opt_varying | VARCHAR | NATIONAL (CHARACTER | CHAR_P) opt_varying ; opt_varying : VARYING | ; constdatetime : (TIMESTAMP | TIME) (OPEN_PAREN iconst CLOSE_PAREN)? opt_timezone ; constinterval : INTERVAL ; //TODO with_la was used opt_timezone : WITH TIME ZONE | WITHOUT TIME ZONE | ; opt_interval : YEAR_P | MONTH_P | DAY_P | HOUR_P | MINUTE_P | interval_second | YEAR_P TO MONTH_P | DAY_P TO (HOUR_P | MINUTE_P | interval_second) | HOUR_P TO (MINUTE_P | interval_second) | MINUTE_P TO interval_second | ; interval_second : SECOND_P (OPEN_PAREN iconst CLOSE_PAREN)? ; opt_escape : ESCAPE a_expr | ; //precendence accroding to Table 4.2. Operator Precedence (highest to lowest) //https://www.postgresql.org/docs/12/sql-syntax-lexical.html#SQL-PRECEDENCE /* original version of a_expr, for info a_expr: c_expr //:: left PostgreSQL-style typecast | a_expr TYPECAST typename -- 1 | a_expr COLLATE any_name -- 2 | a_expr AT TIME ZONE a_expr-- 3 //right unary plus, unary minus | (PLUS| MINUS) a_expr -- 4 //left exponentiation | a_expr CARET a_expr -- 5 //left multiplication, division, modulo | a_expr (STAR | SLASH | PERCENT) a_expr -- 6 //left addition, subtraction | a_expr (PLUS | MINUS) a_expr -- 7 //left all other native and user-defined operators | a_expr qual_op a_expr -- 8 | qual_op a_expr -- 9 //range containment, set membership, string matching BETWEEN IN LIKE ILIKE SIMILAR | a_expr NOT? (LIKE|ILIKE|SIMILAR TO|(BETWEEN SYMMETRIC?)) a_expr opt_escape -- 10 //< > = <= >= <> comparison operators | a_expr (LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) a_expr -- 11 //IS ISNULL NOTNULL IS TRUE, IS FALSE, IS NULL, IS DISTINCT FROM, etc | a_expr IS NOT? ( NULL_P |TRUE_P |FALSE_P |UNKNOWN |DISTINCT FROM a_expr |OF OPEN_PAREN type_list CLOSE_PAREN |DOCUMENT_P |unicode_normal_form? NORMALIZED ) -- 12 | a_expr (ISNULL|NOTNULL) -- 13 | row OVERLAPS row -- 14 //NOT right logical negation | NOT a_expr -- 15 //AND left logical conjunction | a_expr AND a_expr -- 16 //OR left logical disjunction | a_expr OR a_expr -- 17 | a_expr (LESS_LESS|GREATER_GREATER) a_expr -- 18 | a_expr qual_op -- 19 | a_expr NOT? IN_P in_expr -- 20 | a_expr subquery_Op sub_type (select_with_parens|OPEN_PAREN a_expr CLOSE_PAREN) -- 21 | UNIQUE select_with_parens -- 22 | DEFAULT -- 23 ; */ a_expr : a_expr_qual ; /*23*/ /*moved to c_expr*/ /*22*/ /*moved to c_expr*/ /*19*/ a_expr_qual : a_expr_lessless qual_op? ; /*18*/ a_expr_lessless : a_expr_or ((LESS_LESS | GREATER_GREATER) a_expr_or)* ; /*17*/ a_expr_or : a_expr_and (OR a_expr_and)* ; /*16*/ a_expr_and : a_expr_between (AND a_expr_between)* ; /*21*/ a_expr_between : a_expr_in (NOT? BETWEEN SYMMETRIC? a_expr_in AND a_expr_in)? ; /*20*/ a_expr_in : a_expr_unary_not (NOT? IN_P in_expr)? ; /*15*/ a_expr_unary_not : NOT? a_expr_isnull ; /*14*/ /*moved to c_expr*/ /*13*/ a_expr_isnull : a_expr_is_not (ISNULL | NOTNULL)? ; /*12*/ a_expr_is_not : a_expr_compare (IS NOT? (NULL_P | TRUE_P | FALSE_P | UNKNOWN | DISTINCT FROM a_expr | OF OPEN_PAREN type_list CLOSE_PAREN | DOCUMENT_P | unicode_normal_form? NORMALIZED))? ; /*11*/ a_expr_compare : a_expr_like ((LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) a_expr_like |subquery_Op sub_type (select_with_parens | OPEN_PAREN a_expr CLOSE_PAREN) /*21*/ )? ; /*10*/ a_expr_like : a_expr_qual_op (NOT? (LIKE | ILIKE | SIMILAR TO) a_expr_qual_op opt_escape)? ; /* 8*/ a_expr_qual_op : a_expr_unary_qualop (qual_op a_expr_unary_qualop)* ; /* 9*/ a_expr_unary_qualop : qual_op? a_expr_add ; /* 7*/ a_expr_add : a_expr_mul ((MINUS | PLUS) a_expr_mul)* ; /* 6*/ a_expr_mul : a_expr_caret ((STAR | SLASH | PERCENT) a_expr_caret)* ; /* 5*/ a_expr_caret : a_expr_unary_sign (CARET a_expr)? ; /* 4*/ a_expr_unary_sign : (MINUS | PLUS)? a_expr_at_time_zone /* */ ; /* 3*/ a_expr_at_time_zone : a_expr_collate (AT TIME ZONE a_expr)? ; /* 2*/ a_expr_collate : a_expr_typecast (COLLATE any_name)? ; /* 1*/ a_expr_typecast : c_expr (TYPECAST typename)* ; b_expr : c_expr | b_expr TYPECAST typename //right unary plus, unary minus | (PLUS | MINUS) b_expr //^ left exponentiation | b_expr CARET b_expr //* / % left multiplication, division, modulo | b_expr (STAR | SLASH | PERCENT) b_expr //+ - left addition, subtraction | b_expr (PLUS | MINUS) b_expr //(any other operator) left all other native and user-defined operators | b_expr qual_op b_expr //< > = <= >= <> comparison operators | b_expr (LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS) b_expr | qual_op b_expr | b_expr qual_op //S ISNULL NOTNULL IS TRUE, IS FALSE, IS NULL, IS DISTINCT FROM, etc | b_expr IS NOT? (DISTINCT FROM b_expr | OF OPEN_PAREN type_list CLOSE_PAREN | DOCUMENT_P) ; c_expr : EXISTS select_with_parens # c_expr_exists | ARRAY (select_with_parens | array_expr) # c_expr_expr | PARAM opt_indirection # c_expr_expr | GROUPING OPEN_PAREN expr_list CLOSE_PAREN # c_expr_expr | /*22*/ UNIQUE select_with_parens # c_expr_expr | columnref # c_expr_expr | aexprconst # c_expr_expr | plsqlvariablename # c_expr_expr | OPEN_PAREN a_expr_in_parens = a_expr CLOSE_PAREN opt_indirection # c_expr_expr | case_expr # c_expr_case | func_expr # c_expr_expr | select_with_parens indirection? # c_expr_expr | explicit_row # c_expr_expr | implicit_row # c_expr_expr | row OVERLAPS row /* 14*/ # c_expr_expr ; plsqlvariablename : PLSQLVARIABLENAME ; func_application : func_name OPEN_PAREN (func_arg_list (COMMA VARIADIC func_arg_expr)? opt_sort_clause | VARIADIC func_arg_expr opt_sort_clause | (ALL | DISTINCT) func_arg_list opt_sort_clause | STAR |) CLOSE_PAREN ; func_expr : func_application within_group_clause filter_clause over_clause | func_expr_common_subexpr ; func_expr_windowless : func_application | func_expr_common_subexpr ; func_expr_common_subexpr : COLLATION FOR OPEN_PAREN a_expr CLOSE_PAREN | CURRENT_DATE | CURRENT_TIME (OPEN_PAREN iconst CLOSE_PAREN)? | CURRENT_TIMESTAMP (OPEN_PAREN iconst CLOSE_PAREN)? | LOCALTIME (OPEN_PAREN iconst CLOSE_PAREN)? | LOCALTIMESTAMP (OPEN_PAREN iconst CLOSE_PAREN)? | CURRENT_ROLE | CURRENT_USER | SESSION_USER | USER | CURRENT_CATALOG | CURRENT_SCHEMA | CAST OPEN_PAREN a_expr AS typename CLOSE_PAREN | EXTRACT OPEN_PAREN extract_list CLOSE_PAREN | NORMALIZE OPEN_PAREN a_expr (COMMA unicode_normal_form)? CLOSE_PAREN | OVERLAY OPEN_PAREN overlay_list CLOSE_PAREN | POSITION OPEN_PAREN position_list CLOSE_PAREN | SUBSTRING OPEN_PAREN substr_list CLOSE_PAREN | TREAT OPEN_PAREN a_expr AS typename CLOSE_PAREN | TRIM OPEN_PAREN (BOTH | LEADING | TRAILING)? trim_list CLOSE_PAREN | NULLIF OPEN_PAREN a_expr COMMA a_expr CLOSE_PAREN | COALESCE OPEN_PAREN expr_list CLOSE_PAREN | GREATEST OPEN_PAREN expr_list CLOSE_PAREN | LEAST OPEN_PAREN expr_list CLOSE_PAREN | XMLCONCAT OPEN_PAREN expr_list CLOSE_PAREN | XMLELEMENT OPEN_PAREN NAME_P collabel (COMMA (xml_attributes | expr_list))? CLOSE_PAREN | XMLEXISTS OPEN_PAREN c_expr xmlexists_argument CLOSE_PAREN | XMLFOREST OPEN_PAREN xml_attribute_list CLOSE_PAREN | XMLPARSE OPEN_PAREN document_or_content a_expr xml_whitespace_option CLOSE_PAREN | XMLPI OPEN_PAREN NAME_P collabel (COMMA a_expr)? CLOSE_PAREN | XMLROOT OPEN_PAREN XML_P a_expr COMMA xml_root_version opt_xml_root_standalone CLOSE_PAREN | XMLSERIALIZE OPEN_PAREN document_or_content a_expr AS simpletypename CLOSE_PAREN ; xml_root_version : VERSION_P a_expr | VERSION_P NO VALUE_P ; opt_xml_root_standalone : COMMA STANDALONE_P YES_P | COMMA STANDALONE_P NO | COMMA STANDALONE_P NO VALUE_P | ; xml_attributes : XMLATTRIBUTES OPEN_PAREN xml_attribute_list CLOSE_PAREN ; xml_attribute_list : xml_attribute_el (COMMA xml_attribute_el)* ; xml_attribute_el : a_expr (AS collabel)? ; document_or_content : DOCUMENT_P | CONTENT_P ; xml_whitespace_option : PRESERVE WHITESPACE_P | STRIP_P WHITESPACE_P | ; xmlexists_argument : PASSING c_expr | PASSING c_expr xml_passing_mech | PASSING xml_passing_mech c_expr | PASSING xml_passing_mech c_expr xml_passing_mech ; xml_passing_mech : BY (REF | VALUE_P) ; within_group_clause : WITHIN GROUP_P OPEN_PAREN sort_clause CLOSE_PAREN | ; filter_clause : FILTER OPEN_PAREN WHERE a_expr CLOSE_PAREN | ; window_clause : WINDOW window_definition_list | ; window_definition_list : window_definition (COMMA window_definition)* ; window_definition : colid AS window_specification ; over_clause : OVER (window_specification | colid) | ; window_specification : OPEN_PAREN opt_existing_window_name opt_partition_clause opt_sort_clause opt_frame_clause CLOSE_PAREN ; opt_existing_window_name : colid | ; opt_partition_clause : PARTITION BY expr_list | ; opt_frame_clause : RANGE frame_extent opt_window_exclusion_clause | ROWS frame_extent opt_window_exclusion_clause | GROUPS frame_extent opt_window_exclusion_clause | ; frame_extent : frame_bound | BETWEEN frame_bound AND frame_bound ; frame_bound : UNBOUNDED (PRECEDING | FOLLOWING) | CURRENT_P ROW | a_expr (PRECEDING | FOLLOWING) ; opt_window_exclusion_clause : EXCLUDE (CURRENT_P ROW | GROUP_P | TIES | NO OTHERS) | ; row : ROW OPEN_PAREN expr_list? CLOSE_PAREN | OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN ; explicit_row : ROW OPEN_PAREN expr_list? CLOSE_PAREN ; /* TODO: for some reason v1 implicit_row: OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN; works better than v2 implicit_row: OPEN_PAREN expr_list CLOSE_PAREN; while looks like they are almost the same, except v2 requieres at least 2 items in list while v1 allows single item in list */ implicit_row : OPEN_PAREN expr_list COMMA a_expr CLOSE_PAREN ; sub_type : ANY | SOME | ALL ; all_op : Operator | mathop ; mathop : PLUS | MINUS | STAR | SLASH | PERCENT | CARET | LT | GT | EQUAL | LESS_EQUALS | GREATER_EQUALS | NOT_EQUALS ; qual_op : Operator | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN ; qual_all_op : all_op | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN ; subquery_Op : all_op | OPERATOR OPEN_PAREN any_operator CLOSE_PAREN | LIKE | NOT LIKE | ILIKE | NOT ILIKE ; expr_list : a_expr (COMMA a_expr)* ; func_arg_list : func_arg_expr (COMMA func_arg_expr)* ; func_arg_expr : a_expr | param_name (COLON_EQUALS | EQUALS_GREATER) a_expr ; type_list : typename (COMMA typename)* ; array_expr : OPEN_BRACKET (expr_list | array_expr_list)? CLOSE_BRACKET ; array_expr_list : array_expr (COMMA array_expr)* ; extract_list : extract_arg FROM a_expr | ; extract_arg : identifier | YEAR_P | MONTH_P | DAY_P | HOUR_P | MINUTE_P | SECOND_P | sconst ; unicode_normal_form : NFC | NFD | NFKC | NFKD ; overlay_list : a_expr PLACING a_expr FROM a_expr (FOR a_expr)? ; position_list : b_expr IN_P b_expr | ; substr_list : a_expr FROM a_expr FOR a_expr | a_expr FOR a_expr FROM a_expr | a_expr FROM a_expr | a_expr FOR a_expr | a_expr SIMILAR a_expr ESCAPE a_expr | expr_list ; trim_list : a_expr FROM expr_list | FROM expr_list | expr_list ; in_expr : select_with_parens # in_expr_select | OPEN_PAREN expr_list CLOSE_PAREN # in_expr_list ; case_expr : CASE case_arg when_clause_list case_default END_P ; when_clause_list : when_clause+ ; when_clause : WHEN a_expr THEN a_expr ; case_default : ELSE a_expr | ; case_arg : a_expr | ; columnref : colid indirection? ; indirection_el : DOT (attr_name | STAR) | OPEN_BRACKET (a_expr | opt_slice_bound COLON opt_slice_bound) CLOSE_BRACKET ; opt_slice_bound : a_expr | ; indirection : indirection_el+ ; opt_indirection : indirection_el* ; opt_target_list : target_list | ; target_list : target_el (COMMA target_el)* ; target_el : a_expr (AS collabel | identifier |) # target_label | STAR # target_star ; qualified_name_list : qualified_name (COMMA qualified_name)* ; qualified_name : colid indirection? ; name_list : name (COMMA name)* ; name : colid ; attr_name : collabel ; file_name : sconst ; func_name : builtin_function_name | type_function_name | colid indirection | LEFT | RIGHT ; aexprconst : iconst | fconst | sconst | bconst | xconst | func_name (sconst | OPEN_PAREN func_arg_list opt_sort_clause CLOSE_PAREN sconst) | consttypename sconst | constinterval (sconst opt_interval | OPEN_PAREN iconst CLOSE_PAREN sconst) | TRUE_P | FALSE_P | NULL_P ; xconst : HexadecimalStringConstant ; bconst : BinaryStringConstant ; fconst : Numeric ; iconst : Integral ; sconst : anysconst opt_uescape ; anysconst : StringConstant | UnicodeEscapeStringConstant | BeginDollarStringConstant DollarText* EndDollarStringConstant | EscapeStringConstant ; opt_uescape : UESCAPE anysconst | ; signediconst : iconst | PLUS iconst | MINUS iconst ; roleid : rolespec ; rolespec : nonreservedword | CURRENT_USER | SESSION_USER ; role_list : rolespec (COMMA rolespec)* ; colid : identifier | unreserved_keyword | col_name_keyword | plsql_unreserved_keyword | LEFT | RIGHT ; table_alias : identifier | unreserved_keyword | col_name_keyword | plsql_unreserved_keyword ; type_function_name : identifier | unreserved_keyword | plsql_unreserved_keyword | type_func_name_keyword ; nonreservedword : identifier | unreserved_keyword | col_name_keyword | type_func_name_keyword ; collabel : identifier | plsql_unreserved_keyword | unreserved_keyword | col_name_keyword | type_func_name_keyword | reserved_keyword ; identifier : Identifier opt_uescape | QuotedIdentifier | UnicodeQuotedIdentifier | plsqlvariablename | plsqlidentifier | plsql_unreserved_keyword ; plsqlidentifier : PLSQLIDENTIFIER ; unreserved_keyword : ABORT_P | ABSOLUTE_P | ACCESS | ACTION | ADD_P | ADMIN | AFTER | AGGREGATE | ALSO | ALTER | ALWAYS | ASSERTION | ASSIGNMENT | AT | ATTACH | ATTRIBUTE | BACKWARD | BEFORE | BEGIN_P | BY | CACHE | CALL | CALLED | CASCADE | CASCADED | CATALOG | CHAIN | CHARACTERISTICS | CHECKPOINT | CLASS | CLOSE | CLUSTER | COLUMNS | COMMENT | COMMENTS | COMMIT | COMMITTED | CONFIGURATION | CONFLICT | CONNECTION | CONSTRAINTS | CONTENT_P | CONTINUE_P | CONVERSION_P | COPY | COST | CSV | CUBE | CURRENT_P | CURSOR | CYCLE | DATA_P | DATABASE | DAY_P | DEALLOCATE | DECLARE | DEFAULTS | DEFERRED | DEFINER | DELETE_P | DELIMITER | DELIMITERS | DEPENDS | DETACH | DICTIONARY | DISABLE_P | DISCARD | DOCUMENT_P | DOMAIN_P | DOUBLE_P | DROP | EACH | ENABLE_P | ENCODING | ENCRYPTED | ENUM_P | ESCAPE | EVENT | EXCLUDE | EXCLUDING | EXCLUSIVE | EXECUTE | EXPLAIN | EXPRESSION | EXTENSION | EXTERNAL | FAMILY | FILTER | FIRST_P | FOLLOWING | FORCE | FORWARD | FUNCTION | FUNCTIONS | GENERATED | GLOBAL | GRANTED | GROUPS | HANDLER | HEADER_P | HOLD | HOUR_P | IDENTITY_P | IF_P | IMMEDIATE | IMMUTABLE | IMPLICIT_P | IMPORT_P | INCLUDE | INCLUDING | INCREMENT | INDEX | INDEXES | INHERIT | INHERITS | INLINE_P | INPUT_P | INSENSITIVE | INSERT | INSTEAD | INVOKER | ISOLATION | KEY | LABEL | LANGUAGE | LARGE_P | LAST_P | LEAKPROOF | LEVEL | LISTEN | LOAD | LOCAL | LOCATION | LOCK_P | LOCKED | LOGGED | MAPPING | MATCH | MATERIALIZED | MAXVALUE | METHOD | MINUTE_P | MINVALUE | MODE | MONTH_P | MOVE | NAME_P | NAMES | NEW | NEXT | NFC | NFD | NFKC | NFKD | NO | NORMALIZED | NOTHING | NOTIFY | NOWAIT | NULLS_P | OBJECT_P | OF | OFF | OIDS | OLD | OPERATOR | OPTION | OPTIONS | ORDINALITY | OTHERS | OVER | OVERRIDING | OWNED | OWNER | PARALLEL | PARSER | PARTIAL | PARTITION | PASSING | PASSWORD | PLANS | POLICY | PRECEDING | PREPARE | PREPARED | PRESERVE | PRIOR | PRIVILEGES | PROCEDURAL | PROCEDURE | PROCEDURES | PROGRAM | PUBLICATION | QUOTE | RANGE | READ | REASSIGN | RECHECK | RECURSIVE | REF | REFERENCING | REFRESH | REINDEX | RELATIVE_P | RELEASE | RENAME | REPEATABLE | REPLICA | RESET | RESTART | RESTRICT | RETURNS | REVOKE | ROLE | ROLLBACK | ROLLUP | ROUTINE | ROUTINES | ROWS | RULE | SAVEPOINT | SCHEMA | SCHEMAS | SCROLL | SEARCH | SECOND_P | SECURITY | SEQUENCE | SEQUENCES | SERIALIZABLE | SERVER | SESSION | SET | SETS | SHARE | SHOW | SIMPLE | SKIP_P | SNAPSHOT | SQL_P | STABLE | STANDALONE_P | START | STATEMENT | STATISTICS | STDIN | STDOUT | STORAGE | STORED | STRICT_P | STRIP_P | SUBSCRIPTION | SUPPORT | SYSID | SYSTEM_P | TABLES | TABLESPACE | TEMP | TEMPLATE | TEMPORARY | TEXT_P | TIES | TRANSACTION | TRANSFORM | TRIGGER | TRUNCATE | TRUSTED | TYPE_P | TYPES_P | UESCAPE | UNBOUNDED | UNCOMMITTED | UNENCRYPTED | UNKNOWN | UNLISTEN | UNLOGGED | UNTIL | UPDATE | VACUUM | VALID | VALIDATE | VALIDATOR | VALUE_P | VARYING | VERSION_P | VIEW | VIEWS | VOLATILE | WHITESPACE_P | WITHIN | WITHOUT | WORK | WRAPPER | WRITE | XML_P | YEAR_P | YES_P | ZONE ; col_name_keyword : BETWEEN | BIGINT | bit | BOOLEAN_P | CHAR_P | character | COALESCE | DEC | DECIMAL_P | EXISTS | EXTRACT | FLOAT_P | GREATEST | GROUPING | INOUT | INT_P | INTEGER | INTERVAL | LEAST | NATIONAL | NCHAR | NONE | NORMALIZE | NULLIF | numeric | OUT_P | OVERLAY | POSITION | PRECISION | REAL | ROW | SETOF | SMALLINT | SUBSTRING | TIME | TIMESTAMP | TREAT | TRIM | VALUES | VARCHAR | XMLATTRIBUTES | XMLCONCAT | XMLELEMENT | XMLEXISTS | XMLFOREST | XMLNAMESPACES | XMLPARSE | XMLPI | XMLROOT | XMLSERIALIZE | XMLTABLE | builtin_function_name ; type_func_name_keyword : AUTHORIZATION | BINARY | COLLATION | CONCURRENTLY | CROSS | CURRENT_SCHEMA | FREEZE | FULL | ILIKE | INNER_P | IS | ISNULL | JOIN | LIKE | NATURAL | NOTNULL | OUTER_P | OVERLAPS | SIMILAR | TABLESAMPLE | VERBOSE ; reserved_keyword : ALL | ANALYSE | ANALYZE | AND | ANY | ARRAY | AS | ASC | ASYMMETRIC | BOTH | CASE | CAST | CHECK | COLLATE | COLUMN | CONSTRAINT | CREATE | CURRENT_CATALOG | CURRENT_DATE | CURRENT_ROLE | CURRENT_TIME | CURRENT_TIMESTAMP | CURRENT_USER // | DEFAULT | DEFERRABLE | DESC | DISTINCT | DO | ELSE | END_P | EXCEPT | FALSE_P | FETCH | FOR | FOREIGN | FROM | GRANT | GROUP_P | HAVING | IN_P | INITIALLY | INTERSECT /* from pl_gram.y, line ~2982 * Fortunately, INTO is a fully reserved word in the main grammar, so * at least we need not worry about it appearing as an identifier. */ // | INTO | LATERAL_P | LEADING | LIMIT | LOCALTIME | LOCALTIMESTAMP | NOT | NULL_P | OFFSET | ON | ONLY | OR | ORDER | PLACING | PRIMARY | REFERENCES | RETURNING | SELECT | SESSION_USER | SOME | SYMMETRIC | TABLE | THEN | TO | TRAILING | TRUE_P | UNION | UNIQUE | USER | USING | VARIADIC | WHEN | WHERE | WINDOW | WITH ; builtin_function_name : XMLCOMMENT | XML_IS_WELL_FORMED | XML_IS_WELL_FORMED_DOCUMENT | XML_IS_WELL_FORMED_CONTENT | XMLAGG | XPATH | XPATH_EXISTS | ABS | CBRT | CEIL | CEILING | DEGREES | DIV | EXP | FACTORIAL | FLOOR | GCD | LCM | LN | LOG | LOG10 | MIN_SCALE | MOD | PI | POWER | RADIANS | ROUND | SCALE | SIGN | SQRT | TRIM_SCALE | TRUNC | WIDTH_BUCKET | RANDOM | SETSEED | ACOS | ACOSD | ACOSH | ASIN | ASIND | ASINH | ATAN | ATAND | ATANH | ATAN2 | ATAN2D | COS | COSD | COSH | COT | COTD | SIN | SIND | SINH | TAN | TAND | TANH | BIT_LENGTH | CHAR_LENGTH | CHARACTER_LENGTH | LOWER | OCTET_LENGTH | OCTET_LENGTH | UPPER | ASCII | BTRIM | CHR | CONCAT | CONCAT_WS | FORMAT | INITCAP | LENGTH | LPAD | LTRIM | MD5 | PARSE_IDENT | PG_CLIENT_ENCODING | QUOTE_IDENT | QUOTE_LITERAL | QUOTE_NULLABLE | REGEXP_COUNT | REGEXP_INSTR | REGEXP_LIKE | REGEXP_MATCH | REGEXP_MATCHES | REGEXP_REPLACE | REGEXP_SPLIT_TO_ARRAY | REGEXP_SPLIT_TO_TABLE | REGEXP_SUBSTR | REPEAT | REPLACE | REVERSE | RPAD | RTRIM | SPLIT_PART | STARTS_WITH | STRING_TO_ARRAY | STRING_TO_TABLE | STRPOS | SUBSTR | TO_ASCII | TO_HEX | TRANSLATE | UNISTR | AGE | DATE_BIN | DATE_PART | DATE_TRUNC | ISFINITE | JUSTIFY_DAYS | JUSTIFY_HOURS | JUSTIFY_INTERVAL | MAKE_DATE | MAKE_INTERVAL | MAKE_TIME | MAKE_TIMESTAMP | MAKE_TIMESTAMPTZ | CLOCK_TIMESTAMP | NOW | STATEMENT_TIMESTAMP | TIMEOFDAY | TRANSACTION_TIMESTAMP | TO_TIMESTAMP | JUSTIFY_INTERVAL | JUSTIFY_INTERVAL | TO_CHAR | TO_DATE | TO_NUMBER ; /************************************************************************************************************************************************************/ /*PL/SQL GRAMMAR */ /*PLSQL grammar */ /************************************************************************************************************************************************************/ pl_function : comp_options pl_block opt_semi ; comp_options : comp_option* ; comp_option : sharp OPTION DUMP | sharp PRINT_STRICT_PARAMS option_value | sharp VARIABLE_CONFLICT ERROR | sharp VARIABLE_CONFLICT USE_VARIABLE | sharp VARIABLE_CONFLICT USE_COLUMN ; sharp : Operator ; option_value : sconst | reserved_keyword | plsql_unreserved_keyword | unreserved_keyword ; opt_semi : | SEMI ; // exception_sect means opt_exception_sect in original grammar, don't be confused! pl_block : decl_sect BEGIN_P proc_sect exception_sect END_P opt_label ; decl_sect : opt_block_label (decl_start decl_stmts?)? ; decl_start : DECLARE ; decl_stmts : decl_stmt+ ; label_decl : LESS_LESS any_identifier GREATER_GREATER ; decl_stmt : decl_statement | DECLARE | label_decl ; decl_statement : decl_varname ( ALIAS FOR decl_aliasitem | decl_const decl_datatype decl_collate decl_notnull decl_defval | opt_scrollable CURSOR decl_cursor_args decl_is_for decl_cursor_query ) SEMI ; opt_scrollable : | NO SCROLL | SCROLL ; decl_cursor_query : selectstmt ; decl_cursor_args : | OPEN_PAREN decl_cursor_arglist CLOSE_PAREN ; decl_cursor_arglist : decl_cursor_arg (COMMA decl_cursor_arg)* ; decl_cursor_arg : decl_varname decl_datatype ; decl_is_for : IS | FOR ; decl_aliasitem : PARAM | colid ; decl_varname : any_identifier ; decl_const : | CONSTANT ; decl_datatype : typename ; //TODO: $$ = read_datatype(yychar); decl_collate : | COLLATE any_name ; decl_notnull : | NOT NULL_P ; decl_defval : | decl_defkey sql_expression ; decl_defkey : assign_operator | DEFAULT ; assign_operator : EQUAL | COLON_EQUALS ; proc_sect : proc_stmt* ; proc_stmt : pl_block SEMI | stmt_return | stmt_raise | stmt_assign | stmt_if | stmt_case | stmt_loop | stmt_while | stmt_for | stmt_foreach_a | stmt_exit | stmt_assert | stmt_execsql | stmt_dynexecute | stmt_perform | stmt_call | stmt_getdiag | stmt_open | stmt_fetch | stmt_move | stmt_close | stmt_null | stmt_commit | stmt_rollback | stmt_set ; stmt_perform : PERFORM expr_until_semi SEMI ; stmt_call : CALL any_identifier OPEN_PAREN opt_expr_list CLOSE_PAREN SEMI | DO any_identifier OPEN_PAREN opt_expr_list CLOSE_PAREN SEMI ; opt_expr_list : | expr_list ; stmt_assign : assign_var assign_operator sql_expression SEMI ; stmt_getdiag : GET getdiag_area_opt DIAGNOSTICS getdiag_list SEMI ; getdiag_area_opt : | CURRENT_P | STACKED ; getdiag_list : getdiag_list_item (COMMA getdiag_list_item)* ; getdiag_list_item : getdiag_target assign_operator getdiag_item ; getdiag_item : colid ; getdiag_target : assign_var ; assign_var : (any_name | PARAM) (OPEN_BRACKET expr_until_rightbracket CLOSE_BRACKET)* ; stmt_if : IF_P expr_until_then THEN proc_sect stmt_elsifs stmt_else END_P IF_P SEMI ; stmt_elsifs : (ELSIF a_expr THEN proc_sect)* ; stmt_else : | ELSE proc_sect ; stmt_case : CASE opt_expr_until_when case_when_list opt_case_else END_P CASE SEMI ; opt_expr_until_when : | sql_expression ; case_when_list : case_when+ ; case_when : WHEN expr_list THEN proc_sect ; opt_case_else : | ELSE proc_sect ; stmt_loop : opt_loop_label loop_body ; stmt_while : opt_loop_label WHILE expr_until_loop loop_body ; stmt_for : opt_loop_label FOR for_control loop_body ; //TODO: rewrite using read_sql_expression logic? for_control : for_variable IN_P ( cursor_name opt_cursor_parameters | selectstmt | explainstmt | EXECUTE a_expr opt_for_using_expression | opt_reverse a_expr DOT_DOT a_expr opt_by_expression ) ; opt_for_using_expression : | USING expr_list ; opt_cursor_parameters : | OPEN_PAREN a_expr (COMMA a_expr)* CLOSE_PAREN ; opt_reverse : | REVERSE ; opt_by_expression : | BY a_expr ; for_variable : any_name_list ; stmt_foreach_a : opt_loop_label FOREACH for_variable foreach_slice IN_P ARRAY a_expr loop_body ; foreach_slice : | SLICE iconst ; stmt_exit : exit_type opt_label opt_exitcond SEMI ; exit_type : EXIT | CONTINUE_P ; //todo implement RETURN statement according to initial grammar line 1754 stmt_return : RETURN (NEXT sql_expression | QUERY (EXECUTE a_expr opt_for_using_expression | selectstmt) | opt_return_result) SEMI ; opt_return_result : | sql_expression ; //https://www.postgresql.org/docs/current/plpgsql-errors-and-messages.html //RAISE [ level ] 'format' [, expression [, ... ]] [ USING option = expression [, ... ] ]; //RAISE [ level ] condition_name [ USING option = expression [, ... ] ]; //RAISE [ level ] SQLSTATE 'sqlstate' [ USING option = expression [, ... ] ]; //RAISE [ level ] USING option = expression [, ... ]; //RAISE ; stmt_raise : RAISE opt_stmt_raise_level sconst opt_raise_list opt_raise_using SEMI | RAISE opt_stmt_raise_level identifier opt_raise_using SEMI | RAISE opt_stmt_raise_level SQLSTATE sconst opt_raise_using SEMI | RAISE opt_stmt_raise_level opt_raise_using SEMI | RAISE ; opt_stmt_raise_level : | | DEBUG | LOG | INFO | NOTICE | WARNING | EXCEPTION ; opt_raise_list : | (COMMA a_expr)+ ; opt_raise_using : | USING opt_raise_using_elem_list ; opt_raise_using_elem : identifier EQUAL a_expr ; opt_raise_using_elem_list : opt_raise_using_elem (COMMA opt_raise_using_elem)* ; //todo imnplement stmt_assert : ASSERT sql_expression opt_stmt_assert_message SEMI ; opt_stmt_assert_message : | COMMA sql_expression ; loop_body : LOOP proc_sect END_P LOOP opt_label SEMI ; //TODO: looks like all other statements like INSERT/SELECT/UPDATE/DELETE are handled here; //pls take a look at original grammar stmt_execsql : make_execsql_stmt SEMI /*K_IMPORT | K_INSERT | t_word | t_cword */ ; //https://www.postgresql.org/docs/current/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-NORESULT //EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ]; stmt_dynexecute : EXECUTE a_expr ( /*this is silly, but i have to time to find nice way to code */ opt_execute_into opt_execute_using | opt_execute_using opt_execute_into |) SEMI ; opt_execute_using : | USING opt_execute_using_list ; opt_execute_using_list : a_expr (COMMA a_expr)* ; opt_execute_into : | INTO STRICT_P? into_target ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //OPEN unbound_cursorvar [ [ NO ] SCROLL ] FOR query; //OPEN unbound_cursorvar [ [ NO ] SCROLL ] FOR EXECUTE query_string // [ USING expression [, ... ] ]; //OPEN bound_cursorvar [ ( [ argument_name := ] argument_value [, ...] ) ]; stmt_open : OPEN ( cursor_variable opt_scroll_option FOR (selectstmt | EXECUTE sql_expression opt_open_using) | colid (OPEN_PAREN opt_open_bound_list CLOSE_PAREN)? ) SEMI ; opt_open_bound_list_item : colid COLON_EQUALS a_expr | a_expr ; opt_open_bound_list : opt_open_bound_list_item (COMMA opt_open_bound_list_item)* ; opt_open_using : | USING expr_list ; opt_scroll_option : | opt_scroll_option_no SCROLL ; opt_scroll_option_no : | NO ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //FETCH [ direction { FROM | IN } ] cursor INTO target; stmt_fetch : FETCH direction = opt_fetch_direction opt_cursor_from cursor_variable INTO into_target SEMI ; into_target : expr_list ; opt_cursor_from : | FROM | IN_P ; opt_fetch_direction : | | NEXT | PRIOR | FIRST_P | LAST_P | ABSOLUTE_P a_expr | RELATIVE_P a_expr | a_expr | ALL | (FORWARD | BACKWARD) (a_expr | ALL)? ; //https://www.postgresql.org/docs/current/plpgsql-cursors.html#PLPGSQL-CURSOR-OPENING //MOVE [ direction { FROM | IN } ] cursor; stmt_move : MOVE opt_fetch_direction cursor_variable SEMI ; stmt_close : CLOSE cursor_variable SEMI ; stmt_null : NULL_P SEMI ; stmt_commit : COMMIT plsql_opt_transaction_chain SEMI ; stmt_rollback : ROLLBACK plsql_opt_transaction_chain SEMI ; plsql_opt_transaction_chain : AND NO? CHAIN | ; stmt_set : SET any_name TO DEFAULT SEMI | RESET (any_name | ALL) SEMI ; cursor_variable : colid | PARAM ; exception_sect : | EXCEPTION proc_exceptions ; proc_exceptions : proc_exception+ ; proc_exception : WHEN proc_conditions THEN proc_sect ; proc_conditions : proc_condition (OR proc_condition)* ; proc_condition : any_identifier | SQLSTATE sconst ; //expr_until_semi: //; //expr_until_rightbracket: //; //expr_until_loop: //; opt_block_label : | label_decl ; opt_loop_label : | label_decl ; opt_label : | any_identifier ; opt_exitcond : WHEN expr_until_semi | ; any_identifier : colid | plsql_unreserved_keyword ; plsql_unreserved_keyword : ABSOLUTE_P | ALIAS | AND | ARRAY | ASSERT | BACKWARD | CALL | CHAIN | CLOSE | COLLATE | COLUMN //| COLUMN_NAME | COMMIT | CONSTANT | CONSTRAINT //| CONSTRAINT_NAME | CONTINUE_P | CURRENT_P | CURSOR //| DATATYPE | DEBUG | DEFAULT //| DETAIL | DIAGNOSTICS | DO | DUMP | ELSIF //| ERRCODE | ERROR | EXCEPTION | EXIT | FETCH | FIRST_P | FORWARD | GET //| HINT //| IMPORT | INFO | INSERT | IS | LAST_P //| MESSAGE //| MESSAGE_TEXT | MOVE | NEXT | NO | NOTICE | OPEN | OPTION | PERFORM //| PG_CONTEXT //| PG_DATATYPE_NAME //| PG_EXCEPTION_CONTEXT //| PG_EXCEPTION_DETAIL //| PG_EXCEPTION_HINT | PRINT_STRICT_PARAMS | PRIOR | QUERY | RAISE | RELATIVE_P | RESET | RETURN //| RETURNED_SQLSTATE | ROLLBACK //| ROW_COUNT | ROWTYPE | SCHEMA //| SCHEMA_NAME | SCROLL | SET | SLICE | SQLSTATE | STACKED | TABLE //| TABLE_NAME | TYPE_P | USE_COLUMN | USE_VARIABLE | VARIABLE_CONFLICT | WARNING | OUTER_P ; sql_expression : opt_target_list into_clause from_clause where_clause group_clause having_clause window_clause ; expr_until_then : sql_expression ; expr_until_semi : sql_expression ; expr_until_rightbracket : a_expr ; expr_until_loop : a_expr ; make_execsql_stmt : stmt opt_returning_clause_into ; opt_returning_clause_into : INTO opt_strict into_target | ; ================================================ FILE: superior-redshift-parser/src/main/java/io/github/melin/superior/parser/redshift/antlr4/LexerDispatchingErrorListener.java ================================================ package io.github.melin.superior.parser.redshift.antlr4; import java.util.BitSet; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.*; public class LexerDispatchingErrorListener implements ANTLRErrorListener { Lexer _parent; public LexerDispatchingErrorListener(Lexer parent) { _parent = parent; } public void syntaxError( Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); } public void reportAmbiguity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs); } public void reportAttemptingFullContext( Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs); } public void reportContextSensitivity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs); } } ================================================ FILE: superior-redshift-parser/src/main/java/io/github/melin/superior/parser/redshift/antlr4/ParserDispatchingErrorListener.java ================================================ package io.github.melin.superior.parser.redshift.antlr4; import java.util.BitSet; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.dfa.*; public class ParserDispatchingErrorListener implements ANTLRErrorListener { Parser _parent; public ParserDispatchingErrorListener(Parser parent) { _parent = parent; } public void syntaxError( Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e); } public void reportAmbiguity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, boolean exact, BitSet ambigAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAmbiguity(recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs); } public void reportAttemptingFullContext( Parser recognizer, DFA dfa, int startIndex, int stopIndex, BitSet conflictingAlts, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportAttemptingFullContext(recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs); } public void reportContextSensitivity( Parser recognizer, DFA dfa, int startIndex, int stopIndex, int prediction, ATNConfigSet configs) { ProxyErrorListener foo = new ProxyErrorListener(_parent.getErrorListeners()); foo.reportContextSensitivity(recognizer, dfa, startIndex, stopIndex, prediction, configs); } } ================================================ FILE: superior-redshift-parser/src/main/java/io/github/melin/superior/parser/redshift/antlr4/RedshiftLexerBase.java ================================================ package io.github.melin.superior.parser.redshift.antlr4; import java.util.ArrayDeque; import java.util.Deque; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.Lexer; public abstract class RedshiftLexerBase extends Lexer { protected final Deque tags = new ArrayDeque<>(); protected RedshiftLexerBase(CharStream input) { super(input); } public void pushTag() { tags.push(getText()); } public boolean isTag() { return getText().equals(tags.peek()); } public void popTag() { tags.pop(); } public boolean checkLA(int c) { return getInputStream().LA(1) != c; } public boolean charIsLetter() { return Character.isLetter(getInputStream().LA(-1)); } public void HandleNumericFail() { getInputStream().seek(getInputStream().index() - 2); setType(RedshiftLexer.Integral); } public void HandleLessLessGreaterGreater() { if (getText() == "<<") setType(RedshiftLexer.LESS_LESS); if (getText() == ">>") setType(RedshiftLexer.GREATER_GREATER); } public void UnterminatedBlockCommentDebugAssert() { // Debug.Assert(InputStream.LA(1) == -1 /*EOF*/); } public boolean CheckIfUtf32Letter() { int codePoint = getInputStream().LA(-2) << 8 + getInputStream().LA(-1); char[] c; if (codePoint < 0x10000) { c = new char[] {(char) codePoint}; } else { codePoint -= 0x10000; c = new char[] {(char) (codePoint / 0x400 + 0xd800), (char) (codePoint % 0x400 + 0xdc00)}; } return Character.isLetter(c[0]); } } ================================================ FILE: superior-redshift-parser/src/main/java/io/github/melin/superior/parser/redshift/antlr4/RedshiftParserBase.java ================================================ package io.github.melin.superior.parser.redshift.antlr4; import io.github.melin.superior.common.antlr4.UpperCaseCharStream; import java.util.List; import org.antlr.v4.runtime.*; import org.apache.commons.lang3.StringUtils; public abstract class RedshiftParserBase extends Parser { public RedshiftParserBase(TokenStream input) { super(input); } ParserRuleContext GetParsedSqlTree(String script, int line) { RedshiftParser ph = getPostgreSQLParser(script); ParserRuleContext result = ph.root(); return result; } public void ParseRoutineBody(RedshiftParser.Createfunc_opt_listContext _localctx) { String lang = null; for (RedshiftParser.Createfunc_opt_itemContext coi : _localctx.createfunc_opt_item()) { if (coi.LANGUAGE() != null) { if (coi.nonreservedword_or_sconst() != null) if (coi.nonreservedword_or_sconst().nonreservedword() != null) if (coi.nonreservedword_or_sconst().nonreservedword().identifier() != null) if (coi.nonreservedword_or_sconst() .nonreservedword() .identifier() .Identifier() != null) { lang = coi.nonreservedword_or_sconst() .nonreservedword() .identifier() .Identifier() .getText(); break; } } } if (null == lang) return; RedshiftParser.Createfunc_opt_itemContext func_as = null; for (RedshiftParser.Createfunc_opt_itemContext a : _localctx.createfunc_opt_item()) { if (a.func_as() != null) { func_as = a; break; } } if (func_as != null) { String txt = GetRoutineBodyString(func_as.func_as().sconst(0)); RedshiftParser ph = getPostgreSQLParser(StringUtils.trim(txt)); switch (lang) { case "plpgsql": func_as.func_as().Definition = ph.sqlroot(); break; case "sql": func_as.func_as().Definition = ph.root(); break; } } } private String TrimQuotes(String s) { return (s == null || s.isEmpty()) ? s : s.substring(1, s.length() - 1); } public String unquote(String s) { int slength = s.length(); StringBuilder r = new StringBuilder(slength); int i = 0; while (i < slength) { Character c = s.charAt(i); r.append(c); if (c == '\'' && i < slength - 1 && (s.charAt(i + 1) == '\'')) i++; i++; } return r.toString(); } public String GetRoutineBodyString(RedshiftParser.SconstContext rule) { RedshiftParser.AnysconstContext anysconst = rule.anysconst(); org.antlr.v4.runtime.tree.TerminalNode StringConstant = anysconst.StringConstant(); if (null != StringConstant) return unquote(TrimQuotes(StringConstant.getText())); org.antlr.v4.runtime.tree.TerminalNode UnicodeEscapeStringConstant = anysconst.UnicodeEscapeStringConstant(); if (null != UnicodeEscapeStringConstant) return TrimQuotes(UnicodeEscapeStringConstant.getText()); org.antlr.v4.runtime.tree.TerminalNode EscapeStringConstant = anysconst.EscapeStringConstant(); if (null != EscapeStringConstant) return TrimQuotes(EscapeStringConstant.getText()); String result = ""; List dollartext = anysconst.DollarText(); for (org.antlr.v4.runtime.tree.TerminalNode s : dollartext) { result += s.getText(); } return result; } public RedshiftParser getPostgreSQLParser(String script) { UpperCaseCharStream charStream = new UpperCaseCharStream(CharStreams.fromString(script)); Lexer lexer = new RedshiftLexer(charStream); CommonTokenStream tokens = new CommonTokenStream(lexer); RedshiftParser parser = new RedshiftParser(tokens); lexer.removeErrorListeners(); parser.removeErrorListeners(); LexerDispatchingErrorListener listener_lexer = new LexerDispatchingErrorListener( (Lexer) (((CommonTokenStream) (this.getInputStream())).getTokenSource())); ParserDispatchingErrorListener listener_parser = new ParserDispatchingErrorListener(this); lexer.addErrorListener(listener_lexer); parser.addErrorListener(listener_parser); return parser; } } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.redshift.antlr4.RedshiftParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(RedshiftParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: RedshiftParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(RedshiftParser._ATN)) } } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/RedshiftSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.postgre import com.github.melin.superior.sql.parser.util.CommonUtils import com.google.common.collect.Lists import io.github.melin.superior.common.* import io.github.melin.superior.common.AlterActionType.* import io.github.melin.superior.common.StatementType.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.RefreshMaterializedView import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropMaterializedView import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.drop.DropView import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.common.relational.table.TruncateTable import io.github.melin.superior.parser.postgre.relational.CreatePartitionTable import io.github.melin.superior.parser.redshift.antlr4.RedshiftParser import io.github.melin.superior.parser.redshift.antlr4.RedshiftParser.SqlrootContext import io.github.melin.superior.parser.redshift.antlr4.RedshiftParserBaseVisitor import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:57 上午 */ class RedshiftSqlAntlr4Visitor(val splitSql: Boolean = false) : RedshiftParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() // 多语句解析结果 private var statements: ArrayList = arrayListOf() // 存储过程和函数中包含的子语句 private var childStatements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitDecl_cursor_query(ctx: RedshiftParser.Decl_cursor_queryContext): Statement? { val statement = visitSelectstmt(ctx.selectstmt()) statement.setSql(source(ctx)) childStatements.add(statement) return null } override fun visitStmtmulti(ctx: RedshiftParser.StmtmultiContext): Statement? { ctx.stmt().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitStmt(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) currentOptType = StatementType.UNKOWN clean() } } return null } override fun visitStmt(ctx: RedshiftParser.StmtContext): Statement? { val stmt: Statement? = super.visitStmt(ctx) if (stmt != null) { if (currentOptType != CREATE_FUNCTION && currentOptType != CREATE_PROCEDURE) { stmt.setSql(source(ctx)) childStatements.add(stmt) } } clean() return stmt } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() } private fun addOutputTableId(tableId: TableId) { if (!outputTables.contains(tableId)) { outputTables.add(tableId) } } // -----------------------------------database------------------------------------------------- override fun visitCreatedbstmt(ctx: RedshiftParser.CreatedbstmtContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.name().text) return CreateDatabase(databaseName) } override fun visitDropdbstmt(ctx: RedshiftParser.DropdbstmtContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.name().text) return DropDatabase(databaseName) } // -----------------------------------schema------------------------------------------------- override fun visitCreateschemastmt(ctx: RedshiftParser.CreateschemastmtContext): Statement { val schemaName = CommonUtils.cleanQuote(ctx.colid().text) return CreateSchema(schemaName) } // -----------------------------------table------------------------------------------------- override fun visitCreatestmt(ctx: RedshiftParser.CreatestmtContext): Statement { currentOptType = CREATE_TABLE if (ctx.PARTITION() != null) { val partitionTableId = parseTableName(ctx.qualified_name(0)) val tableId = parseTableName(ctx.qualified_name(1)) return CreatePartitionTable(tableId, partitionTableId) } val tableId = parseTableName(ctx.qualified_name(0)) val columns = ctx.opttableelementlist()?.tableelementlist()?.tableelement()?.map { val colDef = it.columnDef() val colName = colDef.colid().text val dataType = colDef.typename().text val columnRel = ColumnRel(colName, dataType) colDef.colquallist().colconstraint().forEach { colconstraint -> val child = colconstraint.getChild(0) if (child is RedshiftParser.ColconstraintelemContext) { if (child.NOT() != null) { columnRel.nullable = false } else if (child.PRIMARY() != null) { columnRel.primaryKey = true } } } columnRel } val createTable = CreateTable(tableId, TableType.POSTGRES, columnRels = columns) if (ctx.opttemp().TEMP() != null || ctx.opttemp().TEMPORARY() != null) { createTable.temporary = true } val partitionspec = ctx.optpartitionspec()?.partitionspec() val tablePartition = ctx.gaussextension()?.tablePartition() if (partitionspec != null) { val partitionType = partitionspec.colid().text.uppercase() val partitionColumns = partitionspec.part_params().part_elem().map { it.text } createTable.partitionColumnNames.addAll(partitionColumns) if ("RANGE" == partitionType) { createTable.partitionType = PartitionType.RANGE } else { createTable.partitionType = PartitionType.LIST } } else if (tablePartition != null) { var partitionType: PartitionType? = null val partitionColumns = mutableListOf() val ptSpec = tablePartition.partition_list() if (ptSpec.list_partition_stmt() != null) { partitionType = PartitionType.LIST partitionColumns.add(ptSpec.list_partition_stmt().partition_key().colid().text) } else if (ptSpec.value_partition_stmt() != null) { partitionType = PartitionType.VALUES partitionColumns.add(ptSpec.value_partition_stmt().partition_key().colid().text) } else if (ptSpec.range_partition_stmt() != null) { partitionType = PartitionType.RANGE partitionColumns.add(ptSpec.range_partition_stmt().partition_key().colid().text) } else if (ptSpec.normal_partition_stmt() != null) { partitionType = PartitionType.NORMAL } createTable.partitionColumnNames.addAll(partitionColumns) createTable.partitionType = partitionType } return createTable } override fun visitFunc_as(ctx: RedshiftParser.Func_asContext): Statement? { if (ctx.Definition != null) { visitSqlroot(ctx.Definition as SqlrootContext) } return super.visitFunc_as(ctx) } override fun visitCreatefunctionstmt(ctx: RedshiftParser.CreatefunctionstmtContext): Statement { currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE childStatements = arrayListOf() val optItems = ctx.createfunc_opt_list().createfunc_opt_item() if (optItems != null) { optItems .filter { it.func_as() != null && it.func_as().Definition != null } .forEach { visitSqlroot(it.func_as().Definition as RedshiftParser.SqlrootContext) } } val replace = if (ctx.opt_or_replace().REPLACE() != null) true else false val funcName = ctx.func_name() if (ctx.FUNCTION() != null) { val functionId = if (funcName.type_function_name() != null) { FunctionId(funcName.text) } else { FunctionId(funcName.colid().text, funcName.indirection().indirection_el()[0].attr_name().text) } currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE return CreateFunction(functionId, childStatements, replace) } else { val procedureId = if (funcName.type_function_name() != null) { ProcedureId(funcName.text) } else { ProcedureId(funcName.colid().text, funcName.indirection().indirection_el()[0].attr_name().text) } currentOptType = if (ctx.FUNCTION() != null) CREATE_FUNCTION else CREATE_PROCEDURE return CreateProcedure(procedureId, childStatements, replace) } } override fun visitProc_stmt(ctx: RedshiftParser.Proc_stmtContext): Statement? { super.visitProc_stmt(ctx) return null } override fun visitViewstmt(ctx: RedshiftParser.ViewstmtContext): Statement { currentOptType = StatementType.CREATE_VIEW val tableId = parseTableName(ctx.qualified_name()) val replace = if (ctx.REPLACE() != null) true else false val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createView = CreateView(tableId, queryStmt) createView.replace = replace if (ctx.opttemp().TEMP() != null || ctx.opttemp().TEMPORARY() != null) { createView.temporary = true } return createView } override fun visitCreatematviewstmt(ctx: RedshiftParser.CreatematviewstmtContext): Statement { currentOptType = StatementType.CREATE_MATERIALIZED_VIEW val tableId = parseTableName(ctx.create_mv_target().qualified_name()) val ifNotExists = if (ctx.IF_P() != null) true else false val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createView = CreateMaterializedView(tableId, queryStmt) createView.ifNotExists = ifNotExists return createView } override fun visitRefreshmatviewstmt(ctx: RedshiftParser.RefreshmatviewstmtContext): Statement { val tableId = parseTableName(ctx.qualified_name()) return RefreshMaterializedView(tableId) } override fun visitRenamestmt(ctx: RedshiftParser.RenamestmtContext): Statement? { if (ctx.TABLE() != null) { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterTable(tableId, action) } else if (ctx.VIEW() != null) { if (ctx.MATERIALIZED() == null) { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterView(tableId, action) } else { val tableId = parseTableName(ctx.qualified_name()) val newTable = ctx.name().get(0).text val ifexists = ctx.EXISTS() != null val action = RenameAction(TableId(newTable), ifexists) return AlterMaterializedView(tableId, action) } } else { return null } } override fun visitSelectstmt(ctx: RedshiftParser.SelectstmtContext): Statement { currentOptType = StatementType.SELECT super.visitSelectstmt(ctx) return QueryStmt(inputTables, limit, offset) } override fun visitCreateasstmt(ctx: RedshiftParser.CreateasstmtContext): Statement { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val tableId = parseTableName(ctx.create_as_target().qualified_name()) val queryStmt = this.visitSelectstmt(ctx.selectstmt()) as QueryStmt val createTable = CreateTableAsSelect(tableId, queryStmt) return createTable } override fun visitUpdatestmt(ctx: RedshiftParser.UpdatestmtContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableName(ctx.relation_expr_opt_alias().relation_expr()) addOutputTableId(tableId) super.visitWhere_or_current_clause(ctx.where_or_current_clause()) super.visitFrom_clause(ctx.from_clause()) return UpdateTable(tableId, inputTables) } override fun visitDeletestmt(ctx: RedshiftParser.DeletestmtContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.relation_expr_opt_alias().relation_expr()) addOutputTableId(tableId) super.visitWhere_or_current_clause(ctx.where_or_current_clause()) super.visitUsing_clause(ctx.using_clause()) return DeleteTable(tableId, inputTables) } override fun visitInsertstmt(ctx: RedshiftParser.InsertstmtContext): Statement { currentOptType = StatementType.INSERT if (ctx.opt_with_clause() != null) { this.visitOpt_with_clause(ctx.opt_with_clause()) } val tableId = parseTableName(ctx.insert_target().qualified_name()) addOutputTableId(tableId) val queryStmt = this.visitSelectstmt(ctx.insert_rest().selectstmt()) as QueryStmt val insertTable = InsertTable(InsertMode.INTO, queryStmt, tableId) insertTable.outputTables.addAll(outputTables.subList(1, outputTables.size)) return insertTable } override fun visitMergestmt(ctx: RedshiftParser.MergestmtContext): Statement { currentOptType = StatementType.MERGE val mergeTableId = parseTableName(ctx.qualified_name(0)) val mergeTable = MergeTable(mergeTableId) if (ctx.qualified_name().size == 2) { val tableId = parseTableName(ctx.qualified_name(1)) inputTables.add(tableId) } else if (ctx.select_with_parens() != null) { super.visitSelect_with_parens(ctx.select_with_parens()) } mergeTable.inputTables = inputTables return mergeTable } override fun visitCte_list(ctx: RedshiftParser.Cte_listContext): Statement { ctx.common_table_expr().forEach { cteTempTables.add(TableId(it.name().text)) } return super.visitCte_list(ctx) } override fun visitQualified_name(ctx: RedshiftParser.Qualified_nameContext): Statement? { if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.CREATE_MATERIALIZED_VIEW || currentOptType == StatementType.CREATE_TABLE_AS_SELECT || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.MERGE || currentOptType == StatementType.INSERT || currentOptType == StatementType.CREATE_FUNCTION || currentOptType == StatementType.CREATE_PROCEDURE ) { if (ctx.parent is RedshiftParser.OpttempTableNameContext) { return null } val tableId = parseTableName(ctx) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } return null } else { throw SQLParserException("not support") } } // create index override fun visitIndexstmt(ctx: RedshiftParser.IndexstmtContext): Statement { val tableId = parseTableName(ctx.relation_expr()) val indexName = if (ctx.opt_index_name() != null) { ctx.opt_index_name().text } else { ctx.name().text } val createIndex = CreateIndex(indexName) return AlterTable(tableId, createIndex) } override fun visitDropstmt(ctx: RedshiftParser.DropstmtContext): Statement { if (ctx.object_type_any_name() != null) { val ifExists = ctx.IF_P() != null if (ctx.object_type_any_name().INDEX() != null) { val actions = ctx.any_name_list().any_name().map { indexName -> DropIndex(indexName.text, ifExists) } val tableId = TableId("") val alterTable = AlterTable(tableId) alterTable.ifExists = ifExists alterTable.addActions(actions) return alterTable } else if (ctx.object_type_any_name().TABLE() != null) { val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } val dropTable = DropTable(tableIds.first(), ifExists) dropTable.tableIds.addAll(tableIds) return dropTable } else if (ctx.object_type_any_name().VIEW() != null) { val isMaterialized = if (ctx.object_type_any_name().MATERIALIZED() != null) { true } else { false } val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } if (isMaterialized) { val dropView = DropMaterializedView(tableIds.first(), ifExists) dropView.tableIds.addAll(tableIds) return dropView } else { val dropView = DropView(tableIds.first(), ifExists) dropView.tableIds.addAll(tableIds) return dropView } } else if (ctx.object_type_any_name().SEQUENCE() != null) { val tableIds = ctx.any_name_list().any_name().map { tableName -> parseTableName(tableName) } val dropSequence = io.github.melin.superior.common.relational.drop.DropSequence(tableIds.first(), ifExists) dropSequence.tableIds.addAll(tableIds) return dropSequence } } throw SQLParserException("not support") } override fun visitTruncatestmt(ctx: RedshiftParser.TruncatestmtContext): Statement { val tableIds = ctx.relation_expr_list().relation_expr().map { parseTableName(it) } return TruncateTable(Lists.newArrayList(tableIds)) } override fun visitAltertablestmt(ctx: RedshiftParser.AltertablestmtContext): Statement? { if (ctx.TABLE() != null) { if (ctx.relation_expr() != null) { val tableId = parseTableName(ctx.relation_expr()) if (ctx.alter_table_cmds() != null) { val alterTable = AlterTable(tableId) val cmds = ctx.alter_table_cmds().alter_table_cmd() for (cmdContext in cmds) { if (cmdContext.ADD_P() != null && cmdContext.columnDef() != null) { val columnDef = cmdContext.columnDef() val columnName = columnDef.colid().text val dataType = source(columnDef.typename()) val action = AlterColumnAction(ADD_COLUMN, columnName, dataType) action.ifNotExists = cmdContext.EXISTS() != null alterTable.actions.add(action) } else if (cmdContext.alter_column_default() != null) { val columnDefaultDef = cmdContext.alter_column_default() val columnName = cmdContext.colid().get(0).text if (columnDefaultDef.DROP() != null) { val action = AlterColumnAction(DROP_COLUMN_DRFAULT, columnName) alterTable.actions.add(action) } else { val value = source(columnDefaultDef.a_expr()) val action = AlterColumnAction(SET_COLUMN_DEFAULT, columnName) action.defaultExpression = CommonUtils.cleanQuote(value) alterTable.actions.add(action) } } } return alterTable } else { var alterTable: AlterTable? = null val partitionCmd = ctx.partition_cmd() if (partitionCmd.ATTACH() != null) { alterTable = AlterTable(tableId, AlterTableAction(ATTACH_PARTITION)) } else { alterTable = AlterTable(tableId, AlterTableAction(DETACH_PARTITION)) } return alterTable } return null } } return null } override fun visitCommentstmt(ctx: RedshiftParser.CommentstmtContext): Statement { val objType: String? = if (ctx.object_type_any_name() != null) { ctx.object_type_any_name().children.map { it.text }.joinToString(" ") } else if (ctx.object_type_name() != null) { ctx.object_type_name().children.map { it.text }.joinToString(" ") } else if (ctx.object_type_name_on_any_name() != null) { ctx.object_type_name_on_any_name().children.map { it.text }.joinToString(" ") } else if (ctx.COLUMN() != null) { ctx.COLUMN().text } else if (ctx.FUNCTION() != null) { ctx.FUNCTION().text } else { null } val objValue = if (ctx.any_name() != null) ctx.any_name().text else null val isNull = if (ctx.comment_text().NULL_P() != null) true else false val text: String? = if (ctx.comment_text().text != null) CommonUtils.cleanQuote(ctx.comment_text().sconst().text) else null return CommentStatement(text, isNull, objType, objValue) } // ----------------------------------------private methods------------------------------------ override fun visitSelect_limit(ctx: RedshiftParser.Select_limitContext): Statement? { val limitClause = ctx.limit_clause() val offsetClause = ctx.offset_clause() if (limitClause != null) { if (limitClause.LIMIT() != null) { if (limitClause.select_limit_value().a_expr() != null) { limit = limitClause.select_limit_value().a_expr().text.toInt() } if (limitClause.select_offset_value() != null) { offset = limitClause.select_offset_value().a_expr().text.toInt() } } if (limitClause.FETCH() != null && limitClause.select_fetch_first_value() != null) { if (limitClause.select_fetch_first_value().c_expr() != null) { limit = limitClause.select_fetch_first_value().c_expr().text.toInt() } } } if (offsetClause != null) { if (offsetClause.select_offset_value() != null) { offset = offsetClause.select_offset_value().text.toInt() } if (offsetClause.select_fetch_first_value() != null) { if (offsetClause.select_fetch_first_value().c_expr() != null) { offset = offsetClause.select_fetch_first_value().c_expr().text.toInt() } } } return super.visitSelect_limit(ctx) } fun parseTableName(ctx: RedshiftParser.Any_nameContext): TableId { val attrNames = ctx.attrs()?.attr_name() if (attrNames == null) { return TableId(null, null, ctx.colid().text) } if (attrNames.size == 2) { return TableId(ctx.colid().text, attrNames.get(0).text, attrNames.get(1).text) } else if (attrNames.size == 1) { return TableId(null, ctx.colid().text, attrNames.get(0).text) } throw SQLParserException("parse schema qualified name error") } fun parseTableName(ctx: RedshiftParser.Relation_exprContext): TableId { return parseTableName(ctx.qualified_name()) } fun parseTableName(ctx: RedshiftParser.Qualified_nameContext): TableId { if (ctx.childCount == 2) { val obj = ctx.getChild(1) if (obj.childCount == 2) { return TableId(ctx.getChild(0).text, obj.getChild(0).getChild(1).text, obj.getChild(1).getChild(1).text) } else if (obj.childCount == 1) { val inEl = obj.getChild(0) as RedshiftParser.Indirection_elContext return TableId(ctx.colid().text, inEl.attr_name().text) } } else if (ctx.childCount == 1) { return TableId(ctx.getChild(0).text) } throw SQLParserException("parse schema qualified name error") } } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/RedshiftSqlHelper.kt ================================================ package io.github.melin.superior.parser.postgre import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.redshift.antlr4.RedshiftLexer import io.github.melin.superior.parser.redshift.antlr4.RedshiftParser import io.github.melin.superior.parser.redshift.antlr4.RedshiftParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:58 上午 */ object RedshiftSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until RedshiftLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = RedshiftLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = RedshiftSqlAntlr4Visitor(false) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = RedshiftSqlAntlr4Visitor(true) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = RedshiftParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: RedshiftParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = RedshiftLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = RedshiftParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) // parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.root()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.root()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/relational/CreatePartitionTable.kt ================================================ package io.github.melin.superior.parser.postgre.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class CreatePartitionTable(override val tableId: TableId, val partitionTableId: TableId) : AbsTableStatement() { // 是否存在 if exists 关键字 override val statementType = StatementType.CREATE_TABLE override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/BooleanType.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsType class BooleanType : AbsType() { override val name: String = "boolean" override val alias: String = "bool" } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/JsonType.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsType class JsonType : AbsType() { override val name: String = "json" } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/datetime.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsDataTimeType class DateType : AbsDataTimeType() { override val name: String = "date" } data class TimeType(val precision: Int = 0, val timezone: Boolean = false) : AbsDataTimeType() { override val name: String = "time" override val alias: String = "timez" } data class TimeStampType(val precision: Int = 0, val timezone: Boolean = false) : AbsDataTimeType() { override val name: String = "timestamp" override val alias: String = "timestampz" } class IntervalType : AbsDataTimeType() { override val name: String = "interval" } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/numeric.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsNumericType data class SmallIntType(val length: Int) : AbsNumericType() { override val name: String = "smallint" override val alias: String = "int2" companion object { const val MIN_VALUE: Int = -32768 const val MAX_VALUE: Int = 32767 } } data class IntegerType(val length: Int) : AbsNumericType() { override val name: String = "integer" override val alias: String = "int" override val alias2: String = "int4" companion object { const val MIN_VALUE: Long = -2147483648L const val MAX_VALUE: Long = 2147483647L } } data class BigIntType(val length: Int) : AbsNumericType() { override val name: String = "bigint" override val alias: String = "int8" } data class NumericType(val precision: Int = 10, val scale: Int = 0) : AbsNumericType() { override val name: String = "numeric" override val alias: String = "decimal" } data class FloatType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "float" } data class DoubleType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "double precision" override val alias: String = "float8" } data class RealType(val precision: Int, val scale: Int = 0) : AbsNumericType() { override val name: String = "real" override val alias: String = "float4" } data class SmallserialType(val length: Int) : AbsNumericType() { override val name: String = "smallserial" override val alias: String = "serial2" companion object { const val MIN_VALUE: Int = 1 const val MAX_VALUE: Int = 32767 } } data class SerialType(val length: Int) : AbsNumericType() { override val name: String = "serial" override val alias: String = "serial4" companion object { const val MIN_VALUE: Long = 1 const val MAX_VALUE: Long = 2147483647L } } data class BigserialType(val length: Int) : AbsNumericType() { override val name: String = "bigserial" override val alias: String = "serial8" } data class BitType(val length: Int) : AbsNumericType() { override val name: String = "bit" } data class VarbitType(val length: Int) : AbsNumericType() { override val name: String = "bit varying" override val alias: String = "varbit" } ================================================ FILE: superior-redshift-parser/src/main/kotlin/io/github/melin/superior/parser/postgre/type/string.kt ================================================ package io.github.melin.superior.parser.postgre.type import io.github.melin.superior.common.type.AbsStringType data class CharType(val length: Int) : AbsStringType() { override val name: String = "char" override val alias: String = "character" companion object { const val MAX_LENGTH: Int = 255 } } data class VarcharType(val length: Int) : AbsStringType() { override val name: String = "varchar" override val alias: String = "character varying" companion object { const val MAX_LENGTH: Int = 65535 } } class TextType : AbsStringType() { override val name: String = "text" } class ByteaType : AbsStringType() { override val name: String = "bytea" } data class EnumType(val typeName: String, val values: List) : AbsStringType() { override val name: String = "enum" } ================================================ FILE: superior-redshift-parser/src/test/java/io/github/melin/superior/parser/postgre/RedshiftSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.AlterActionType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.CommentStatement import io.github.melin.superior.common.relational.common.RefreshMaterializedView import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropMaterializedView import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.parser.postgre.relational.CreatePartitionTable import org.junit.Assert import org.junit.Test /** * Created by libinsong on 2020/6/30 11:04 上午 */ class RedshiftSqlParserDdlTest { @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE bigdata1; drop DATABASE bigdata2 """.trimIndent() val statements = RedshiftSqlHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("bigdata1", createDatabse.databaseName) } else { Assert.fail() } if (dropDatabase is DropDatabase) { Assert.assertEquals("bigdata2", dropDatabase.databaseName) } else { Assert.fail() } } @Test fun createSchemaTest() { val sql = """ CREATE schema bigdata1; CREATE schema bigdata2; """.trimIndent() val statements = RedshiftSqlHelper.parseMultiStatement(sql) val createSchema1 = statements.get(0) val createSchema2 = statements.get(1) if (createSchema1 is CreateSchema) { Assert.assertEquals("bigdata1", createSchema1.schemaName) } else { Assert.fail() } if (createSchema2 is CreateSchema) { Assert.assertEquals("bigdata2", createSchema2.schemaName) } else { Assert.fail() } } @Test fun createTable0() { val sql = """ CREATE TEMPORARY TABLE test.public.authors ( id INTEGER NOT NULL PRIMARY KEY, last_name TEXT, first_name TEXT, age int not null ) PARTITION BY RANGE (age); """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertTrue(statement.temporary) Assert.assertEquals(TableId("test", "public", "authors"), statement.tableId) Assert.assertEquals(4, statement.columnRels?.size) Assert.assertTrue(statement.columnRels?.get(0)?.primaryKey!!) Assert.assertEquals(PartitionType.RANGE, statement.partitionType) Assert.assertEquals(1, statement.partitionColumnNames.size) } else { Assert.fail() } } @Test fun createTable1() { val sql = """ CREATE TABLE IF NOT EXISTS sales_range_partitioned3 ( id INT, sales_date DATE, amount DECIMAL(10, 2) ) PARTITION BY RANGE (sales_date) ( PARTITION p2022 VALUES LESS THAN ('2023-01-01'), PARTITION p2023 VALUES LESS THAN ('2024-01-01'), PARTITION p2024 VALUES LESS THAN ('2025-01-01') ); """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals(TableId("sales_range_partitioned3"), statement.tableId) Assert.assertEquals(3, statement.columnRels?.size) Assert.assertEquals(PartitionType.RANGE, statement.partitionType) Assert.assertEquals(1, statement.partitionColumnNames.size) } else { Assert.fail() } } @Test fun createView0() { val sql = """ CREATE OR REPLACE VIEW comedies AS SELECT f.*, country_code_to_name(f.country_code) AS country, (SELECT avg(r.rating) FROM user_ratings r WHERE r.film_id = f.id) AS avg_rating FROM films f WHERE f.kind = 'Comedy' WITH CASCADED CHECK OPTION; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("comedies", statement.tableId.tableName) Assert.assertEquals(2, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun createMatView0() { val sql = """ CREATE MATERIALIZED VIEW sales_summary AS SELECT seller_no, invoice_date, sum(invoice_amt)::numeric(13,2) as sales_amt FROM invoice WHERE invoice_date < CURRENT_DATE GROUP BY seller_no, invoice_date; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateMaterializedView) { Assert.assertEquals(StatementType.CREATE_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals("sales_summary", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun dropMvTest() { val sql = """ DROP MATERIALIZED VIEW tickets_mv; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is DropMaterializedView) { Assert.assertEquals(StatementType.DROP_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) } else { Assert.fail() } } @Test fun refreshMvTest() { val sql = """ REFRESH MATERIALIZED VIEW tickets_mv; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is RefreshMaterializedView) { Assert.assertEquals(StatementType.REFRESH_MV, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) } else { Assert.fail() } } @Test fun renameMvTest() { val sql = """ ALTER MATERIALIZED VIEW tickets_mv RENAME TO tickets_mv_1; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is AlterMaterializedView) { Assert.assertEquals(StatementType.ALTER_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals(TableId("tickets_mv"), statement.tableId) Assert.assertEquals(AlterActionType.RENAME, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun dropTable0() { val sql = """ drop TABLE test.public.authors """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals(TableId("test", "public", "authors"), statement.tableId) } else { Assert.fail() } } @Test fun dropTable1() { val sql = """ drop TABLE authors, tests """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals(TableId("authors"), statement.tableId) Assert.assertEquals(2, statement.tableIds.size) } else { Assert.fail() } } @Test fun createIndexTest() { val sql = "CREATE UNIQUE INDEX title_idx ON films (title) INCLUDE (director, rating);\n" val statement = RedshiftSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("films"), statement.tableId) val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals(AlterActionType.ADD_INDEX, createIndex.alterType) Assert.assertEquals("title_idx", createIndex.indexName) } else { Assert.fail() } } @Test fun dropIndexTest() { val sql = "DROP INDEX title_idx" val statement = RedshiftSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { val dropIndex = statement.firstAction() as DropIndex Assert.assertEquals(AlterActionType.DROP_INDEX, dropIndex.alterType) Assert.assertEquals("title_idx", dropIndex.indexName) } else { Assert.fail() } } @Test fun createPartitonTableTest() { val sql = "create table pkslow_person_r1 partition of pkslow_person_r for values from (MINVALUE) to (10); \n" val statement = RedshiftSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreatePartitionTable) { Assert.assertEquals("pkslow_person_r", statement.tableId.tableName) Assert.assertEquals("pkslow_person_r1", statement.partitionTableId.tableName) } else { Assert.fail() } } @Test fun commentTest0() { val sql = """ COMMENT ON TABLE my_schema.my_table IS 'Employee Information'; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CommentStatement) { Assert.assertEquals(StatementType.COMMENT, statement.statementType) Assert.assertEquals("Employee Information", statement.comment) Assert.assertFalse(statement.isNull) } else { Assert.fail() } } @Test fun alterTableTest() { val sql = """ ALTER TABLE distributors ADD COLUMN address varchar(30), ALTER COLUMN status SET default 'current'; """.trimIndent() val statements = RedshiftSqlHelper.parseMultiStatement(sql) val alterTable1 = statements.get(0) as AlterTable Assert.assertEquals("distributors", alterTable1.tableId.tableName) var action = alterTable1.actions.get(0) as AlterColumnAction Assert.assertEquals(AlterActionType.ADD_COLUMN, action.alterType) Assert.assertEquals("address", action.columName) Assert.assertEquals("varchar(30)", action.dataType) action = alterTable1.actions.get(1) as AlterColumnAction Assert.assertEquals(AlterActionType.SET_COLUMN_DEFAULT, action.alterType) Assert.assertEquals("status", action.columName) Assert.assertEquals("current", action.defaultExpression) } @Test fun showTest() { val sql = """ SHOW COLUMNS FROM TABLE awsdatacatalog.batman.nation LIMIT 2; SHOW SCHEMAS FROM DATABASE awsdatacatalog LIMIT 5; show table sales; SHOW TABLES FROM SCHEMA dev.public; show view LA_Venues_v; """.trimIndent() val statements = RedshiftSqlHelper.parseMultiStatement(sql) Assert.assertEquals(5, statements.size) } } ================================================ FILE: superior-redshift-parser/src/test/java/io/github/melin/superior/parser/postgre/RedshiftSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.table.TruncateTable import org.junit.Assert import org.junit.Test /** * Created by libinsong on 2020/6/30 11:04 上午 */ class RedshiftSqlParserDmlTest { @Test fun queryTest0() { val sql = """ select a.* from datacompute1.datacompute.dc_job a left join datacompute1.datacompute.dc_job_scheduler b on a.id=b.job_id LIMIT 3, 2 """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(3, statement.limit) Assert.assertEquals(2, statement.offset) } else { Assert.fail() } } @Test fun queryTest1() { val sql = """ SELECT * FROM public.usertest LIMIT 3 OFFSET 2; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(3, statement.limit) Assert.assertEquals(2, statement.offset) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun queryTest2() { val sql = """ SELECT * FROM public.usertest FETCH FIRST 5 ROWS ONLY; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(5, statement.limit) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun queryTest3() { val sql = """ SELECT * FROM public.usertest OFFSET 10 FETCH FIRST 10 ROWS ONLY; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(10, statement.limit) Assert.assertEquals(10, statement.offset) Assert.assertEquals(TableId("public", "usertest"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun cteSqlTest0() { val sql = """ WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales) ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("orders"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun createAsQueryTest0() { val sql = """ CREATE TABLE films_recent AS SELECT * FROM films WHERE date_prod >= '2002-01-01'; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("films_recent", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) Assert.assertEquals("films", statement.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun deleteTest0() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest1() { val sql = """ DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo'; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("producers", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest1() { val sql = """ UPDATE product p SET net_price = price - price * discount FROM product_segment s WHERE p.segment_id = s.id; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("product", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("product_segment", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun insertTest0() { val sql = """ INSERT INTO films (code, title, did, date_prod, kind) VALUES ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy'); """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(0, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest1() { val sql = """ WITH upd AS ( UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation') RETURNING * ) INSERT INTO employees_log SELECT *, current_timestamp FROM upd; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("employees_log", statement.tableId?.tableName) Assert.assertEquals(2, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest2() { val sql = """ truncate table films INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07'; """.trimIndent() val statements = RedshiftSqlHelper.parseMultiStatement(sql) var statement = statements.get(0) if (statement is TruncateTable) { Assert.assertEquals(StatementType.TRUNCATE_TABLE, statement.statementType) Assert.assertEquals("films", statement.tableId.tableName) } else { Assert.fail() } statement = statements.get(1) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.outputTables.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest() { val sql = """ MERGE INTO wines w USING wine_stock_changes s ON s.winename = w.winename WHEN NOT MATCHED AND s.stock_delta > 0 THEN INSERT VALUES(s.winename, s.stock_delta) WHEN MATCHED AND w.stock + s.stock_delta > 0 THEN UPDATE SET stock = w.stock + s.stock_delta WHEN MATCHED THEN DELETE; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("wines", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-redshift-parser/src/test/java/io/github/melin/superior/parser/postgre/RedshiftSqlProcessParserTest.kt ================================================ package io.github.melin.superior.parser.postgre import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.ProcedureId import io.github.melin.superior.common.relational.create.CreateFunction import io.github.melin.superior.common.relational.create.CreateProcedure import org.junit.Assert import org.junit.Test class RedshiftSqlProcessParserTest { @Test fun createFunctionTest() { val sql = """ CREATE FUNCTION public.myadd(integer, integer) RETURNS integer AS 'select ${'$'}1 + ${'$'}2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("public", "myadd"), statement.functionId) Assert.assertEquals("myadd", statement.functionId.functionName) } else { Assert.fail() } } @Test fun createFunctionTest1() { val sql = """ CREATE FUNCTION myadd(integer, integer) RETURNS integer AS 'select ${'$'}1 + ${'$'}2;' LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("myadd"), statement.functionId) Assert.assertEquals("myadd", statement.functionId.functionName) } else { Assert.fail() } } @Test fun createFunctionTest2() { val sql = """ CREATE FUNCTION check_password(uname TEXT, pass TEXT) RETURNS BOOLEAN AS ${'$'}${'$'} DECLARE passed BOOLEAN; BEGIN SELECT (pwd = ${'$'}2) INTO passed FROM pwds WHERE username = ${'$'}1; RETURN passed; END; ${'$'}${'$'} LANGUAGE plpgsql SECURITY DEFINER """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(StatementType.CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId( "check_password"), statement.functionId) Assert.assertEquals(1, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest3() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) LANGUAGE plpgsql as ${'$'}${'$'} BEGIN update accounts_1 set balance = balance - amount where id = sender; update accounts_2 set balance = balance + amount where id = receiver; commit; END;${'$'}${'$'}; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } @Test fun createFunctionTest4() { val sql = """ create or replace procedure prac_transfer( sender int, receiver int, amount dec ) LANGUAGE plpgsql as ${'$'}${'$'} BEGIN update accounts set balance = balance - amount where id = sender; update accounts set balance = balance + amount where id = receiver; commit; END;${'$'}${'$'}; """.trimIndent() val statement = RedshiftSqlHelper.parseStatement(sql) if (statement is CreateProcedure) { Assert.assertEquals(StatementType.CREATE_PROCEDURE, statement.statementType) Assert.assertEquals(ProcedureId( "prac_transfer"), statement.procedureId) Assert.assertEquals(2, statement.childStatements.size) } else { Assert.fail() } } } ================================================ FILE: superior-redshift-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-spark-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-spark-parser superior-spark-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-spark-parser/src/main/antlr4/io/github/melin/superior/parser/spark/antlr4/SparkSqlLexer.g4 ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is an adaptation of Presto's presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 grammar. */ lexer grammar SparkSqlLexer; @members { /** * When true, parser should throw ParseException for unclosed bracketed comment. */ public boolean has_unclosed_bracketed_comment = false; /** * Verify whether current token is a valid decimal token (which contains dot). * Returns true if the character that follows the token is not a digit or letter or underscore. * * For example: * For char stream "2.3", "2." is not a valid decimal token, because it is followed by digit '3'. * For char stream "2.3_", "2.3" is not a valid decimal token, because it is followed by '_'. * For char stream "2.3W", "2.3" is not a valid decimal token, because it is followed by 'W'. * For char stream "12.0D 34.E2+0.12 " 12.0D is a valid decimal token because it is followed * by a space. 34.E2 is a valid decimal token because it is followed by symbol '+' * which is not a digit or letter or underscore. */ public boolean isValidDecimal() { int nextChar = _input.LA(1); if (nextChar >= 'A' && nextChar <= 'Z' || nextChar >= '0' && nextChar <= '9' || nextChar == '_') { return false; } else { return true; } } /** * This method will be called when we see '/*' and try to match it as a bracketed comment. * If the next character is '+', it should be parsed as hint later, and we cannot match * it as a bracketed comment. * * Returns true if the next character is '+'. */ public boolean isHint() { int nextChar = _input.LA(1); if (nextChar == '+') { return true; } else { return false; } } /** * This method will be called when the character stream ends and try to find out the * unclosed bracketed comment. * If the method be called, it means the end of the entire character stream match, * and we set the flag and fail later. */ public void markUnclosedComment() { has_unclosed_bracketed_comment = true; } } SEMICOLON: ';'; LEFT_PAREN: '('; RIGHT_PAREN: ')'; COMMA: ','; DOT: '.'; LEFT_BRACKET: '['; RIGHT_BRACKET: ']'; LEFT_BRACE: '{'; RIGHT_BRACE: '}'; // NOTE: If you add a new token in the list below, you should update the list of keywords // and reserved tag in `docs/sql-ref-ansi-compliance.md#sql-keywords`, and // modify `ParserUtils.toExprAlias()` which assumes all keywords are between `ADD` and `ZONE`. //============================ // Start of the keywords list //============================ //--SPARK-KEYWORD-LIST-START ADD: 'ADD'; AFTER: 'AFTER'; ALL: 'ALL'; ALTER: 'ALTER'; ALWAYS: 'ALWAYS'; ANALYZE: 'ANALYZE'; AND: 'AND'; ANTI: 'ANTI'; ANY: 'ANY'; ANY_VALUE: 'ANY_VALUE'; ARCHIVE: 'ARCHIVE'; ARRAY: 'ARRAY'; AS: 'AS'; ASC: 'ASC'; AT: 'AT'; AUTHORIZATION: 'AUTHORIZATION'; BETWEEN: 'BETWEEN'; BIGINT: 'BIGINT'; BINARY: 'BINARY'; BOOLEAN: 'BOOLEAN'; BOTH: 'BOTH'; BRANCH: 'BRANCH'; BUCKET: 'BUCKET'; BUCKETS: 'BUCKETS'; BY: 'BY'; BYTE: 'BYTE'; CACHE: 'CACHE'; CALL: 'CALL'; CASCADE: 'CASCADE'; CASE: 'CASE'; CAST: 'CAST'; CATALOG: 'CATALOG'; CATALOGS: 'CATALOGS'; CHANGE: 'CHANGE'; CHAR: 'CHAR'; CHARACTER: 'CHARACTER'; CHECK: 'CHECK'; CLEAR: 'CLEAR'; CLUSTER: 'CLUSTER'; CLUSTERED: 'CLUSTERED'; CODEGEN: 'CODEGEN'; COLLATE: 'COLLATE'; COLLECTION: 'COLLECTION'; COLUMN: 'COLUMN'; COLUMNS: 'COLUMNS'; COMMENT: 'COMMENT'; COMMIT: 'COMMIT'; COMPACT: 'COMPACT'; COMPACTIONS: 'COMPACTIONS'; COMPRESSION: 'COMPRESSION'; COMPUTE: 'COMPUTE'; CONCATENATE: 'CONCATENATE'; CONSTRAINT: 'CONSTRAINT'; COST: 'COST'; CREATE: 'CREATE'; CROSS: 'CROSS'; CUBE: 'CUBE'; CURRENT: 'CURRENT'; CURRENT_DATE: 'CURRENT_DATE'; CURRENT_TIME: 'CURRENT_TIME'; CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'; CURRENT_USER: 'CURRENT_USER'; DAY: 'DAY'; DAYS: 'DAYS'; DAYOFYEAR: 'DAYOFYEAR'; DATA: 'DATA'; DATE: 'DATE'; DATABASE: 'DATABASE'; DATABASES: 'DATABASES'; DATATUNNEL: 'DATATUNNEL'; DATEADD: 'DATEADD'; DATE_ADD: 'DATE_ADD'; DATEDIFF: 'DATEDIFF'; DATE_DIFF: 'DATE_DIFF'; DBPROPERTIES: 'DBPROPERTIES'; DEC: 'DEC'; DECIMAL: 'DECIMAL'; DEFAULT: 'DEFAULT'; DEFINED: 'DEFINED'; DELETE: 'DELETE'; DELIMITED: 'DELIMITED'; DESC: 'DESC'; DESCRIBE: 'DESCRIBE'; DFS: 'DFS'; DIRECTORIES: 'DIRECTORIES'; DIRECTORY: 'DIRECTORY'; DISTCP: 'DISTCP'; DISTINCT: 'DISTINCT'; DISTRIBUTE: 'DISTRIBUTE'; DISTRIBUTED: 'DISTRIBUTED'; DIV: 'DIV'; DOUBLE: 'DOUBLE'; DROP: 'DROP'; ELSE: 'ELSE'; END: 'END'; ESCAPE: 'ESCAPE'; ESCAPED: 'ESCAPED'; EXCEPT: 'EXCEPT'; EXCHANGE: 'EXCHANGE'; EXCLUDE: 'EXCLUDE'; EXISTS: 'EXISTS'; EXPLAIN: 'EXPLAIN'; EXPORT: 'EXPORT'; EXTENDED: 'EXTENDED'; EXTERNAL: 'EXTERNAL'; EXTRACT: 'EXTRACT'; FALSE: 'FALSE'; FETCH: 'FETCH'; FIELD: 'FIELD'; FIELDS: 'FIELDS'; FILTER: 'FILTER'; FILE: 'FILE'; FILEFORMAT: 'FILEFORMAT'; FIRST: 'FIRST'; FLOAT: 'FLOAT'; FOLLOWING: 'FOLLOWING'; FOR: 'FOR'; FOREIGN: 'FOREIGN'; FORMAT: 'FORMAT'; FORMATTED: 'FORMATTED'; FROM: 'FROM'; FULL: 'FULL'; FUNCTION: 'FUNCTION'; FUNCTIONS: 'FUNCTIONS'; GENERATED: 'GENERATED'; GLOBAL: 'GLOBAL'; GRANT: 'GRANT'; GROUP: 'GROUP'; GROUPING: 'GROUPING'; HAVING: 'HAVING'; BINARY_HEX: 'X'; HELP: 'HELP'; HOUR: 'HOUR'; HOURS: 'HOURS'; IDENTIFIER_KW: 'IDENTIFIER'; IF: 'IF'; IGNORE: 'IGNORE'; IMPORT: 'IMPORT'; IN: 'IN'; INCLUDE: 'INCLUDE'; INDEX: 'INDEX'; INDEXES: 'INDEXES'; INNER: 'INNER'; INPATH: 'INPATH'; INPUTFORMAT: 'INPUTFORMAT'; INSERT: 'INSERT'; INTERSECT: 'INTERSECT'; INTERVAL: 'INTERVAL'; INT: 'INT'; INTEGER: 'INTEGER'; INTO: 'INTO'; IS: 'IS'; ITEMS: 'ITEMS'; JOIN: 'JOIN'; KEYS: 'KEYS'; LAST: 'LAST'; LATERAL: 'LATERAL'; LAZY: 'LAZY'; LEADING: 'LEADING'; LEFT: 'LEFT'; LIKE: 'LIKE'; LIFECYCLE: 'LIFECYCLE'; ILIKE: 'ILIKE'; LIMIT: 'LIMIT'; LINES: 'LINES'; LIST: 'LIST'; LOAD: 'LOAD'; LOCAL: 'LOCAL'; LOCATION: 'LOCATION'; LOCK: 'LOCK'; LOCKS: 'LOCKS'; LOGICAL: 'LOGICAL'; LONG: 'LONG'; LOCALLY: 'LOCALLY'; MACRO: 'MACRO'; MAP: 'MAP'; MATCHED: 'MATCHED'; MAX_FILE_SIZE: 'MAX_FILE_SIZE'; MERGE: 'MERGE'; MICROSECOND: 'MICROSECOND'; MICROSECONDS: 'MICROSECONDS'; MILLISECOND: 'MILLISECOND'; MILLISECONDS: 'MILLISECONDS'; MINUTE: 'MINUTE'; MINUTES: 'MINUTES'; MONTH: 'MONTH'; MONTHS: 'MONTHS'; MSCK: 'MSCK'; NAME: 'NAME'; NAMESPACE: 'NAMESPACE'; NAMESPACES: 'NAMESPACES'; NANOSECOND: 'NANOSECOND'; NANOSECONDS: 'NANOSECONDS'; NATURAL: 'NATURAL'; NO: 'NO'; NOT: 'NOT' | '!'; NULL: 'NULL'; NULLS: 'NULLS'; NUMERIC: 'NUMERIC'; OF: 'OF'; OFFSET: 'OFFSET'; ON: 'ON'; ONLY: 'ONLY'; OPTION: 'OPTION'; OPTIONS: 'OPTIONS'; OR: 'OR'; ORDER: 'ORDER'; ORDERED: 'ORDERED'; OUT: 'OUT'; OUTER: 'OUTER'; OUTPUTFORMAT: 'OUTPUTFORMAT'; OVER: 'OVER'; OVERLAPS: 'OVERLAPS'; OVERLAY: 'OVERLAY'; OVERWRITE: 'OVERWRITE'; OWNER: 'OWNER'; PARTITION: 'PARTITION'; PARTITIONED: 'PARTITIONED'; PARTITIONS: 'PARTITIONS'; PERCENTILE_CONT: 'PERCENTILE_CONT'; PERCENTILE_DISC: 'PERCENTILE_DISC'; PERCENTLIT: 'PERCENT'; PIVOT: 'PIVOT'; PLACING: 'PLACING'; POSITION: 'POSITION'; PRECEDING: 'PRECEDING'; PRIMARY: 'PRIMARY'; PRINCIPALS: 'PRINCIPALS'; PROPERTIES: 'PROPERTIES'; PURGE: 'PURGE'; QUARTER: 'QUARTER'; QUERY: 'QUERY'; RANGE: 'RANGE'; REAL: 'REAL'; RECORDREADER: 'RECORDREADER'; RECORDWRITER: 'RECORDWRITER'; RECOVER: 'RECOVER'; REDUCE: 'REDUCE'; REFERENCES: 'REFERENCES'; REFRESH: 'REFRESH'; RENAME: 'RENAME'; REPAIR: 'REPAIR'; REPEATABLE: 'REPEATABLE'; REPLACE: 'REPLACE'; RESET: 'RESET'; RESPECT: 'RESPECT'; RESTRICT: 'RESTRICT'; RETAIN: 'RETAIN'; RETENTION: 'RETENTION'; REVOKE: 'REVOKE'; RIGHT: 'RIGHT'; RLIKE: 'RLIKE' | 'REGEXP'; ROLE: 'ROLE'; ROLES: 'ROLES'; ROLLBACK: 'ROLLBACK'; ROLLUP: 'ROLLUP'; ROW: 'ROW'; ROWS: 'ROWS'; SNAPSHOT: 'SNAPSHOT'; SNAPSHOTS: 'SNAPSHOTS'; SECOND: 'SECOND'; SECONDS: 'SECONDS'; SCHEMA: 'SCHEMA'; SCHEMAS: 'SCHEMAS'; SELECT: 'SELECT'; SEMI: 'SEMI'; SEPARATED: 'SEPARATED'; SERDE: 'SERDE'; SERDEPROPERTIES: 'SERDEPROPERTIES'; SESSION_USER: 'SESSION_USER'; SET: 'SET'; SETMINUS: 'MINUS'; SETS: 'SETS'; SHORT: 'SHORT'; SHOW: 'SHOW'; SIZE_LIMIT: 'SIZE_LIMIT'; SINGLE: 'SINGLE'; SINK: 'SINK'; SKEWED: 'SKEWED'; SMALLINT: 'SMALLINT'; SOME: 'SOME'; SORT: 'SORT'; SORTED: 'SORTED'; SOURCE: 'SOURCE'; START: 'START'; STATISTICS: 'STATISTICS'; STORED: 'STORED'; STRATIFY: 'STRATIFY'; STRING: 'STRING'; STRUCT: 'STRUCT'; SUBSTR: 'SUBSTR'; SUBSTRING: 'SUBSTRING'; SYNC: 'SYNC'; SYSTEM_TIME: 'SYSTEM_TIME'; SYSTEM_VERSION: 'SYSTEM_VERSION'; TABLE: 'TABLE'; TABLES: 'TABLES'; TABLESAMPLE: 'TABLESAMPLE'; TAG: 'TAG'; TARGET: 'TARGET'; TBLPROPERTIES: 'TBLPROPERTIES'; TEMPORARY: 'TEMPORARY' | 'TEMP'; TERMINATED: 'TERMINATED'; THEN: 'THEN'; TIME: 'TIME'; TIMESTAMP: 'TIMESTAMP'; TIMESTAMP_LTZ: 'TIMESTAMP_LTZ'; TIMESTAMP_NTZ: 'TIMESTAMP_NTZ'; TIMESTAMPADD: 'TIMESTAMPADD'; TIMESTAMPDIFF: 'TIMESTAMPDIFF'; TINYINT: 'TINYINT'; TO: 'TO'; TOUCH: 'TOUCH'; TRAILING: 'TRAILING'; TRANSACTION: 'TRANSACTION'; TRANSACTIONS: 'TRANSACTIONS'; TRANSFORM: 'TRANSFORM'; TRIM: 'TRIM'; TRUE: 'TRUE'; TRUNCATE: 'TRUNCATE'; TRY_CAST: 'TRY_CAST'; TYPE: 'TYPE'; UNARCHIVE: 'UNARCHIVE'; UNBOUNDED: 'UNBOUNDED'; UNCACHE: 'UNCACHE'; UNION: 'UNION'; UNIQUE: 'UNIQUE'; UNKNOWN: 'UNKNOWN'; UNLOCK: 'UNLOCK'; UNPIVOT: 'UNPIVOT'; UNSET: 'UNSET'; UPDATE: 'UPDATE'; UNORDERED: 'UNORDERED'; USE: 'USE'; USER: 'USER'; USING: 'USING'; VALUES: 'VALUES'; VARCHAR: 'VARCHAR'; VERSION: 'VERSION'; VIEW: 'VIEW'; VIEWS: 'VIEWS'; VOID: 'VOID'; WEEK: 'WEEK'; WEEKS: 'WEEKS'; WHEN: 'WHEN'; WHERE: 'WHERE'; WINDOW: 'WINDOW'; WITH: 'WITH'; WITHIN: 'WITHIN'; WRITE: 'WRITE'; YEAR: 'YEAR'; YEARS: 'YEARS'; ZONE: 'ZONE'; // delta VACUUM: 'VACUUM'; INVENTORY: 'INVENTORY'; DRY: 'DRY'; RUN: 'RUN'; OPTIMIZE: 'OPTIMIZE'; ZORDER: 'ZORDER'; DETAIL: 'DETAIL'; HISTORY: 'HISTORY'; FEATURE: 'FEATURE'; NONE: 'NONE'; IDENTITY: 'IDENTITY'; INCLUDING: 'INCLUDING'; EXCLUDING: 'EXCLUDING'; //--SPARK-KEYWORD-LIST-END //============================ // End of the keywords list //============================ EQ : '=' | '=='; NSEQ: '<=>'; NEQ : '<>'; NEQJ: '!='; LT : '<'; LTE : '<=' | '!>'; GT : '>'; GTE : '>=' | '!<'; PLUS: '+'; MINUS: '-'; ASTERISK: '*'; SLASH: '/'; PERCENT: '%'; TILDE: '~'; AMPERSAND: '&'; PIPE: '|'; CONCAT_PIPE: '||'; HAT: '^'; COLON: ':'; ARROW: '->'; FAT_ARROW : '=>'; HENT_START: '/*+'; HENT_END: '*/'; QUESTION: '?'; STRING_LITERAL : '\'' ( ~('\''|'\\') | ('\\' .) )* '\'' | 'R\'' (~'\'')* '\'' | 'R"'(~'"')* '"' ; DOUBLEQUOTED_STRING :'"' ( ~('"'|'\\') | ('\\' .) )* '"' ; // NOTE: If you move a numeric literal, you should modify `ParserUtils.toExprAlias()` // which assumes all numeric literals are between `BIGINT_LITERAL` and `BIGDECIMAL_LITERAL`. BIGINT_LITERAL : DIGIT+ 'L' ; SMALLINT_LITERAL : DIGIT+ 'S' ; TINYINT_LITERAL : DIGIT+ 'Y' ; INTEGER_VALUE : DIGIT+ ; EXPONENT_VALUE : DIGIT+ EXPONENT | DECIMAL_DIGITS EXPONENT {isValidDecimal()}? ; DECIMAL_VALUE : DECIMAL_DIGITS {isValidDecimal()}? ; FLOAT_LITERAL : DIGIT+ EXPONENT? 'F' | DECIMAL_DIGITS EXPONENT? 'F' {isValidDecimal()}? ; DOUBLE_LITERAL : DIGIT+ EXPONENT? 'D' | DECIMAL_DIGITS EXPONENT? 'D' {isValidDecimal()}? ; BIGDECIMAL_LITERAL : DIGIT+ EXPONENT? 'BD' | DECIMAL_DIGITS EXPONENT? 'BD' {isValidDecimal()}? ; IDENTIFIER : (LETTER | DIGIT | '_')+ ; BACKQUOTED_IDENTIFIER : '`' ( ~'`' | '``' )* '`' ; fragment DECIMAL_DIGITS : DIGIT+ '.' DIGIT* | '.' DIGIT+ ; fragment EXPONENT : 'E' [+-]? DIGIT+ ; fragment DIGIT : [0-9] ; fragment LETTER : [A-Z] ; SIMPLE_COMMENT : '--' ('\\\n' | ~[\r\n])* '\r'? '\n'? -> channel(HIDDEN) ; BRACKETED_COMMENT : '/*' {!isHint()}? ( BRACKETED_COMMENT | . )*? ('*/' | {markUnclosedComment();} EOF) -> channel(HIDDEN) ; WS : [ \r\n\t]+ -> channel(HIDDEN) ; // Catch-all for anything we can't recognize. // We use this to be able to ignore and recover all the text // when splitting statements with DelimiterLexer UNRECOGNIZED : . ; ================================================ FILE: superior-spark-parser/src/main/antlr4/io/github/melin/superior/parser/spark/antlr4/SparkSqlParser.g4 ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is an adaptation of Presto's presto-parser/src/main/antlr4/com/facebook/presto/sql/parser/SqlBase.g4 grammar. */ parser grammar SparkSqlParser; options { tokenVocab = SparkSqlLexer; } @members { /** * When false, INTERSECT is given the greater precedence over the other set * operations (UNION, EXCEPT and MINUS) as per the SQL standard. */ public boolean legacy_setops_precedence_enabled = false; /** * When false, a literal with an exponent would be converted into * double type rather than decimal type. */ public boolean legacy_exponent_literal_as_decimal_enabled = false; /** * When true, the behavior of keywords follows ANSI SQL standard. */ public boolean SQL_standard_keyword_behavior = false; /** * When true, double quoted literals are identifiers rather than STRINGs. */ public boolean double_quoted_identifiers = false; } sqlStatements : singleStatement* EOF ; singleStatement : statement SEMICOLON? ; singleExpression : namedExpression EOF ; singleTableIdentifier : tableIdentifier EOF ; singleMultipartIdentifier : multipartIdentifier EOF ; singleFunctionIdentifier : functionIdentifier EOF ; singleDataType : dataType EOF ; singleTableSchema : colTypeList EOF ; statement : query #statementDefault | ctes? dmlStatementNoWith #dmlStatement | USE identifierReference #use | USE namespace identifierReference #useNamespace | SET CATALOG (identifier | stringLit) #setCatalog | CREATE namespace (IF NOT EXISTS)? identifierReference (commentSpec | locationSpec | (WITH (DBPROPERTIES | PROPERTIES) propertyList))* #createNamespace | ALTER namespace identifierReference SET (DBPROPERTIES | PROPERTIES) propertyList #setNamespaceProperties | ALTER namespace identifierReference SET locationSpec #setNamespaceLocation | DROP namespace (IF EXISTS)? identifierReference (RESTRICT | CASCADE)? #dropNamespace | SHOW namespaces ((FROM | IN) multipartIdentifier)? (LIKE? pattern=stringLit)? #showNamespaces | createTableHeader (LEFT_PAREN createOrReplaceTableColTypeList RIGHT_PAREN)? tableProvider? createTableClauses (AS? query)? #createTable | CREATE TABLE (IF NOT EXISTS)? target=tableIdentifier LIKE source=tableIdentifier (tableProvider | rowFormat | createFileFormat | locationSpec | (LIFECYCLE lifecycle=INTEGER_VALUE) | (TBLPROPERTIES tableProps=propertyList))* #createTableLike | replaceTableHeader (LEFT_PAREN createOrReplaceTableColTypeList RIGHT_PAREN)? tableProvider? createTableClauses (AS? query)? #replaceTable | ANALYZE TABLE identifierReference partitionSpec? COMPUTE STATISTICS (identifier | FOR COLUMNS identifierSeq | FOR ALL COLUMNS)? #analyze | ANALYZE TABLES ((FROM | IN) identifierReference)? COMPUTE STATISTICS (identifier)? #analyzeTables | ALTER TABLE identifierReference ADD (COLUMN | COLUMNS) columns=qualifiedColTypeWithPositionList #addTableColumns | ALTER TABLE identifierReference ADD (COLUMN | COLUMNS) LEFT_PAREN columns=qualifiedColTypeWithPositionList RIGHT_PAREN #addTableColumns | ALTER TABLE table=identifierReference RENAME COLUMN from=multipartIdentifier TO to=errorCapturingIdentifier #renameTableColumn | ALTER TABLE identifierReference DROP (COLUMN | COLUMNS) (IF EXISTS)? LEFT_PAREN columns=multipartIdentifierList RIGHT_PAREN #dropTableColumns | ALTER TABLE identifierReference DROP (COLUMN | COLUMNS) (IF EXISTS)? columns=multipartIdentifierList #dropTableColumns | ALTER (TABLE | VIEW) from=identifierReference RENAME TO to=multipartIdentifier #renameTable | ALTER (TABLE | VIEW) identifierReference SET TBLPROPERTIES propertyList #setTableProperties | ALTER (TABLE | VIEW) identifierReference UNSET TBLPROPERTIES (IF EXISTS)? propertyList #unsetTableProperties | ALTER TABLE table=identifierReference (ALTER | CHANGE) COLUMN? column=multipartIdentifier alterColumnAction? #alterTableAlterColumn | ALTER TABLE table=identifierReference partitionSpec? CHANGE COLUMN? colName=multipartIdentifier colType colPosition? #hiveChangeColumn | ALTER TABLE table=identifierReference partitionSpec? REPLACE COLUMNS LEFT_PAREN columns=qualifiedColTypeWithPositionList RIGHT_PAREN #hiveReplaceColumns | ALTER TABLE identifierReference (partitionSpec)? SET SERDE stringLit (WITH SERDEPROPERTIES propertyList)? #setTableSerDe | ALTER TABLE identifierReference (partitionSpec)? SET SERDEPROPERTIES propertyList #setTableSerDe | ALTER (TABLE | VIEW) identifierReference ADD (IF NOT EXISTS)? partitionSpecLocation+ #addTablePartition | ALTER TABLE identifierReference from=partitionSpec RENAME TO to=partitionSpec #renameTablePartition | ALTER TABLE table=identifierReference TOUCH partitionSpec? #touchTable | ALTER (TABLE | VIEW) identifierReference DROP (IF EXISTS)? dropPartitionSpec (',' dropPartitionSpec)* PURGE? #dropTablePartitions | ALTER TABLE identifierReference (partitionSpec)? SET locationSpec #setTableLocation | ALTER TABLE identifierReference RECOVER PARTITIONS #recoverPartitions | DROP TABLE (IF EXISTS)? identifierReference PURGE? #dropTable | DROP VIEW (IF EXISTS)? identifierReference #dropView | CREATE (OR REPLACE)? (GLOBAL? TEMPORARY)? VIEW (IF NOT EXISTS)? identifierReference identifierCommentList? (commentSpec | (PARTITIONED ON identifierList) | (TBLPROPERTIES propertyList))* AS query #createView | CREATE (OR REPLACE)? GLOBAL? TEMPORARY VIEW tableIdentifier (LEFT_PAREN colTypeList RIGHT_PAREN)? tableProvider (OPTIONS propertyList)? #createTempViewUsing | ALTER VIEW identifierReference AS? query #alterViewQuery | CREATE (OR REPLACE)? TEMPORARY? FUNCTION (IF NOT EXISTS)? identifierReference AS className=stringLit (USING resource (COMMA resource)*)? #createFunction | DROP TEMPORARY? FUNCTION (IF EXISTS)? identifierReference #dropFunction | EXPLAIN (LOGICAL | FORMATTED | EXTENDED | CODEGEN | COST)? statement #explain | SHOW TABLES ((FROM | IN) identifierReference)? (LIKE? pattern=stringLit)? #showTables | SHOW TABLE EXTENDED ((FROM | IN) ns=identifierReference)? LIKE pattern=stringLit partitionSpec? #showTableExtended | SHOW TBLPROPERTIES table=identifierReference (LEFT_PAREN key=propertyKey RIGHT_PAREN)? #showTblProperties | SHOW COLUMNS (FROM | IN) table=identifierReference ((FROM | IN) ns=multipartIdentifier)? #showColumns | SHOW VIEWS ((FROM | IN) identifierReference)? (LIKE? pattern=stringLit)? #showViews | SHOW PARTITIONS identifierReference partitionSpec? #showPartitions | SHOW identifier? FUNCTIONS ((FROM | IN) ns=identifierReference)? (LIKE? (legacy=multipartIdentifier | pattern=stringLit))? #showFunctions | SHOW CREATE TABLE identifierReference (AS SERDE)? #showCreateTable | SHOW CURRENT namespace #showCurrentNamespace | SHOW CATALOGS (LIKE? pattern=stringLit)? #showCatalogs | (DESC | DESCRIBE) FUNCTION EXTENDED? describeFuncName #describeFunction | (DESC | DESCRIBE) namespace EXTENDED? identifierReference #describeNamespace | (DESC | DESCRIBE) DETAIL multipartIdentifier #describeDeltaDetail | (DESC | DESCRIBE) HISTORY multipartIdentifier (LIMIT limit=INTEGER_VALUE)? #describeDeltaHistory | (DESC | DESCRIBE) TABLE? option=(EXTENDED | FORMATTED)? identifierReference partitionSpec? describeColName? #describeRelation | (DESC | DESCRIBE) QUERY? query #describeQuery | COMMENT ON namespace identifierReference IS comment #commentNamespace | COMMENT ON TABLE identifierReference IS comment #commentTable | REFRESH TABLE identifierReference #refreshTable | REFRESH FUNCTION identifierReference #refreshFunction | REFRESH (stringLit | .*?) #refreshResource | CACHE LAZY? TABLE identifierReference (OPTIONS options=propertyList)? (AS? query)? #cacheTable | UNCACHE TABLE (IF EXISTS)? identifierReference #uncacheTable | CLEAR CACHE #clearCache | LOAD DATA LOCAL? INPATH path=stringLit OVERWRITE? INTO TABLE identifierReference partitionSpec? #loadData | TRUNCATE TABLE identifierReference partitionSpec? #truncateTable | (MSCK)? REPAIR TABLE identifierReference (option=(ADD|DROP|SYNC) PARTITIONS)? #repairTable | op=(ADD | LIST) identifier .*? #manageResource | SET ROLE setKey #failNativeCommand | SET TIME ZONE interval #setTimeZone | SET TIME ZONE timezone #setTimeZone | SET TIME ZONE setKey #setTimeZone | SET setKey EQ configValue #setQuotedConfiguration | SET setKey #setConfiguration | RESET setKey #resetConfiguration | CREATE INDEX (IF NOT EXISTS)? identifier ON TABLE? identifierReference (USING indexType=identifier)? LEFT_PAREN columns=multipartIdentifierPropertyList RIGHT_PAREN (OPTIONS options=propertyList)? #createIndex | DROP INDEX (IF EXISTS)? identifier ON TABLE? identifierReference #dropIndex | MERGE TABLE multipartIdentifier partitionSpec? (OPTIONS options=propertyList)? #mergeFile | CREATE TEMPORARY? VIEW multipartIdentifier tableProvider FILE path=stringLit (OPTIONS options=propertyList)? createFileViewClauses #createFileView | ctes? EXPORT TABLE multipartIdentifier partitionSpec? TO filePath=stringLit (OPTIONS options=propertyList)? exportTableClauses #exportTable | ctes? DATATUNNEL SOURCE LEFT_PAREN sourceName=stringLit RIGHT_PAREN OPTIONS sourceOpts=dtPropertyList (TRANSFORM EQ transfromSql=stringLit)? SINK LEFT_PAREN sinkName=stringLit RIGHT_PAREN (OPTIONS sinkOpts=dtPropertyList)? (PROPERTIES properties=dtPropertyList)? #datatunnelExpr | DISTCP OPTIONS options=dtPropertyList (PROPERTIES properties=dtPropertyList)? #distCpExpr | DATATUNNEL HELP dtType=(SOURCE | SINK | ALL) LEFT_PAREN value=stringLit RIGHT_PAREN #datatunnelHelp | CALL HELP callHelpExpr? #callHelp | CALL multipartIdentifier LEFT_PAREN callArgument (COMMA callArgument)* RIGHT_PAREN #call | SYNC dtType=(DATABASE|TABLE) FROM source=multipartIdentifier (SET OWNER principal=identifier)? #syncTableMeta // iceberg sql extensions | ALTER TABLE multipartIdentifier ADD PARTITION FIELD transform (AS name=identifier)? #addPartitionField | ALTER TABLE multipartIdentifier DROP PARTITION FIELD transform #dropPartitionField | ALTER TABLE multipartIdentifier REPLACE PARTITION FIELD transform WITH transform (AS name=identifier)? #replacePartitionField | ALTER TABLE multipartIdentifier WRITE writeSpec #setWriteDistributionAndOrdering | ALTER TABLE multipartIdentifier SET IDENTIFIER_KW FIELDS fieldList #setIdentifierFields | ALTER TABLE multipartIdentifier DROP IDENTIFIER_KW FIELDS fieldList #dropIdentifierFields | ALTER TABLE multipartIdentifier createReplaceBranchClause #createOrReplaceBranch | ALTER TABLE multipartIdentifier createReplaceTagClause #createOrReplaceTag | ALTER TABLE multipartIdentifier DROP BRANCH (IF EXISTS)? identifier #dropBranch | ALTER TABLE multipartIdentifier DROP TAG (IF EXISTS)? identifier #dropTag // delta sql extensions | VACUUM table=multipartIdentifier (USING INVENTORY (inventoryTable=multipartIdentifier | LEFT_PAREN inventoryQuery=query RIGHT_PAREN))? (RETAIN number HOURS)? (DRY RUN)? #vacuumTable | ALTER TABLE multipartIdentifier ADD CONSTRAINT name=identifier constraint #addTableConstraint | ALTER TABLE multipartIdentifier DROP CONSTRAINT (IF EXISTS)? name=identifier #dropTableConstraint | ALTER TABLE multipartIdentifier DROP FEATURE featureName=featureNameValue (TRUNCATE HISTORY)? #alterTableDropFeature | ALTER TABLE multipartIdentifier (clusterBySpec | CLUSTER BY NONE) #alterTableClusterBy | ALTER TABLE table=multipartIdentifier (ALTER | CHANGE) COLUMN? column=multipartIdentifier SYNC IDENTITY #alterTableSyncIdentity | OPTIMIZE multipartIdentifier whereClause? (zorderSpec)? #optimizeTable | unsupportedHiveNativeCommands .*? #failNativeCommand ; setKey : (identifier | DECIMAL_VALUE | '.' | MINUS)+ | DOUBLEQUOTED_STRING ; timezone : stringLit | LOCAL ; configKey : quotedIdentifier ; configValue : number | (identifier | '.' | MINUS)+ | booleanValue | DOUBLEQUOTED_STRING ; callArgument : expression | identifier FAT_ARROW expression ; callHelpExpr : LEFT_PAREN callArgument RIGHT_PAREN | identifier ; dtPropertyList : LEFT_PAREN dtProperty (COMMA dtProperty)* RIGHT_PAREN ; columnDef : LEFT_BRACE dtColProperty (COMMA dtColProperty)* RIGHT_BRACE ; dtProperty : key=dtPropertyKey (EQ? value=dtPropertyValue)? ; dtColProperty : key=dtPropertyKey (COLON? value=dtPropertyValue)? ; dtPropertyKey : identifier (DOT identifier)* | DOUBLEQUOTED_STRING | stringLit ; dtPropertyValue : INTEGER_VALUE | DECIMAL_VALUE | booleanValue | DOUBLEQUOTED_STRING | stringLit | LEFT_BRACKET dtPropertyValue (',' dtPropertyValue)* RIGHT_BRACKET | LEFT_BRACKET columnDef (COMMA columnDef)* RIGHT_BRACKET ; createFileViewClauses : ((COMPRESSION compressionName = identifier) | (SIZE_LIMIT sizelimit = identifier))* ; exportTableClauses : ((FORMAT fileformatName = identifier) | (COMPRESSION compressionName = identifier) | (OVERWRITE overwrite = booleanValue) | (MAX_FILE_SIZE maxfilesize = identifier) | (SINGLE single = booleanValue))* ; createReplaceTagClause : (CREATE OR)? REPLACE TAG identifier tagOptions | CREATE TAG (IF NOT EXISTS)? identifier tagOptions ; createReplaceBranchClause : (CREATE OR)? REPLACE BRANCH identifier branchOptions | CREATE BRANCH (IF NOT EXISTS)? identifier branchOptions ; tagOptions : (AS OF VERSION snapshotId)? (refRetain)? ; branchOptions : (AS OF VERSION snapshotId)? (refRetain)? (snapshotRetention)? ; snapshotId : number ; timeUnit : DAYS | HOURS | MINUTES ; snapshotRetention : WITH SNAPSHOT RETENTION minSnapshotsToKeep | WITH SNAPSHOT RETENTION maxSnapshotAge | WITH SNAPSHOT RETENTION minSnapshotsToKeep maxSnapshotAge ; refRetain : RETAIN number timeUnit ; maxSnapshotAge : number timeUnit ; minSnapshotsToKeep : number SNAPSHOTS ; writeSpec : (writeDistributionSpec | writeOrderingSpec)* ; writeDistributionSpec : DISTRIBUTED BY PARTITION ; writeOrderingSpec : LOCALLY? ORDERED BY orderExpr | UNORDERED ; orderExpr : fields+=orderField (',' fields+=orderField)* | '(' fields+=orderField (',' fields+=orderField)* ')' ; orderField : transform direction=(ASC | DESC)? (NULLS nullOrder=(FIRST | LAST))? ; fieldList : fields+=multipartIdentifier (',' fields+=multipartIdentifier)* ; zorderSpec : ZORDER BY LEFT_PAREN interleave+=qualifiedName (COMMA interleave+=qualifiedName)* RIGHT_PAREN | ZORDER BY interleave+=qualifiedName (COMMA interleave+=qualifiedName)* ; clusterBySpec : CLUSTER BY LEFT_PAREN interleave+=qualifiedName (COMMA interleave+=qualifiedName)* RIGHT_PAREN ; constraint : CHECK '(' exprToken+ ')' #checkConstraint ; exprToken : .+? ; featureNameValue : identifier | stringLit ; unsupportedHiveNativeCommands : kw1=CREATE kw2=ROLE | kw1=DROP kw2=ROLE | kw1=GRANT kw2=ROLE? | kw1=REVOKE kw2=ROLE? | kw1=SHOW kw2=GRANT | kw1=SHOW kw2=ROLE kw3=GRANT? | kw1=SHOW kw2=PRINCIPALS | kw1=SHOW kw2=ROLES | kw1=SHOW kw2=CURRENT kw3=ROLES | kw1=EXPORT kw2=TABLE | kw1=IMPORT kw2=TABLE | kw1=SHOW kw2=COMPACTIONS | kw1=SHOW kw2=CREATE kw3=TABLE | kw1=SHOW kw2=TRANSACTIONS | kw1=SHOW kw2=INDEXES | kw1=SHOW kw2=LOCKS | kw1=CREATE kw2=INDEX | kw1=DROP kw2=INDEX | kw1=ALTER kw2=INDEX | kw1=LOCK kw2=TABLE | kw1=LOCK kw2=DATABASE | kw1=UNLOCK kw2=TABLE | kw1=UNLOCK kw2=DATABASE | kw1=CREATE kw2=TEMPORARY kw3=MACRO | kw1=DROP kw2=TEMPORARY kw3=MACRO | kw1=ALTER kw2=TABLE tableIdentifier kw3=NOT kw4=CLUSTERED | kw1=ALTER kw2=TABLE tableIdentifier kw3=CLUSTERED kw4=BY | kw1=ALTER kw2=TABLE tableIdentifier kw3=NOT kw4=SORTED | kw1=ALTER kw2=TABLE tableIdentifier kw3=SKEWED kw4=BY | kw1=ALTER kw2=TABLE tableIdentifier kw3=NOT kw4=SKEWED | kw1=ALTER kw2=TABLE tableIdentifier kw3=NOT kw4=STORED kw5=AS kw6=DIRECTORIES | kw1=ALTER kw2=TABLE tableIdentifier kw3=SET kw4=SKEWED kw5=LOCATION | kw1=ALTER kw2=TABLE tableIdentifier kw3=EXCHANGE kw4=PARTITION | kw1=ALTER kw2=TABLE tableIdentifier kw3=ARCHIVE kw4=PARTITION | kw1=ALTER kw2=TABLE tableIdentifier kw3=UNARCHIVE kw4=PARTITION | kw1=ALTER kw2=TABLE tableIdentifier kw3=TOUCH | kw1=ALTER kw2=TABLE tableIdentifier partitionSpec? kw3=COMPACT | kw1=ALTER kw2=TABLE tableIdentifier partitionSpec? kw3=CONCATENATE | kw1=ALTER kw2=TABLE tableIdentifier partitionSpec? kw3=SET kw4=FILEFORMAT | kw1=ALTER kw2=TABLE tableIdentifier partitionSpec? kw3=REPLACE kw4=COLUMNS | kw1=START kw2=TRANSACTION | kw1=COMMIT | kw1=ROLLBACK | kw1=DFS ; createTableHeader : CREATE TEMPORARY? EXTERNAL? TABLE (IF NOT EXISTS)? identifierReference ; replaceTableHeader : (CREATE OR)? REPLACE TABLE identifierReference ; bucketSpec : CLUSTERED BY identifierList (SORTED BY orderedIdentifierList)? INTO INTEGER_VALUE BUCKETS ; skewSpec : SKEWED BY identifierList ON (constantList | nestedConstantList) (STORED AS DIRECTORIES)? ; locationSpec : LOCATION stringLit ; commentSpec : COMMENT stringLit ; query : ctes? queryTerm queryOrganization ; insertInto : INSERT (hints+=hint)* OVERWRITE TABLE? identifierReference (partitionSpec (IF NOT EXISTS)?)? ((BY NAME) | identifierList)? #insertOverwriteTable | INSERT (hints+=hint)* INTO TABLE? identifierReference partitionSpec? (IF NOT EXISTS)? ((BY NAME) | identifierList)? #insertIntoTable | INSERT (hints+=hint)* INTO TABLE? identifierReference REPLACE whereClause #insertIntoReplaceWhere | INSERT (hints+=hint)* OVERWRITE LOCAL? DIRECTORY path=stringLit rowFormat? createFileFormat? #insertOverwriteHiveDir | INSERT (hints+=hint)* OVERWRITE LOCAL? DIRECTORY (path=stringLit)? tableProvider (OPTIONS options=propertyList)? #insertOverwriteDir ; partitionSpecLocation : partitionSpec locationSpec? ; partitionSpec : PARTITION LEFT_PAREN partitionVal (COMMA partitionVal)* RIGHT_PAREN ; partitionVal : identifier (EQ constant)? | identifier EQ DEFAULT ; namespace : NAMESPACE | DATABASE | SCHEMA ; namespaces : NAMESPACES | DATABASES | SCHEMAS ; dropPartitionSpec : PARTITION '(' dropPartitionVal (',' dropPartitionVal)* ')' ; dropPartitionVal : identifier (comparisonOperator constant)? ; describeFuncName : identifierReference | stringLit | comparisonOperator | arithmeticOperator | predicateOperator ; describeColName : nameParts+=identifier (DOT nameParts+=identifier)* ; ctes : WITH namedQuery (COMMA namedQuery)* ; namedQuery : name=errorCapturingIdentifier (columnAliases=identifierList)? AS? LEFT_PAREN query RIGHT_PAREN ; tableProvider : USING multipartIdentifier ; createTableClauses :((OPTIONS options=expressionPropertyList) | (PARTITIONED BY partitioning=partitionFieldList) | skewSpec | bucketSpec | rowFormat | createFileFormat | locationSpec | commentSpec | (LIFECYCLE lifecycle=INTEGER_VALUE) | (TBLPROPERTIES tableProps=propertyList))* ; propertyList : LEFT_PAREN property (COMMA property)* RIGHT_PAREN ; property : key=propertyKey (EQ? value=propertyValue)? ; propertyKey : identifier (DOT identifier)* | stringLit ; propertyValue : INTEGER_VALUE | DECIMAL_VALUE | booleanValue | stringLit ; expressionPropertyList : LEFT_PAREN expressionProperty (COMMA expressionProperty)* RIGHT_PAREN ; expressionProperty : key=propertyKey (EQ? value=expression)? ; constantList : LEFT_PAREN constant (COMMA constant)* RIGHT_PAREN ; nestedConstantList : LEFT_PAREN constantList (COMMA constantList)* RIGHT_PAREN ; createFileFormat : STORED AS fileFormat | STORED BY storageHandler ; fileFormat : INPUTFORMAT inFmt=stringLit OUTPUTFORMAT outFmt=stringLit #tableFileFormat | identifier #genericFileFormat ; storageHandler : stringLit (WITH SERDEPROPERTIES propertyList)? ; resource : identifier stringLit ; dmlStatementNoWith : insertInto query #singleInsertQuery | fromClause multiInsertQueryBody+ #multiInsertQuery | DELETE FROM identifierReference tableAlias whereClause? #deleteFromTable | UPDATE identifierReference tableAlias setClause whereClause? #updateTable | MERGE INTO target=identifierReference targetAlias=tableAlias USING (source=identifierReference | LEFT_PAREN sourceQuery=query RIGHT_PAREN) sourceAlias=tableAlias ON mergeCondition=booleanExpression matchedClause* notMatchedClause* notMatchedBySourceClause* #mergeIntoTable ; identifierReference : IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN | multipartIdentifier ; queryOrganization : (ORDER BY order+=sortItem (COMMA order+=sortItem)*)? (CLUSTER BY clusterBy+=expression (COMMA clusterBy+=expression)*)? (DISTRIBUTE BY distributeBy+=expression (COMMA distributeBy+=expression)*)? (SORT BY sort+=sortItem (COMMA sort+=sortItem)*)? windowClause? (LIMIT (ALL | limit=expression))? (OFFSET offset=expression)? ; multiInsertQueryBody : insertInto fromStatementBody ; queryTerm : queryPrimary #queryTermDefault | left=queryTerm {legacy_setops_precedence_enabled}? operator=(INTERSECT | UNION | EXCEPT | SETMINUS) setQuantifier? right=queryTerm #setOperation | left=queryTerm {!legacy_setops_precedence_enabled}? operator=INTERSECT setQuantifier? right=queryTerm #setOperation | left=queryTerm {!legacy_setops_precedence_enabled}? operator=(UNION | EXCEPT | SETMINUS) setQuantifier? right=queryTerm #setOperation ; queryPrimary : querySpecification #queryPrimaryDefault | fromStatement #fromStmt | TABLE identifierReference #table | inlineTable #inlineTableDefault1 | LEFT_PAREN query RIGHT_PAREN #subquery ; sortItem : expression ordering=(ASC | DESC)? (NULLS nullOrder=(LAST | FIRST))? ; fromStatement : fromClause fromStatementBody+ ; fromStatementBody : selectClause lateralView* whereClause? aggregationClause? havingClause? windowClause? queryOrganization | transformClause whereClause? queryOrganization ; querySpecification : transformClause fromClause? lateralView* whereClause? aggregationClause? havingClause? windowClause? #transformQuerySpecification | selectClause fromClause? lateralView* whereClause? aggregationClause? havingClause? windowClause? #regularQuerySpecification ; transformClause : (SELECT kind=TRANSFORM LEFT_PAREN setQuantifier? expressionSeq RIGHT_PAREN | kind=MAP setQuantifier? expressionSeq | kind=REDUCE setQuantifier? expressionSeq) inRowFormat=rowFormat? (RECORDWRITER recordWriter=stringLit)? USING script=stringLit (AS (identifierSeq | colTypeList | (LEFT_PAREN (identifierSeq | colTypeList) RIGHT_PAREN)))? outRowFormat=rowFormat? (RECORDREADER recordReader=stringLit)? ; selectClause : SELECT (hints+=hint)* setQuantifier? namedExpressionSeq ; setClause : SET assignmentList ; matchedClause : WHEN MATCHED (AND matchedCond=booleanExpression)? THEN matchedAction ; notMatchedClause : WHEN NOT MATCHED (BY TARGET)? (AND notMatchedCond=booleanExpression)? THEN notMatchedAction ; notMatchedBySourceClause : WHEN NOT MATCHED BY SOURCE (AND notMatchedBySourceCond=booleanExpression)? THEN notMatchedBySourceAction ; matchedAction : DELETE | UPDATE SET ASTERISK | UPDATE SET assignmentList ; notMatchedAction : INSERT ASTERISK | INSERT LEFT_PAREN columns=multipartIdentifierList RIGHT_PAREN VALUES LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN ; notMatchedBySourceAction : DELETE | UPDATE SET assignmentList ; assignmentList : assignment (COMMA assignment)* ; assignment : key=multipartIdentifier EQ value=expression ; whereClause : WHERE booleanExpression ; havingClause : HAVING booleanExpression ; hint : HENT_START hintStatements+=hintStatement (COMMA? hintStatements+=hintStatement)* HENT_END ; hintStatement : hintName=identifier | hintName=identifier LEFT_PAREN parameters+=primaryExpression (COMMA parameters+=primaryExpression)* RIGHT_PAREN ; fromClause : FROM relation (COMMA relation)* lateralView* pivotClause? unpivotClause? ; temporalClause : FOR? (SYSTEM_VERSION | VERSION) AS OF version | FOR? (SYSTEM_TIME | TIMESTAMP) AS OF timestamp=valueExpression ; aggregationClause : GROUP BY groupingExpressionsWithGroupingAnalytics+=groupByClause (COMMA groupingExpressionsWithGroupingAnalytics+=groupByClause)* | GROUP BY groupingExpressions+=expression (COMMA groupingExpressions+=expression)* ( WITH kind=ROLLUP | WITH kind=CUBE | kind=GROUPING SETS LEFT_PAREN groupingSet (COMMA groupingSet)* RIGHT_PAREN)? ; groupByClause : groupingAnalytics | expression ; groupingAnalytics : (ROLLUP | CUBE) LEFT_PAREN groupingSet (COMMA groupingSet)* RIGHT_PAREN | GROUPING SETS LEFT_PAREN groupingElement (COMMA groupingElement)* RIGHT_PAREN ; groupingElement : groupingAnalytics | groupingSet ; groupingSet : LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN | expression ; pivotClause : PIVOT LEFT_PAREN aggregates=namedExpressionSeq FOR pivotColumn IN LEFT_PAREN pivotValues+=pivotValue (COMMA pivotValues+=pivotValue)* RIGHT_PAREN RIGHT_PAREN ; pivotColumn : identifiers+=identifier | LEFT_PAREN identifiers+=identifier (COMMA identifiers+=identifier)* RIGHT_PAREN ; pivotValue : expression (AS? identifier)? ; unpivotClause : UNPIVOT nullOperator=unpivotNullClause? LEFT_PAREN operator=unpivotOperator RIGHT_PAREN (AS? identifier)? ; unpivotNullClause : (INCLUDE | EXCLUDE) NULLS ; unpivotOperator : (unpivotSingleValueColumnClause | unpivotMultiValueColumnClause) ; unpivotSingleValueColumnClause : unpivotValueColumn FOR unpivotNameColumn IN LEFT_PAREN unpivotColumns+=unpivotColumnAndAlias (COMMA unpivotColumns+=unpivotColumnAndAlias)* RIGHT_PAREN ; unpivotMultiValueColumnClause : LEFT_PAREN unpivotValueColumns+=unpivotValueColumn (COMMA unpivotValueColumns+=unpivotValueColumn)* RIGHT_PAREN FOR unpivotNameColumn IN LEFT_PAREN unpivotColumnSets+=unpivotColumnSet (COMMA unpivotColumnSets+=unpivotColumnSet)* RIGHT_PAREN ; unpivotColumnSet : LEFT_PAREN unpivotColumns+=unpivotColumn (COMMA unpivotColumns+=unpivotColumn)* RIGHT_PAREN unpivotAlias? ; unpivotValueColumn : identifier ; unpivotNameColumn : identifier ; unpivotColumnAndAlias : unpivotColumn unpivotAlias? ; unpivotColumn : multipartIdentifier ; unpivotAlias : AS? identifier ; lateralView : LATERAL VIEW (OUTER)? qualifiedName LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN tblName=identifier (AS? colName+=identifier (COMMA colName+=identifier)*)? ; setQuantifier : DISTINCT | ALL ; relation : LATERAL? relationPrimary relationExtension* ; relationExtension : joinRelation | pivotClause | unpivotClause ; joinRelation : (joinType) JOIN LATERAL? right=relationPrimary joinCriteria? | NATURAL joinType JOIN LATERAL? right=relationPrimary ; joinType : INNER? | CROSS | LEFT OUTER? | LEFT? SEMI | RIGHT OUTER? | FULL OUTER? | LEFT? ANTI ; joinCriteria : ON booleanExpression | USING identifierList ; sample : TABLESAMPLE LEFT_PAREN sampleMethod? RIGHT_PAREN (REPEATABLE LEFT_PAREN seed=INTEGER_VALUE RIGHT_PAREN)? ; sampleMethod : negativeSign=MINUS? percentage=(INTEGER_VALUE | DECIMAL_VALUE) PERCENTLIT #sampleByPercentile | expression ROWS #sampleByRows | sampleType=BUCKET numerator=INTEGER_VALUE OUT OF denominator=INTEGER_VALUE (ON (identifier | qualifiedName LEFT_PAREN RIGHT_PAREN))? #sampleByBucket | bytes=expression #sampleByBytes ; identifierList : LEFT_PAREN identifierSeq RIGHT_PAREN ; identifierSeq : ident+=errorCapturingIdentifier (COMMA ident+=errorCapturingIdentifier)* ; orderedIdentifierList : LEFT_PAREN orderedIdentifier (COMMA orderedIdentifier)* RIGHT_PAREN ; orderedIdentifier : ident=errorCapturingIdentifier ordering=(ASC | DESC)? ; identifierCommentList : LEFT_PAREN identifierComment (COMMA identifierComment)* RIGHT_PAREN ; identifierComment : identifier commentSpec? ; relationPrimary : identifierReference temporalClause? sample? tableAlias #tableName | LEFT_PAREN query RIGHT_PAREN sample? tableAlias #aliasedQuery | LEFT_PAREN relation RIGHT_PAREN sample? tableAlias #aliasedRelation | inlineTable #inlineTableDefault2 | functionTable #tableValuedFunction ; inlineTable : VALUES expression (COMMA expression)* tableAlias ; functionTableSubqueryArgument : TABLE identifierReference | TABLE LEFT_PAREN identifierReference RIGHT_PAREN | TABLE LEFT_PAREN query RIGHT_PAREN ; functionTableNamedArgumentExpression : key=identifier FAT_ARROW table=functionTableSubqueryArgument ; functionTableReferenceArgument : functionTableSubqueryArgument | functionTableNamedArgumentExpression ; functionTableArgument : functionTableReferenceArgument | functionArgument ; functionTable : funcName=functionName LEFT_PAREN (functionTableArgument (COMMA functionTableArgument)*)? RIGHT_PAREN tableAlias ; tableAlias : (AS? strictIdentifier identifierList?)? ; rowFormat : ROW FORMAT SERDE name=stringLit (WITH SERDEPROPERTIES props=propertyList)? #rowFormatSerde | ROW FORMAT DELIMITED (FIELDS TERMINATED BY fieldsTerminatedBy=stringLit (ESCAPED BY escapedBy=stringLit)?)? (COLLECTION ITEMS TERMINATED BY collectionItemsTerminatedBy=stringLit)? (MAP KEYS TERMINATED BY keysTerminatedBy=stringLit)? (LINES TERMINATED BY linesSeparatedBy=stringLit)? (NULL DEFINED AS nullDefinedAs=stringLit)? #rowFormatDelimited ; multipartIdentifierList : multipartIdentifier (COMMA multipartIdentifier)* ; multipartIdentifier : parts+=errorCapturingIdentifier (DOT parts+=errorCapturingIdentifier)* ; multipartIdentifierPropertyList : multipartIdentifierProperty (COMMA multipartIdentifierProperty)* ; multipartIdentifierProperty : multipartIdentifier (OPTIONS options=propertyList)? ; tableIdentifier : (db=errorCapturingIdentifier DOT)? table=errorCapturingIdentifier ; functionIdentifier : (db=errorCapturingIdentifier DOT)? function=errorCapturingIdentifier ; namedExpression : expression (AS? (name=errorCapturingIdentifier | identifierList))? ; namedExpressionSeq : namedExpression (COMMA namedExpression)* ; partitionFieldList : LEFT_PAREN fields+=partitionField (COMMA fields+=partitionField)* RIGHT_PAREN ; partitionField : transform #partitionTransform | colType #partitionColumn ; transform : qualifiedName #identityTransform | transformName=identifier LEFT_PAREN argument+=transformArgument (COMMA argument+=transformArgument)* RIGHT_PAREN #applyTransform ; transformArgument : qualifiedName | constant ; expression : booleanExpression ; namedArgumentExpression : key=identifier FAT_ARROW value=expression ; functionArgument : expression | namedArgumentExpression ; expressionSeq : expression (COMMA expression)* ; booleanExpression : NOT booleanExpression #logicalNot | EXISTS LEFT_PAREN query RIGHT_PAREN #exists | valueExpression predicate? #predicated | left=booleanExpression operator=AND right=booleanExpression #logicalBinary | left=booleanExpression operator=OR right=booleanExpression #logicalBinary ; predicate : NOT? kind=BETWEEN lower=valueExpression AND upper=valueExpression | NOT? kind=IN LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN | NOT? kind=IN LEFT_PAREN query RIGHT_PAREN | NOT? kind=RLIKE pattern=valueExpression | NOT? kind=(LIKE | ILIKE) quantifier=(ANY | SOME | ALL) (LEFT_PAREN RIGHT_PAREN | LEFT_PAREN expression (COMMA expression)* RIGHT_PAREN) | NOT? kind=(LIKE | ILIKE) pattern=valueExpression (ESCAPE escapeChar=stringLit)? | IS NOT? kind=NULL | IS NOT? kind=(TRUE | FALSE | UNKNOWN) | IS NOT? kind=DISTINCT FROM right=valueExpression ; valueExpression : primaryExpression #valueExpressionDefault | operator=(MINUS | PLUS | TILDE) valueExpression #arithmeticUnary | left=valueExpression operator=(ASTERISK | SLASH | PERCENT | DIV) right=valueExpression #arithmeticBinary | left=valueExpression operator=(PLUS | MINUS | CONCAT_PIPE) right=valueExpression #arithmeticBinary | left=valueExpression operator=AMPERSAND right=valueExpression #arithmeticBinary | left=valueExpression operator=HAT right=valueExpression #arithmeticBinary | left=valueExpression operator=PIPE right=valueExpression #arithmeticBinary | left=valueExpression comparisonOperator right=valueExpression #comparison ; datetimeUnit : YEAR | QUARTER | MONTH | WEEK | DAY | DAYOFYEAR | HOUR | MINUTE | SECOND | MILLISECOND | MICROSECOND ; primaryExpression : name=(CURRENT_DATE | CURRENT_TIMESTAMP | CURRENT_USER | USER) #currentLike | name=(TIMESTAMPADD | DATEADD | DATE_ADD) LEFT_PAREN (unit=datetimeUnit | invalidUnit=stringLit) COMMA unitsAmount=valueExpression COMMA timestamp=valueExpression RIGHT_PAREN #timestampadd | name=(TIMESTAMPDIFF | DATEDIFF | DATE_DIFF) LEFT_PAREN (unit=datetimeUnit | invalidUnit=stringLit) COMMA startTimestamp=valueExpression COMMA endTimestamp=valueExpression RIGHT_PAREN #timestampdiff | CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | CASE value=expression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | name=(CAST | TRY_CAST) LEFT_PAREN expression AS dataType RIGHT_PAREN #cast | STRUCT LEFT_PAREN (argument+=namedExpression (COMMA argument+=namedExpression)*)? RIGHT_PAREN #struct | FIRST LEFT_PAREN expression (IGNORE NULLS)? RIGHT_PAREN #first | ANY_VALUE LEFT_PAREN expression (IGNORE NULLS)? RIGHT_PAREN #any_value | LAST LEFT_PAREN expression (IGNORE NULLS)? RIGHT_PAREN #last | POSITION LEFT_PAREN substr=valueExpression IN str=valueExpression RIGHT_PAREN #position | constant #constantDefault | ASTERISK #star | qualifiedName DOT ASTERISK #star | LEFT_PAREN namedExpression (COMMA namedExpression)+ RIGHT_PAREN #rowConstructor | LEFT_PAREN query RIGHT_PAREN #subqueryExpression | IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN #identifierClause | functionName LEFT_PAREN (setQuantifier? argument+=functionArgument (COMMA argument+=functionArgument)*)? RIGHT_PAREN (FILTER LEFT_PAREN WHERE where=booleanExpression RIGHT_PAREN)? (nullsOption=(IGNORE | RESPECT) NULLS)? ( OVER windowSpec)? #functionCall | identifier ARROW expression #lambda | LEFT_PAREN identifier (COMMA identifier)+ RIGHT_PAREN ARROW expression #lambda | value=primaryExpression LEFT_BRACKET index=valueExpression RIGHT_BRACKET #subscript | identifier #columnReference | base=primaryExpression DOT fieldName=identifier #dereference | LEFT_PAREN expression RIGHT_PAREN #parenthesizedExpression | EXTRACT LEFT_PAREN field=identifier FROM source=valueExpression RIGHT_PAREN #extract | (SUBSTR | SUBSTRING) LEFT_PAREN str=valueExpression (FROM | COMMA) pos=valueExpression ((FOR | COMMA) len=valueExpression)? RIGHT_PAREN #substring | TRIM LEFT_PAREN trimOption=(BOTH | LEADING | TRAILING)? (trimStr=valueExpression)? FROM srcStr=valueExpression RIGHT_PAREN #trim | OVERLAY LEFT_PAREN input=valueExpression PLACING replace=valueExpression FROM position=valueExpression (FOR length=valueExpression)? RIGHT_PAREN #overlay | name=(PERCENTILE_CONT | PERCENTILE_DISC) LEFT_PAREN percentage=valueExpression RIGHT_PAREN WITHIN GROUP LEFT_PAREN ORDER BY sortItem RIGHT_PAREN (FILTER LEFT_PAREN WHERE where=booleanExpression RIGHT_PAREN)? ( OVER windowSpec)? #percentile ; literalType : DATE | TIMESTAMP | TIMESTAMP_LTZ | TIMESTAMP_NTZ | INTERVAL | BINARY_HEX | unsupportedType=identifier ; constant : NULL #nullLiteral | QUESTION #posParameterLiteral | COLON identifier #namedParameterLiteral | interval #intervalLiteral | literalType stringLit #typeConstructor | number #numericLiteral | booleanValue #booleanLiteral | stringLit+ #stringLiteral ; comparisonOperator : EQ | NEQ | NEQJ | LT | LTE | GT | GTE | NSEQ ; arithmeticOperator : PLUS | MINUS | ASTERISK | SLASH | PERCENT | DIV | TILDE | AMPERSAND | PIPE | CONCAT_PIPE | HAT ; predicateOperator : OR | AND | IN | NOT ; booleanValue : TRUE | FALSE ; interval : INTERVAL (errorCapturingMultiUnitsInterval | errorCapturingUnitToUnitInterval) ; errorCapturingMultiUnitsInterval : body=multiUnitsInterval unitToUnitInterval? ; multiUnitsInterval : (intervalValue unit+=unitInMultiUnits)+ ; errorCapturingUnitToUnitInterval : body=unitToUnitInterval (error1=multiUnitsInterval | error2=unitToUnitInterval)? ; unitToUnitInterval : value=intervalValue from=unitInUnitToUnit TO to=unitInUnitToUnit ; intervalValue : (PLUS | MINUS)? (INTEGER_VALUE | DECIMAL_VALUE | stringLit) ; unitInMultiUnits : NANOSECOND | NANOSECONDS | MICROSECOND | MICROSECONDS | MILLISECOND | MILLISECONDS | SECOND | SECONDS | MINUTE | MINUTES | HOUR | HOURS | DAY | DAYS | WEEK | WEEKS | MONTH | MONTHS | YEAR | YEARS ; unitInUnitToUnit : SECOND | MINUTE | HOUR | DAY | MONTH | YEAR ; colPosition : position=FIRST | position=AFTER afterCol=errorCapturingIdentifier ; type : BOOLEAN | TINYINT | BYTE | SMALLINT | SHORT | INT | INTEGER | BIGINT | LONG | FLOAT | REAL | DOUBLE | DATE | TIMESTAMP | TIMESTAMP_NTZ | TIMESTAMP_LTZ | STRING | CHARACTER | CHAR | VARCHAR | BINARY | DECIMAL | DEC | NUMERIC | VOID | INTERVAL | ARRAY | STRUCT | MAP | unsupportedType=identifier ; dataType : complex=ARRAY LT dataType GT #complexDataType | complex=MAP LT dataType COMMA dataType GT #complexDataType | complex=STRUCT (LT complexColTypeList? GT | NEQ) #complexDataType | INTERVAL from=(YEAR | MONTH) (TO to=MONTH)? #yearMonthIntervalDataType | INTERVAL from=(DAY | HOUR | MINUTE | SECOND) (TO to=(HOUR | MINUTE | SECOND))? #dayTimeIntervalDataType | type (LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN)? #primitiveDataType ; qualifiedColTypeWithPositionList : qualifiedColTypeWithPosition (COMMA qualifiedColTypeWithPosition)* ; qualifiedColTypeWithPosition : name=multipartIdentifier dataType colDefinitionDescriptorWithPosition* ; colDefinitionDescriptorWithPosition : NOT NULL | defaultExpression | commentSpec | colPosition ; defaultExpression : DEFAULT expression ; colTypeList : colType (COMMA colType)* ; colType : colName=errorCapturingIdentifier dataType (NOT NULL)? commentSpec? ; createOrReplaceTableColTypeList : createOrReplaceTableColType (COMMA createOrReplaceTableColType)* ; createOrReplaceTableColType : colName=errorCapturingIdentifier dataType colDefinitionOption* ; colDefinitionOption : NOT NULL | defaultExpression | generationExpression | commentSpec ; generationExpression : GENERATED ALWAYS AS LEFT_PAREN expression RIGHT_PAREN ; complexColTypeList : complexColType (COMMA complexColType)* ; complexColType : identifier COLON? dataType (NOT NULL)? commentSpec? ; whenClause : WHEN condition=expression THEN result=expression ; windowClause : WINDOW namedWindow (COMMA namedWindow)* ; namedWindow : name=errorCapturingIdentifier AS windowSpec ; windowSpec : name=errorCapturingIdentifier #windowRef | LEFT_PAREN name=errorCapturingIdentifier RIGHT_PAREN #windowRef | LEFT_PAREN ( CLUSTER BY partition+=expression (COMMA partition+=expression)* | ((PARTITION | DISTRIBUTE) BY partition+=expression (COMMA partition+=expression)*)? ((ORDER | SORT) BY sortItem (COMMA sortItem)*)?) windowFrame? RIGHT_PAREN #windowDef ; windowFrame : frameType=RANGE start=frameBound | frameType=ROWS start=frameBound | frameType=RANGE BETWEEN start=frameBound AND end=frameBound | frameType=ROWS BETWEEN start=frameBound AND end=frameBound ; frameBound : UNBOUNDED boundType=(PRECEDING | FOLLOWING) | boundType=CURRENT ROW | expression boundType=(PRECEDING | FOLLOWING) ; qualifiedNameList : qualifiedName (COMMA qualifiedName)* ; functionName : IDENTIFIER_KW LEFT_PAREN expression RIGHT_PAREN | qualifiedName | FILTER | LEFT | RIGHT ; qualifiedName : identifier (DOT identifier)* ; // this rule is used for explicitly capturing wrong identifiers such as test-table, which should actually be `test-table` // replace identifier with errorCapturingIdentifier where the immediate follow symbol is not an expression, otherwise // valid expressions such as "a-b" can be recognized as an identifier errorCapturingIdentifier : identifier errorCapturingIdentifierExtra ; // extra left-factoring grammar errorCapturingIdentifierExtra : (MINUS identifier)+ #errorIdent | #realIdent ; identifier : strictIdentifier | {!SQL_standard_keyword_behavior}? strictNonReserved ; strictIdentifier : IDENTIFIER #unquotedIdentifier | quotedIdentifier #quotedIdentifierAlternative | {SQL_standard_keyword_behavior}? ansiNonReserved #unquotedIdentifier | {!SQL_standard_keyword_behavior}? nonReserved #unquotedIdentifier ; quotedIdentifier : BACKQUOTED_IDENTIFIER | {double_quoted_identifiers}? DOUBLEQUOTED_STRING ; backQuotedIdentifier : BACKQUOTED_IDENTIFIER ; number : {!legacy_exponent_literal_as_decimal_enabled}? MINUS? EXPONENT_VALUE #exponentLiteral | {!legacy_exponent_literal_as_decimal_enabled}? MINUS? DECIMAL_VALUE #decimalLiteral | {legacy_exponent_literal_as_decimal_enabled}? MINUS? (EXPONENT_VALUE | DECIMAL_VALUE) #legacyDecimalLiteral | MINUS? INTEGER_VALUE #integerLiteral | MINUS? BIGINT_LITERAL #bigIntLiteral | MINUS? SMALLINT_LITERAL #smallIntLiteral | MINUS? TINYINT_LITERAL #tinyIntLiteral | MINUS? DOUBLE_LITERAL #doubleLiteral | MINUS? FLOAT_LITERAL #floatLiteral | MINUS? BIGDECIMAL_LITERAL #bigDecimalLiteral ; alterColumnAction : TYPE dataType | commentSpec | colPosition | setOrDrop=(SET | DROP) NOT NULL | SET defaultExpression | dropDefault=DROP DEFAULT ; stringLit : STRING_LITERAL | {!double_quoted_identifiers}? DOUBLEQUOTED_STRING ; comment : stringLit | NULL ; version : INTEGER_VALUE | stringLit ; // When `SQL_standard_keyword_behavior=true`, there are 2 kinds of keywords in Spark SQL. // - Reserved keywords: // Keywords that are reserved and can't be used as identifiers for table, view, column, // function, alias, etc. // - Non-reserved keywords: // Keywords that have a special meaning only in particular contexts and can be used as // identifiers in other contexts. For example, `EXPLAIN SELECT ...` is a command, but EXPLAIN // can be used as identifiers in other places. // You can find the full keywords list by searching "Start of the keywords list" in this file. // The non-reserved keywords are listed below. Keywords not in this list are reserved keywords. ansiNonReserved //--ANSI-NON-RESERVED-START : ADD | AFTER | ALTER | ALWAYS | ANALYZE | ANTI | ANY_VALUE | ARCHIVE | ARRAY | ASC | AT | BETWEEN | BIGINT | BINARY | BINARY_HEX | BOOLEAN | BUCKET | BUCKETS | BY | BYTE | CACHE | CASCADE | CATALOG | CATALOGS | CHANGE | CHAR | CHARACTER | CLEAR | CLUSTER | CLUSTERED | CODEGEN | COLLECTION | COLUMNS | COMMENT | COMMIT | COMPACT | COMPACTIONS | COMPUTE | CONCATENATE | COST | CUBE | CURRENT | DATA | DATABASE | DATABASES | DATE | DATEADD | DATE_ADD | DATEDIFF | DATE_DIFF | DAY | DAYS | DAYOFYEAR | DBPROPERTIES | DEC | DECIMAL | DEFAULT | DEFINED | DELETE | DELIMITED | DESC | DESCRIBE | DFS | DIRECTORIES | DIRECTORY | DISTRIBUTE | DIV | DOUBLE | DROP | ESCAPED | EXCHANGE | EXCLUDE | EXISTS | EXPLAIN | EXPORT | EXTENDED | EXTERNAL | EXTRACT | FIELD | FIELDS | FILEFORMAT | FIRST | FLOAT | FOLLOWING | FORMAT | FORMATTED | FUNCTION | FUNCTIONS | GENERATED | GLOBAL | GROUPING | HOUR | HOURS | IDENTIFIER_KW | IF | IGNORE | IMPORT | INCLUDE | INDEX | INDEXES | INPATH | INPUTFORMAT | INSERT | INT | INTEGER | INTERVAL | ITEMS | KEYS | LAST | LAZY | LIKE | ILIKE | LIMIT | LINES | LIST | LOAD | LOCAL | LOCATION | LOCK | LOCKS | LOGICAL | LONG | MACRO | MAP | MATCHED | MERGE | MICROSECOND | MICROSECONDS | MILLISECOND | MILLISECONDS | MINUTE | MINUTES | MONTH | MONTHS | MSCK | NAME | NAMESPACE | NAMESPACES | NANOSECOND | NANOSECONDS | NO | NULLS | NUMERIC | OF | OPTION | OPTIONS | OUT | OUTPUTFORMAT | OVER | OVERLAY | OVERWRITE | PARTITION | PARTITIONED | PARTITIONS | PERCENTLIT | PIVOT | PLACING | POSITION | PRECEDING | PRINCIPALS | PROPERTIES | PURGE | QUARTER | QUERY | RANGE | REAL | RECORDREADER | RECORDWRITER | RECOVER | REDUCE | REFRESH | RENAME | REPAIR | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | REVOKE | RLIKE | ROLE | ROLES | ROLLBACK | ROLLUP | ROW | ROWS | SCHEMA | SCHEMAS | SECOND | SECONDS | SEMI | SEPARATED | SERDE | SERDEPROPERTIES | SET | SETMINUS | SETS | SHORT | SHOW | SKEWED | SMALLINT | SORT | SORTED | SOURCE | START | STATISTICS | STORED | STRATIFY | STRING | STRUCT | SUBSTR | SUBSTRING | SYNC | SYSTEM_TIME | SYSTEM_VERSION | TABLES | TABLESAMPLE | TARGET | TBLPROPERTIES | TEMPORARY | TERMINATED | TIMESTAMP | TIMESTAMP_LTZ | TIMESTAMP_NTZ | TIMESTAMPADD | TIMESTAMPDIFF | TINYINT | TOUCH | TRANSACTION | TRANSACTIONS | TRANSFORM | TRIM | TRUE | TRUNCATE | TRY_CAST | TYPE | UNARCHIVE | UNBOUNDED | UNCACHE | UNLOCK | UNPIVOT | UNSET | UPDATE | USE | VALUES | VARCHAR | VERSION | VIEW | VIEWS | VOID | WEEK | WEEKS | WINDOW | YEAR | YEARS | ZONE | COMPRESSION | FILE | HELP | LIFECYCLE | DATATUNNEL | DISTCP | SINK | CALL | OWNER | SIZE_LIMIT | SINGLE | MAX_FILE_SIZE | INCLUDING //--ANSI-NON-RESERVED-END ; // When `SQL_standard_keyword_behavior=false`, there are 2 kinds of keywords in Spark SQL. // - Non-reserved keywords: // Same definition as the one when `SQL_standard_keyword_behavior=true`. // - Strict-non-reserved keywords: // A strict version of non-reserved keywords, which can not be used as table alias. // You can find the full keywords list by searching "Start of the keywords list" in this file. // The strict-non-reserved keywords are listed in `strictNonReserved`. // The non-reserved keywords are listed in `nonReserved`. // These 2 together contain all the keywords. strictNonReserved : ANTI | CROSS | EXCEPT | FULL | INNER | INTERSECT | JOIN | LATERAL | LEFT | NATURAL | ON | RIGHT | SEMI | SETMINUS | UNION | USING ; nonReserved //--DEFAULT-NON-RESERVED-START : ADD | AFTER | ALL | ALTER | ALWAYS | ANALYZE | AND | ANY | ANY_VALUE | ARCHIVE | ARRAY | AS | ASC | AT | AUTHORIZATION | BETWEEN | BIGINT | BINARY | BINARY_HEX | BOOLEAN | BOTH | BRANCH | BUCKET | BUCKETS | BY | BYTE | CACHE | CASCADE | CASE | CAST | CATALOG | CATALOGS | CHANGE | CHAR | CHARACTER | CHECK | CLEAR | CLUSTER | CLUSTERED | CODEGEN | COLLATE | COLLECTION | COLUMN | COLUMNS | COMMENT | COMMIT | COMPACT | COMPACTIONS | COMPUTE | CONCATENATE | CONSTRAINT | COST | CREATE | CUBE | CURRENT | CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP | CURRENT_USER | DATA | DATABASE | DATABASES | DATE | DATEADD | DATE_ADD | DATEDIFF | DATE_DIFF | DAY | DAYS | DAYOFYEAR | DBPROPERTIES | DEC | DECIMAL | DEFAULT | DEFINED | DELETE | DELIMITED | DESC | DESCRIBE | DFS | DIRECTORIES | DIRECTORY | DISTINCT | DISTRIBUTE | DISTRIBUTED | DIV | DOUBLE | DROP | ELSE | END | ESCAPE | ESCAPED | EXCHANGE | EXCLUDE | EXISTS | EXPLAIN | EXPORT | EXTENDED | EXTERNAL | EXTRACT | FALSE | FETCH | FILTER | FIELD | FIELDS | FILEFORMAT | FIRST | FLOAT | FOLLOWING | FOR | FOREIGN | FORMAT | FORMATTED | FROM | FUNCTION | FUNCTIONS | GENERATED | GLOBAL | GRANT | GROUP | GROUPING | HAVING | HOUR | HOURS | IDENTIFIER_KW | IF | IGNORE | IMPORT | IN | INCLUDE | INDEX | INDEXES | INPATH | INPUTFORMAT | INSERT | INT | INTEGER | INTERVAL | INTO | IS | ITEMS | KEYS | LAST | LAZY | LEADING | LIKE | LONG | ILIKE | LIMIT | LINES | LIST | LOAD | LOCAL | LOCATION | LOCK | LOCKS | LOGICAL | LONG | LOCALLY | MACRO | MAP | MATCHED | MERGE | MICROSECOND | MICROSECONDS | MILLISECOND | MILLISECONDS | MINUTE | MINUTES | MONTH | MONTHS | MSCK | NAME | NAMESPACE | NAMESPACES | NANOSECOND | NANOSECONDS | NO | NOT | NULL | NULLS | NUMERIC | OF | OFFSET | ONLY | OPTION | OPTIONS | OR | ORDER | ORDERED | OUT | OUTER | OUTPUTFORMAT | OVER | OVERLAPS | OVERLAY | OVERWRITE | PARTITION | PARTITIONED | PARTITIONS | PERCENTILE_CONT | PERCENTILE_DISC | PERCENTLIT | PIVOT | PLACING | POSITION | PRECEDING | PRIMARY | PRINCIPALS | PROPERTIES | PURGE | QUARTER | QUERY | RANGE | REAL | RECORDREADER | RECORDWRITER | RECOVER | REDUCE | REFERENCES | REFRESH | RENAME | REPAIR | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | RETAIN | RETENTION | REVOKE | RLIKE | ROLE | ROLES | ROLLBACK | ROLLUP | ROW | ROWS | SNAPSHOT | SNAPSHOTS | SCHEMA | SCHEMAS | SECOND | SECONDS | SELECT | SEPARATED | SERDE | SERDEPROPERTIES | SESSION_USER | SET | SETS | SHORT | SHOW | SKEWED | SMALLINT | SOME | SORT | SORTED | SOURCE | START | STATISTICS | STORED | STRATIFY | STRING | STRUCT | SUBSTR | SUBSTRING | SYNC | SYSTEM_TIME | SYSTEM_VERSION | TABLE | TABLES | TABLESAMPLE | TAG | TARGET | TBLPROPERTIES | TEMPORARY | TERMINATED | THEN | TIME | TIMESTAMP | TIMESTAMP_LTZ | TIMESTAMP_NTZ | TIMESTAMPADD | TIMESTAMPDIFF | TINYINT | TO | TOUCH | TRAILING | TRANSACTION | TRANSACTIONS | TRANSFORM | TRIM | TRUE | TRUNCATE | TRY_CAST | TYPE | UNARCHIVE | UNBOUNDED | UNCACHE | UNIQUE | UNKNOWN | UNLOCK | UNPIVOT | UNSET | UPDATE | USE | USER | UNORDERED | VALUES | VARCHAR | VERSION | VIEW | VIEWS | VOID | WEEK | WEEKS | WHEN | WHERE | WINDOW | WITH | WITHIN | WRITE | YEAR | YEARS | ZONE | COMPRESSION | FILE | HELP | LIFECYCLE | DATATUNNEL | DISTCP | SINK | CALL | OWNER | SIZE_LIMIT | SINGLE | MAX_FILE_SIZE | INCLUDING | EXCLUDING | VACUUM | INVENTORY | DRY | RUN | OPTIMIZE | ZORDER | DETAIL | HISTORY | FEATURE | NONE | IDENTITY //--DEFAULT-NON-RESERVED-END ; ================================================ FILE: superior-spark-parser/src/main/antlr4/io/github/melin/superior/parser/spark/antlr4/SparkStreamSqlLexer.g4 ================================================ lexer grammar SparkStreamSqlLexer; channels { DCSTREAMCOMMENT, ERRORCHANNEL } // SKIP SPACE: [ \t\r\n]+ -> channel(HIDDEN); SPEC_MYSQL_COMMENT: '/*!' .+? '*/' -> channel(DCSTREAMCOMMENT); COMMENT_INPUT: '/*' .*? '*/' -> channel(HIDDEN); LINE_COMMENT: ( ('-- ' | '#') ~[\r\n]* ('\r'? '\n' | EOF) | '--' ('\r'? '\n' | EOF) ) -> channel(HIDDEN); // Keywords // Common Keywords CREATE: 'CREATE'; TABLE: 'TABLE'; STREAM: 'STREAM'; WITH: 'WITH'; COMMENT: 'COMMENT'; TRUE: 'TRUE'; FALSE: 'FALSE'; AS: 'AS'; BY: 'BY'; SET: 'SET'; DELAY: 'DELAY'; INSERT: 'INSERT'; INTO: 'INTO'; USING: 'USING'; PATTERN: 'PATTERN'; MINUSMINUS: '--'; // DATA TYPE Keywords STRING: 'STRING'; BOOLEAN: 'BOOLEAN'; INT: 'INT'; BIGINT: 'BIGINT'; FLOAT: 'FLOAT'; DOUBLE: 'DOUBLE'; DATE: 'DATE'; TIMESTAMP: 'TIMESTAMP'; // Operators. Arithmetics STAR: '*'; DIVIDE: '/'; MODULE: '%'; PLUS: '+'; MINUS: '-'; // Operators. Comparation EQUAL_SYMBOL: '='; GREATER_SYMBOL: '>'; LESS_SYMBOL: '<'; EXCLAMATION_SYMBOL: '!'; // Operators. Bit BIT_NOT_OP: '~'; BIT_OR_OP: '|'; BIT_AND_OP: '&'; BIT_XOR_OP: '^'; // Constructors symbols DOT: '.'; LR_BRACKET: '('; RR_BRACKET: ')'; COMMA: ','; SEMI: ';'; ID: ID_LITERAL; REVERSE_QUOTE_ID: '`' ~'`'+ '`'; STRING_LITERAL: DQUOTA_STRING | SQUOTA_STRING; DECIMAL_LITERAL: DEC_DIGIT+; REAL_LITERAL: (DEC_DIGIT+)? '.' DEC_DIGIT+ | DEC_DIGIT+ '.' EXPONENT_NUM_PART | (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART) | DEC_DIGIT+ EXPONENT_NUM_PART; fragment EXPONENT_NUM_PART: 'E' '-'? DEC_DIGIT+; fragment ID_LITERAL: [A-Z_$0-9]*?[A-Z_$]+?[A-Z_$0-9]*; fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"'; fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\''; fragment DEC_DIGIT: [0-9]; ERROR_RECONGNIGION: . -> channel(ERRORCHANNEL); ================================================ FILE: superior-spark-parser/src/main/antlr4/io/github/melin/superior/parser/spark/antlr4/SparkStreamSqlParser.g4 ================================================ parser grammar SparkStreamSqlParser; options { tokenVocab=SparkStreamSqlLexer; } root : sqlStatements? MINUSMINUS? EOF ; sqlStatements : (sqlStatement MINUSMINUS? SEMI | emptyStatement)* (sqlStatement (MINUSMINUS? SEMI)? | emptyStatement) ; sqlStatement : createStreamTable | insertStatement | setStatement ; createStreamTable : CREATE STREAM TABLE tableName=tableIdentifier ('(' columns=colTypeList ')')? WITH tableProps=tablePropertyList ; insertStatement : INSERT INTO tableName=tableIdentifier select = selectExpr ; setStatement : SET setKeyExpr EQUAL_SYMBOL valueKeyExpr ; emptyStatement : SEMI ; setKeyExpr : ID ('.' ID)* ; valueKeyExpr : word (word)* ; selectExpr : word (word)* ; word : ID | ('.' ID) | STRING_LITERAL | DECIMAL_LITERAL | REAL_LITERAL | booleanValue | AS | BY | SET | STAR | DIVIDE | MODULE | PLUS | MINUS | EQUAL_SYMBOL | GREATER_SYMBOL | LESS_SYMBOL | EXCLAMATION_SYMBOL | BIT_NOT_OP | BIT_OR_OP | BIT_AND_OP | BIT_XOR_OP | LR_BRACKET | RR_BRACKET | COMMA | TABLE ; colTypeList : colType (',' colType)* ; colType : ID (jsonPath=STRING_LITERAL)? dataType (PATTERN pattern=STRING_LITERAL)? (COMMENT comment=STRING_LITERAL)? ; dataType : STRING | BOOLEAN | INT | BIGINT | FLOAT | DOUBLE | DATE | TIMESTAMP ; tablePropertyList : '(' tableProperty (',' tableProperty)* ')' ; tableProperty : key=tablePropertyKey EQUAL_SYMBOL value=tablePropertyValue ; tablePropertyKey : ID ('.' ID)* | STRING_LITERAL ; tablePropertyValue : DECIMAL_LITERAL | booleanValue | STRING_LITERAL ; booleanValue : TRUE | FALSE ; tableIdentifier : (db=identifier '.')? table=identifier ; identifier : ID ; ================================================ FILE: superior-spark-parser/src/main/java/io/github/melin/superior/parser/spark/SparkSqlPostProcessor.java ================================================ package io.github.melin.superior.parser.spark; import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser; import io.github.melin.superior.parser.spark.antlr4.SparkSqlParserBaseListener; import org.antlr.v4.runtime.CommonToken; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.Pair; public class SparkSqlPostProcessor extends SparkSqlParserBaseListener { /** Remove the back ticks from an Identifier. */ @Override public void exitQuotedIdentifier(SparkSqlParser.QuotedIdentifierContext ctx) { ParserRuleContext parent = ctx.getParent(); parent.removeLastChild(); Token token = (Token) ctx.getChild(0).getPayload(); CommonToken commonToken = new CommonToken( new org.antlr.v4.runtime.misc.Pair(token.getTokenSource(), token.getInputStream()), SparkSqlParser.IDENTIFIER, token.getChannel(), token.getStartIndex() + 1, token.getStopIndex() - 1); commonToken.setText(commonToken.getText().replace("``", "`")); parent.addChild(commonToken); } /** Treat non-reserved keywords as Identifiers. */ @Override public void exitNonReserved(SparkSqlParser.NonReservedContext ctx) { ParserRuleContext parent = ctx.getParent(); parent.removeLastChild(); Token token = (Token) ctx.getChild(0).getPayload(); parent.addChild(new CommonToken( new Pair(token.getTokenSource(), token.getInputStream()), SparkSqlParser.IDENTIFIER, token.getChannel(), token.getStartIndex() + 0, token.getStopIndex() - 0)); } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/AbstractSparkStreamSqlParser.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.spark.antlr4.SparkStreamSqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSparkStreamSqlParser { private val parserCaches = AtomicReference(AntlrCaches(SparkStreamSqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: SparkStreamSqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(SparkStreamSqlParser._ATN)) } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(SparkSqlParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: SparkSqlParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(SparkSqlParser._ATN)) } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/SparkSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.spark import com.github.melin.superior.sql.parser.util.CommonUtils import com.google.common.collect.Lists import io.github.melin.superior.common.AlterActionType import io.github.melin.superior.common.AlterActionType.* import io.github.melin.superior.common.SQLParserException import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.TableType import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.* import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.delta.OptimizeTable import io.github.melin.superior.common.relational.delta.VacuumTable import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.common.relational.drop.DropFunction import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.common.relational.drop.DropView import io.github.melin.superior.common.relational.io.ExportTable import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.common.relational.table.RepairTable import io.github.melin.superior.common.relational.table.TruncateTable import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.AlterColumnActionContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.ColDefinitionOptionContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.CreateOrReplaceTableColTypeListContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.CreateTableClausesContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.DtColPropertyContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.DtPropertyContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.DtPropertyListContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.FromClauseContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.HintContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.IdentifierContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.InsertIntoContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.MultiInsertQueryContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.PartitionSpecContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.PropertyListContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.QueryContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.SingleInsertQueryContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser.TableProviderContext import io.github.melin.superior.parser.spark.antlr4.SparkSqlParserBaseVisitor import io.github.melin.superior.parser.spark.relational.* import java.util.LinkedList import java.util.regex.Pattern import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils class SparkSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : SparkSqlParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var currentAlterActionType: AlterActionType = UNKOWN private var multiInsertToken: String? = null private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var inCte = false private var cteTempTables: ArrayList = arrayListOf() private var functionNames: HashSet = hashSetOf() private var rows: ArrayList> = ArrayList() private var insertSql: Boolean = false private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitSqlStatements(ctx: SparkSqlParser.SqlStatementsContext): Statement? { ctx.singleStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSingleStatement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN currentAlterActionType = UNKOWN multiInsertToken = null limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() inCte = false cteTempTables = arrayListOf() functionNames = hashSetOf() rows = arrayListOf() insertSql = false } override fun visitSingleStatement(ctx: SparkSqlParser.SingleStatementContext): Statement? { val statement = super.visitSingleStatement(ctx) if (statement == null) { throw SQLParserException("不支持的SQL: " + command) } return statement } fun parseNamespace(ctx: SparkSqlParser.IdentifierReferenceContext): Pair { if (ctx.multipartIdentifier() == null) { throw IllegalAccessException("not support: " + source(ctx)) } else { return parseNamespace(ctx.multipartIdentifier()) } } fun parseNamespace(ctx: SparkSqlParser.MultipartIdentifierContext): Pair { return if (ctx.parts.size == 2) { Pair(ctx.parts.get(0).text, ctx.parts.get(1).text) } else if (ctx.parts.size == 1) { Pair(null, ctx.parts.get(0).text) } else { throw SQLParserException("parse multipart error: " + ctx.parts.size) } } fun parseTableName(ctx: SparkSqlParser.IdentifierReferenceContext): TableId { if (ctx.multipartIdentifier() == null) { throw IllegalAccessException("not support: " + source(ctx)) } else { return parseTableName(ctx.multipartIdentifier()) } } fun parseTableName(ctx: SparkSqlParser.MultipartIdentifierContext): TableId { return if (ctx.parts.size == 4) { TableId(ctx.parts.get(0).text, ctx.parts.get(1).text, ctx.parts.get(2).text, ctx.parts.get(3).text) } else if (ctx.parts.size == 3) { TableId(ctx.parts.get(0).text, ctx.parts.get(1).text, ctx.parts.get(2).text) } else if (ctx.parts.size == 2) { TableId(null, ctx.parts.get(0).text, ctx.parts.get(1).text) } else if (ctx.parts.size == 1) { TableId(null, null, ctx.parts.get(0).text) } else { throw SQLParserException("parse multipart error: " + ctx.parts.size) } } fun parseFunctionName(ctx: SparkSqlParser.MultipartIdentifierContext): FunctionId { return if (ctx.parts.size == 3) { FunctionId(ctx.parts.get(0).text, ctx.parts.get(1).text, ctx.parts.get(2).text) } else if (ctx.parts.size == 2) { FunctionId(null, ctx.parts.get(0).text, ctx.parts.get(1).text) } else if (ctx.parts.size == 1) { FunctionId(null, null, ctx.parts.get(0).text) } else { throw SQLParserException("parse multipart error: " + ctx.parts.size) } } fun parseIdentifier(ctx: List): String { return ctx.map { iden -> iden.text }.joinToString(",") } // -----------------------------------database------------------------------------------------- override fun visitCreateNamespace(ctx: SparkSqlParser.CreateNamespaceContext): Statement { var location: String = "" if (ctx.locationSpec().size > 0) { location = ctx.locationSpec().get(0).stringLit().text location = CommonUtils.cleanQuote(location) } val type = ctx.namespace().text.uppercase() if (StringUtils.equalsIgnoreCase("database", type) || StringUtils.equalsIgnoreCase("schema", type)) { val (catalogName, databaseName) = parseNamespace(ctx.identifierReference()) return CreateDatabase(catalogName, databaseName, location) } else { throw RuntimeException("not support: " + type) } } override fun visitDropNamespace(ctx: SparkSqlParser.DropNamespaceContext): Statement { val type = ctx.namespace().text.uppercase() if (StringUtils.equalsIgnoreCase("database", type) || StringUtils.equalsIgnoreCase("schema", type)) { val (catalogName, databaseName) = parseNamespace(ctx.identifierReference()) return DropDatabase(catalogName, databaseName) } else { throw RuntimeException("not support: " + type) } } // -----------------------------------table------------------------------------------------- override fun visitCreateTable(ctx: SparkSqlParser.CreateTableContext): Statement { val tableId = parseTableName(ctx.createTableHeader().identifierReference()) return createTable( tableId, false, ctx.createTableHeader().TEMPORARY() != null, ctx.createTableHeader().EXTERNAL() != null, ctx.createTableHeader().IF() != null, ctx.createOrReplaceTableColTypeList(), ctx.createTableClauses(), ctx.tableProvider(), ctx.query() ) } override fun visitReplaceTable(ctx: SparkSqlParser.ReplaceTableContext): Statement { val tableId = parseTableName(ctx.replaceTableHeader().identifierReference()) return createTable( tableId, true, false, false, false, ctx.createOrReplaceTableColTypeList(), ctx.createTableClauses(), ctx.tableProvider(), ctx.query() ) } private fun createTable( tableId: TableId, replace: Boolean, temporary: Boolean, external: Boolean, ifNotExists: Boolean, createOrReplaceTableColTypeList: CreateOrReplaceTableColTypeListContext?, createTableClauses: CreateTableClausesContext, tableProvider: TableProviderContext?, query: QueryContext? ): Statement { val comment = if (createTableClauses.commentSpec().size > 0) CommonUtils.cleanQuote(createTableClauses.commentSpec(0).stringLit().text) else null val lifeCycle = createTableClauses.lifecycle?.text?.toInt() var partitionColumnRels: List? = null val partitionColumnNames: ArrayList = arrayListOf() var columnRels: List? = null var modelType = "hive" if (query == null) { columnRels = createOrReplaceTableColTypeList?.createOrReplaceTableColType()?.map { val colName = it.colName.text val dataType = it.dataType().text val (nullable, defaultExpr, colComment) = parseColDefinition(it.colDefinitionOption()) ColumnRel(colName, dataType, colComment, nullable, defaultExpr) } if (tableProvider != null) { modelType = "spark" } if (createTableClauses.partitioning != null) { if ("spark" == modelType) { createTableClauses.partitioning.children .filter { it is SparkSqlParser.PartitionTransformContext } .forEach { item -> val column = item as SparkSqlParser.PartitionTransformContext partitionColumnNames.add(column.text) } if (partitionColumnNames.size == 0) { throw SQLParserException("spark create table 语法创建表,创建分区字段语法错误,请参考文档") } } else { partitionColumnRels = createTableClauses.partitioning.children .filter { it is SparkSqlParser.PartitionColumnContext } .map { item -> val column = item as SparkSqlParser.PartitionColumnContext val colName = column.colType().colName.text // primitiveDataType val dataType = column.colType().dataType().getChild(0).text checkPartitionDataType(dataType) partitionColumnNames.add(colName) val colComment = if (column.colType().commentSpec() != null) CommonUtils.cleanQuote(column.colType().commentSpec().stringLit().text) else null ColumnRel(colName, dataType, colComment) } } } } else { if (createTableClauses.partitioning != null) { createTableClauses.partitioning.children .filter { it is SparkSqlParser.PartitionTransformContext } .forEach { item -> val column = item as SparkSqlParser.PartitionTransformContext partitionColumnNames.add(column.text) } } } val properties = HashMap() val options = HashMap() if (createTableClauses.tableProps != null) { createTableClauses.tableProps.children .filter { it is SparkSqlParser.PropertyContext } .forEach { item -> val property = item as SparkSqlParser.PropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } } else if (createTableClauses.options != null) { createTableClauses.options.children .filter { it is SparkSqlParser.ExpressionPropertyContext } .forEach { item -> val property = item as SparkSqlParser.ExpressionPropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) options.put(key, value) } } var fileFormat = tableProvider?.multipartIdentifier()?.text var storageHandler: String? = null createTableClauses.createFileFormat() if (createTableClauses.createFileFormat().size == 1) { val createFileFormatContext = createTableClauses.createFileFormat().get(0) if (createFileFormatContext.fileFormat() != null) { fileFormat = createFileFormatContext.fileFormat().text } else if (createFileFormatContext.storageHandler() != null) { storageHandler = createFileFormatContext.storageHandler().stringLit().STRING_LITERAL().text storageHandler = CommonUtils.cleanQuote(storageHandler) } } if (query != null) { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val queryStmt = parseQuery(query) val createTable = CreateTableAsSelect( tableId, queryStmt, comment, lifeCycle, partitionColumnRels, columnRels, properties, fileFormat, ifNotExists ) createTable.modelType = modelType createTable.replace = replace createTable.options = options createTable.storageHandler = storageHandler if (partitionColumnNames.size > 0) { createTable.partitionColumnNames.addAll(partitionColumnNames) createTable.partitionType = PartitionType.LIST } return createTable } else { currentOptType = StatementType.CREATE_TABLE val createTable = CreateTable( tableId, TableType.HIVE, comment, lifeCycle, partitionColumnRels, columnRels, properties, fileFormat, ifNotExists ) createTable.modelType = modelType createTable.options = options createTable.replace = replace createTable.external = external createTable.temporary = temporary createTable.storageHandler = storageHandler if (createTableClauses.locationSpec().size > 0) { var location = createTableClauses.locationSpec().get(0).stringLit().text createTable.location = CommonUtils.cleanQuote(location); } if (partitionColumnNames.size > 0) { createTable.partitionColumnNames.addAll(partitionColumnNames) createTable.partitionType = PartitionType.LIST } return createTable } } override fun visitCreateTableLike(ctx: SparkSqlParser.CreateTableLikeContext): Statement { val newDatabaseName = ctx.target.db?.text val newTableName = ctx.target.table.text val oldDatabaseName = ctx.source.db?.text val oldTableName = ctx.source.table.text val createTableLike = CreateTableLike(TableId(oldDatabaseName, oldTableName), TableId(newDatabaseName, newTableName)) createTableLike.ifNotExists = ctx.NOT() != null return createTableLike } override fun visitDropTable(ctx: SparkSqlParser.DropTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val dropTable = DropTable(tableId) dropTable.ifExists = ctx.EXISTS() != null return dropTable } override fun visitDropView(ctx: SparkSqlParser.DropViewContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return DropView(tableId, ctx.EXISTS() != null) } override fun visitTruncateTable(ctx: SparkSqlParser.TruncateTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return TruncateTable(tableId) } override fun visitRepairTable(ctx: SparkSqlParser.RepairTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return RepairTable(tableId) } override fun visitRenameTable(ctx: SparkSqlParser.RenameTableContext): Statement { val tableId = parseTableName(ctx.from) val newTableId = parseTableName(ctx.to) return if (ctx.VIEW() != null) { val action = RenameAction(newTableId) AlterView(tableId, action) } else { val action = RenameAction(newTableId) AlterTable(tableId, action) } } override fun visitSetTableProperties(ctx: SparkSqlParser.SetTablePropertiesContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val properties = parseOptions(ctx.propertyList()) val action = AlterPropsAction() action.properties.putAll(properties) return if (ctx.VIEW() == null) { AlterTable(tableId, action) } else { AlterView(tableId, action) } } override fun visitSetTableSerDe(ctx: SparkSqlParser.SetTableSerDeContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val properties = parseOptions(ctx.propertyList()) val action = AlterSerDeAction(properties) return AlterTable(tableId, action) } override fun visitAddTableColumns(ctx: SparkSqlParser.AddTableColumnsContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val actions = ctx.columns.children .filter { it is SparkSqlParser.QualifiedColTypeWithPositionContext } .map { item -> val column = item as SparkSqlParser.QualifiedColTypeWithPositionContext val columnName = column.multipartIdentifier().text val dataType = column.dataType().text var comment: String? = null var position: String? = null var afterCol: String? = null column.colDefinitionDescriptorWithPosition().forEach { colDesc -> if (colDesc.commentSpec() != null) { comment = CommonUtils.cleanQuote(colDesc.commentSpec().stringLit().text) } else if (colDesc.colPosition() != null) { if (colDesc.colPosition() != null) { if (colDesc.colPosition().FIRST() != null) { position = "first" } else if (colDesc.colPosition().AFTER() != null) { position = "after" afterCol = colDesc.colPosition().afterCol.text } } } } AlterColumnAction(ADD_COLUMN, columnName, dataType, comment, position, afterCol) } val alterTable = AlterTable(tableId) alterTable.addActions(actions) return alterTable } override fun visitHiveChangeColumn(ctx: SparkSqlParser.HiveChangeColumnContext): Statement { val tableId = parseTableName(ctx.table) val columnName = ctx.colName.parts.get(0).text val newColumnName = ctx.colType().colName.text val dataType = ctx.colType().dataType().text val commentNode = ctx.colType().commentSpec()?.stringLit() val comment = if (commentNode != null) CommonUtils.cleanQuote(commentNode.text) else null val action = AlterColumnAction(ALTER_COLUMN, columnName, dataType, comment) action.newColumName = newColumnName if (ctx.colPosition() != null) { if (ctx.colPosition().FIRST() != null) { action.position = "first" } else if (ctx.colPosition().AFTER() != null) { action.position = "after" action.afterCol = ctx.colPosition().afterCol.text } } return AlterTable(tableId, action) } override fun visitRenameTableColumn(ctx: SparkSqlParser.RenameTableColumnContext): Statement { val tableId = parseTableName(ctx.table) val columnName = ctx.from.text val newColumnName = ctx.to.text val action = AlterColumnAction(RENAME, columnName) action.newColumName = newColumnName return AlterTable(tableId, action) } override fun visitAlterTableAlterColumn(ctx: SparkSqlParser.AlterTableAlterColumnContext): Statement { val tableId = parseTableName(ctx.table) val action = parseAlterColumnAction(ctx.alterColumnAction()) action.columName = ctx.column.text return AlterTable(tableId, action) } override fun visitTouchTable(ctx: SparkSqlParser.TouchTableContext): Statement { val tableId = parseTableName(ctx.table) val partitionVals = if (ctx.partitionSpec() != null) parsePartitionSpec(ctx.partitionSpec()) else null val action = AlterTouchPartitionAction(tableId, partitionVals) val alterTable = AlterTable(tableId, action) return alterTable } override fun visitDropTableColumns(ctx: SparkSqlParser.DropTableColumnsContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val columns = ctx.columns.multipartIdentifier().map { id -> id.text } val action = DropColumnAction(columns.joinToString(".")) return AlterTable(tableId, action) } override fun visitSetTableLocation(ctx: SparkSqlParser.SetTableLocationContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val location = CommonUtils.cleanQuote(ctx.locationSpec().stringLit().text) val action = AlterPropsAction(location) return AlterTable(tableId, action) } override fun visitMergeFile(ctx: SparkSqlParser.MergeFileContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val partitionVals = parsePartitionSpec(ctx.partitionSpec()) val properties = parseOptions(ctx.propertyList()) return MergeFileData(tableId, properties, partitionVals) } override fun visitRefreshTable(ctx: SparkSqlParser.RefreshTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return RefreshStatement(tableId) } override fun visitAnalyze(ctx: SparkSqlParser.AnalyzeContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return AnalyzeTable(listOf(tableId)) } override fun visitDistCpExpr(ctx: SparkSqlParser.DistCpExprContext): Statement { val options = parseDtOptions(ctx.options) val properties = parseDtOptions(ctx.properties) return DistCpExpr(options, properties) } override fun visitDatatunnelExpr(ctx: SparkSqlParser.DatatunnelExprContext): Statement { val sourceType = CommonUtils.cleanQuote(ctx.sourceName.text) val sinkType = CommonUtils.cleanQuote(ctx.sinkName.text) currentOptType = StatementType.DATATUNNEL if (ctx.ctes() != null) { visitCtes(ctx.ctes()) } val sourceOptions = parseDtOptions(ctx.sourceOpts) var transformSql: String? = null if (ctx.transfromSql != null) { transformSql = CommonUtils.cleanQuote(ctx.transfromSql.text) } val sinkOptions = parseDtOptions(ctx.sinkOpts) val properties = parseDtOptions(ctx.properties) val data = DataTunnelExpr(sourceType, sourceOptions, transformSql, sinkType, sinkOptions, properties) data.inputTables.addAll(inputTables) data.functionNames.addAll(functionNames) return data } override fun visitDatatunnelHelp(ctx: SparkSqlParser.DatatunnelHelpContext): Statement { val type = if (ctx.SOURCE() != null) "source" else "sink" val value = CommonUtils.cleanQuote(ctx.value.text) return DataTunnelHelp(type, value) } private fun parseDtOptions(ctx: DtPropertyListContext?): HashMap { val options = LinkedHashMap() if (ctx != null) { ctx.dtProperty().map { item -> val property = item as DtPropertyContext val key = CommonUtils.cleanQuote(property.key.text) if (property.value.columnDef().size > 0) { val list = arrayListOf>() property.value.columnDef().map { col -> val map = HashMap() col.dtColProperty().map { pt -> val colProperty = pt as DtColPropertyContext val colKey = CommonUtils.cleanQuote(colProperty.key.text) val colValue = CommonUtils.cleanQuote(colProperty.value.text) map.put(colKey, colValue) } list.add(map) } options.put(key, list) } else if (property.value.dtPropertyValue().size > 0) { val list = arrayListOf() property.value.dtPropertyValue().map { col -> val value = CommonUtils.cleanQuote(col.text) list.add(value) } options.put(key, list) } else { val value = CommonUtils.cleanQuote(property.value.text) options.put(key, value) } } } return options } override fun visitCall(ctx: SparkSqlParser.CallContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val properties = HashMap() ctx.callArgument() .filter { it.FAT_ARROW() != null } .forEach { item -> val key = CommonUtils.cleanQuote(item.identifier().text) val value = CommonUtils.cleanQuote(item.expression().text) properties.put(key.lowercase(), value) } return CallProcedure(ProcedureId(tableId.catalogName, tableId.schemaName, tableId.tableName), properties) } override fun visitCallHelp(ctx: SparkSqlParser.CallHelpContext): Statement { var procedure: String? = null if (ctx.callHelpExpr() != null) { procedure = if (ctx.callHelpExpr().callArgument() != null) { CommonUtils.cleanQuote(ctx.callHelpExpr().callArgument().expression().text) } else { ctx.callHelpExpr().identifier().text } } return CallHelp(procedure) } override fun visitSyncTableMeta(ctx: SparkSqlParser.SyncTableMetaContext): Statement { val syncType = ctx.dtType.text.lowercase() var owner: String? = null if (ctx.principal != null) { owner = ctx.principal.text } return if ("database" == syncType) { val source = parseNamespace(ctx.source) SyncDatabaseMetadata(source.first, source.second, owner) } else { val sourceTableId = parseTableName(ctx.source) SyncTableMetadata(sourceTableId, owner) } } // -----------------------------------partition------------------------------------------------- override fun visitAddTablePartition(ctx: SparkSqlParser.AddTablePartitionContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val partitions = ctx.partitionSpecLocation().map { parsePartitionSpec(it.partitionSpec()) } val ifNotExists = ctx.NOT() != null val action = AddPartitionAction(ifNotExists, partitions) return AlterTable(tableId, action) } override fun visitDropTablePartitions(ctx: SparkSqlParser.DropTablePartitionsContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val ifExists = ctx.EXISTS() != null val action = DropPartitionAction(ifExists) return AlterTable(tableId, action) } override fun visitRenameTablePartition(ctx: SparkSqlParser.RenameTablePartitionContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val fromPartition = parsePartitionSpec(ctx.from) val toPartition = parsePartitionSpec(ctx.to) val action = RenamePartitionAction(fromPartition, toPartition) return AlterTable(tableId, action) } // -----------------------------------view------------------------------------------------- override fun visitCreateView(ctx: SparkSqlParser.CreateViewContext): Statement { var comment: String? = null if (ctx.commentSpec().size > 0) { comment = ctx.commentSpec().get(0).stringLit().text comment = CommonUtils.cleanQuote(comment) } val tableId = parseTableName(ctx.identifierReference()) val ifNotExists = ctx.NOT() != null val queryStmt = parseQuery(ctx.query()) currentOptType = StatementType.CREATE_VIEW this.visitQuery(ctx.query()) val columnNameList = parseColumRefs(ctx.identifierCommentList()) val createView = CreateView(tableId, queryStmt, comment, ifNotExists, columnNameList) if (ctx.REPLACE() != null) { createView.replace = true } if (ctx.TEMPORARY() != null) { createView.temporary = true } if (ctx.GLOBAL() != null) { createView.global = true } return createView } override fun visitCreateTempViewUsing(ctx: SparkSqlParser.CreateTempViewUsingContext): Statement { val tableName = ctx.tableIdentifier().table.text var databaseName: String? = null if (ctx.tableIdentifier().db != null) { databaseName = ctx.tableIdentifier().db.text } currentOptType = StatementType.CREATE_TEMP_VIEW_USING val tableId = TableId(null, databaseName, tableName) val fileFormat = ctx.tableProvider().multipartIdentifier().text val properties = parseOptions(ctx.propertyList()) val createView = CreateTempViewUsing(tableId, fileFormat, properties) if (ctx.REPLACE() != null) { createView.replace = true } if (ctx.GLOBAL() != null) { createView.global = true } return createView } override fun visitAlterViewQuery(ctx: SparkSqlParser.AlterViewQueryContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val queryStmt = parseQuery(ctx.query()) currentAlterActionType = ALTER_VIEW_QUERY visitQuery(ctx.query()) val action = AlterViewAction(queryStmt) return AlterTable(tableId, action) } override fun visitCreateIndex(ctx: SparkSqlParser.CreateIndexContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val indexName = parseIdentifier(ctx.identifier()) val createIndex = CreateIndex(indexName) return AlterTable(tableId, createIndex) } override fun visitDropIndex(ctx: SparkSqlParser.DropIndexContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val indexName = ctx.identifier().text val dropIndex = DropIndex(indexName) return AlterTable(tableId, dropIndex) } // -----------------------------------function------------------------------------------------- override fun visitCreateFunction(ctx: SparkSqlParser.CreateFunctionContext): Statement { val functionId = parseFunctionName(ctx.identifierReference().multipartIdentifier()) val classNmae = ctx.className.text var temporary = false var file: String? = null if (ctx.TEMPORARY() != null) { temporary = true } else { file = ctx.resource(0).stringLit().text } val replace = if (ctx.REPLACE() != null) true else false return CreateFunction(functionId, arrayListOf(), replace, temporary, classNmae, file) } override fun visitDropFunction(ctx: SparkSqlParser.DropFunctionContext): Statement { val functionId = parseFunctionName(ctx.identifierReference().multipartIdentifier()) return DropFunction(functionId) } override fun visitDescribeNamespace(ctx: SparkSqlParser.DescribeNamespaceContext): Statement { if (ctx.namespace().NAMESPACE() != null) { return DescCatalog(ctx.identifierReference().multipartIdentifier().text) } else { val (catalogName, schemaName) = parseNamespace(ctx.identifierReference()) return DescSchema(SchemaId(catalogName, schemaName)) } } override fun visitDescribeFuncName(ctx: SparkSqlParser.DescribeFuncNameContext): Statement { val functionId = parseFunctionName(ctx.identifierReference().multipartIdentifier()) return DescFunction(functionId) } override fun visitDescribeQuery(ctx: SparkSqlParser.DescribeQueryContext): Statement { val query = parseQuery(ctx.query()) return DescQuery(query) } override fun visitDescribeRelation(ctx: SparkSqlParser.DescribeRelationContext): Statement { val tableId = parseTableName(ctx.identifierReference().multipartIdentifier()) return DescTable(tableId) } // -----------------------------------iceberg sql start ------------------------------------- override fun visitAddPartitionField(ctx: SparkSqlParser.AddPartitionFieldContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterTableAction(ADD_PARTITION_FIELD)) } override fun visitDropPartitionField(ctx: SparkSqlParser.DropPartitionFieldContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterTableAction(DROP_PARTITION_FIELD)) } override fun visitReplacePartitionField(ctx: SparkSqlParser.ReplacePartitionFieldContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterTableAction(REPLACE_PARTITION_FIELD)) } override fun visitSetWriteDistributionAndOrdering( ctx: SparkSqlParser.SetWriteDistributionAndOrderingContext ): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterTableAction(SET_WRITE_DISTRIBUTION_AND_ORDERING)) } override fun visitSetIdentifierFields(ctx: SparkSqlParser.SetIdentifierFieldsContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val fields = ctx.fieldList().fields.map { field -> field.text }.toList() return AlterTable(tableId, AlterSetIdentifierFieldsAction(fields)) } override fun visitDropIdentifierFields(ctx: SparkSqlParser.DropIdentifierFieldsContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val fields = ctx.fieldList().fields.map { field -> field.text }.toList() return AlterTable(tableId, AlterDropIdentifierFieldsAction(fields)) } override fun visitCreateOrReplaceTag(ctx: SparkSqlParser.CreateOrReplaceTagContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val tagName = CommonUtils.cleanQuote(ctx.createReplaceTagClause().identifier().text) return AlterTable(tableId, AlterCreateTagAction(tagName)) } override fun visitDropTag(ctx: SparkSqlParser.DropTagContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val tagName = CommonUtils.cleanQuote(ctx.identifier().text) return AlterTable(tableId, AlterDropTagAction(tagName)) } override fun visitCreateOrReplaceBranch(ctx: SparkSqlParser.CreateOrReplaceBranchContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val branchName = CommonUtils.cleanQuote(ctx.createReplaceBranchClause().identifier().text) return AlterTable(tableId, AlterCreateBranchAction(branchName)) } override fun visitDropBranch(ctx: SparkSqlParser.DropBranchContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val branchName = CommonUtils.cleanQuote(ctx.identifier().text) return AlterTable(tableId, AlterDropBranchAction(branchName)) } // -----------------------------------iceberg sql end ------------------------------------- // -----------------------------------delta sql start ------------------------------------- override fun visitVacuumTable(ctx: SparkSqlParser.VacuumTableContext): Statement { val tableId = parseTableName(ctx.table) return VacuumTable(tableId) } override fun visitOptimizeTable(ctx: SparkSqlParser.OptimizeTableContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return OptimizeTable(tableId) } override fun visitDescribeDeltaDetail(ctx: SparkSqlParser.DescribeDeltaDetailContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return DescDeltaDetail(tableId) } override fun visitDescribeDeltaHistory(ctx: SparkSqlParser.DescribeDeltaHistoryContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) if (ctx.limit != null) { return DescDeltaHistory(tableId, ctx.limit.text.toInt()) } else { return DescDeltaHistory(tableId) } } override fun visitAddTableConstraint(ctx: SparkSqlParser.AddTableConstraintContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterAddConstraintAction()) } override fun visitDropTableConstraint(ctx: SparkSqlParser.DropTableConstraintContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterDropConstraintAction()) } override fun visitAlterTableDropFeature(ctx: SparkSqlParser.AlterTableDropFeatureContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterDropFeatureAction()) } override fun visitAlterTableClusterBy(ctx: SparkSqlParser.AlterTableClusterByContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) return AlterTable(tableId, AlterClusterByAction()) } override fun visitAlterTableSyncIdentity(ctx: SparkSqlParser.AlterTableSyncIdentityContext): Statement { val tableId = parseTableName(ctx.table) return AlterTable(tableId, AlterSyncIdentityAction()) } // -----------------------------------delta sql start ------------------------------------- // -----------------------------------cache------------------------------------------------- override fun visitCacheTable(ctx: SparkSqlParser.CacheTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val options = parseOptions(ctx.propertyList()) if (ctx.query() != null) { val query = parseQuery(ctx.query()) return CacheTable(tableId, options, query) } else { return CacheTable(tableId, options) } } private fun parseQuery(ctx: QueryContext): QueryStmt { currentOptType = StatementType.SELECT this.visitQuery(ctx) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) var querySql = source(ctx) if (StringUtils.startsWith(querySql, "(") && StringUtils.endsWith(querySql, ")")) { querySql = StringUtils.substring(querySql, 1, -1) } queryStmt.setSql(querySql) return queryStmt } private fun parseFromClause(ctx: FromClauseContext): QueryStmt { currentOptType = StatementType.SELECT this.visitFromClause(ctx) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) var querySql = source(ctx) if (StringUtils.startsWith(querySql, "(") && StringUtils.endsWith(querySql, ")")) { querySql = StringUtils.substring(querySql, 1, -1) } queryStmt.setSql(querySql) return queryStmt } override fun visitUncacheTable(ctx: SparkSqlParser.UncacheTableContext): Statement { val tableId = parseTableName(ctx.identifierReference()) return UnCacheTable(tableId) } override fun visitClearCache(ctx: SparkSqlParser.ClearCacheContext?): Statement { return DefaultStatement(StatementType.CLEAR_CACHE) } // -----------------------------------other------------------------------------------------- override fun visitExplain(ctx: SparkSqlParser.ExplainContext?): Statement { return DefaultStatement(StatementType.EXPLAIN) } override fun visitCreateFileView(ctx: SparkSqlParser.CreateFileViewContext): Statement { val tableId = parseTableName(ctx.multipartIdentifier()) val path = CommonUtils.cleanQuote(ctx.path.text) var compression: String? = null var sizeLimit: String? = null val fileFormat = ctx.tableProvider().multipartIdentifier().text val causes = ctx.createFileViewClauses() if (causes != null) { if (causes.compressionName != null) compression = causes.compressionName.text if (causes.sizelimit != null) sizeLimit = causes.sizelimit.text } val properties = parseOptions(ctx.propertyList()) return CreateFileView(tableId, path, properties, fileFormat, compression, sizeLimit) } override fun visitLoadData(ctx: SparkSqlParser.LoadDataContext): Statement { val tableId = parseTableName(ctx.identifierReference()) val path = CommonUtils.cleanQuote(ctx.path.text) val local: Boolean = ctx.LOCAL() != null val mode: InsertMode = if (ctx.OVERWRITE() != null) InsertMode.OVERWRITE else InsertMode.INTO val partitionVals = parsePartitionSpec(ctx.partitionSpec()) return LoadData(tableId, path, local, partitionVals, mode) } override fun visitExportTable(ctx: SparkSqlParser.ExportTableContext): Statement { if (ctx.ctes() != null) { visitCtes(ctx.ctes()) } currentOptType = StatementType.EXPORT_TABLE super.visitExportTable(ctx) val tableId = parseTableName(ctx.multipartIdentifier()) val filePath = CommonUtils.cleanQuote(ctx.filePath.text) val properties = parseOptions(ctx.propertyList()) val partitionVals = parsePartitionSpec(ctx.partitionSpec()) var fileFormat: String? = null var compression: String? = null var maxFileSize: String? = null var overwrite: Boolean = false var single: Boolean = false val causes = ctx.exportTableClauses() if (causes != null) { if (causes.fileformatName != null) fileFormat = causes.fileformatName.text if (causes.compressionName != null) compression = causes.compressionName.text if (causes.maxfilesize != null) maxFileSize = causes.maxfilesize.text if (causes.overwrite != null) overwrite = causes.overwrite.TRUE() != null if (causes.single != null) single = causes.single.TRUE() != null } val exportTable = ExportTable( tableId, filePath, properties, partitionVals, fileFormat, compression, maxFileSize, overwrite, single, inputTables ) exportTable.functionNames.addAll(functionNames) return exportTable } override fun visitUse(ctx: SparkSqlParser.UseContext): Statement { val (catalogName, databaseName) = parseNamespace(ctx.identifierReference()) return UseDatabase(catalogName, databaseName) } override fun visitUseNamespace(ctx: SparkSqlParser.UseNamespaceContext): Statement { val type = ctx.namespace().text.uppercase() if (StringUtils.equalsIgnoreCase("database", type) || StringUtils.equalsIgnoreCase("schema", type)) { val (catalogName, databaseName) = parseNamespace(ctx.identifierReference()) return UseDatabase(catalogName, databaseName) } else if (StringUtils.equalsIgnoreCase("namespace", type)) { return UseCatalog(ctx.identifierReference().text) } else { throw RuntimeException("not support: " + type) } } override fun visitSetConfiguration(ctx: SparkSqlParser.SetConfigurationContext): Statement { return SetStatement(ctx.setKey().text) } override fun visitSetQuotedConfiguration(ctx: SparkSqlParser.SetQuotedConfigurationContext): Statement { assert(ctx.configValue() != null) if (ctx.setKey() != null) { val key = CommonUtils.cleanQuote(ctx.setKey().getText()) val value = CommonUtils.cleanQuote(ctx.configValue().getText()) return SetStatement(key, value) } else { throw SQLParserException("not support" + source(ctx)) } } override fun visitResetConfiguration(ctx: SparkSqlParser.ResetConfigurationContext): Statement { val key = StringUtils.trim(CommonUtils.subsql(command, ctx.RESET().symbol, ctx.stop)) return ReSetStatement(key) } // -----------------------------------insert & // query------------------------------------------------- override fun visitStatementDefault(ctx: SparkSqlParser.StatementDefaultContext): Statement? { val node = ctx.getChild(0) if (node is QueryContext) { currentOptType = StatementType.SELECT super.visitStatementDefault(ctx) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) return queryStmt } return null } override fun visitDmlStatement(ctx: SparkSqlParser.DmlStatementContext): Statement? { currentOptType = StatementType.INSERT val node = if (ctx.ctes() != null) { this.visitCtes(ctx.ctes()) ctx.getChild(1) } else { ctx.getChild(0) } if (node is SingleInsertQueryContext) { insertSql = true val queryStmt = parseQuery(node.query()) currentOptType = StatementType.INSERT val insertTable = parseInsertInto(node.insertInto(), queryStmt) insertTable.rows = rows return insertTable } else if (node is MultiInsertQueryContext) { val queryStmt = parseFromClause(node.fromClause()) currentOptType = StatementType.INSERT node.multiInsertQueryBody().forEach { this.visitMultiInsertQueryBody(it) } val insertTable = InsertTable(InsertMode.OVERWRITE, queryStmt, outputTables.first()) insertTable.outputTables.addAll(outputTables.subList(1, outputTables.size)) return insertTable } else if ( node is SparkSqlParser.UpdateTableContext || node is SparkSqlParser.DeleteFromTableContext || node is SparkSqlParser.MergeIntoTableContext ) { return super.visitDmlStatement(ctx) } else { return null } } private fun parseInsertInto(ctx: InsertIntoContext, queryStmt: QueryStmt): InsertTable { return if (ctx is SparkSqlParser.InsertIntoTableContext) { val tableId = parseTableName(ctx.identifierReference()) val partitionVals = parsePartitionSpec(ctx.partitionSpec()) var columnNameList: List? = null if (ctx.identifierList() != null) { columnNameList = ctx.identifierList().identifierSeq().ident.map { ColumnRel(CommonUtils.cleanQuote(it.text)) } } val stmt = InsertTable(InsertMode.INTO, queryStmt, tableId, columnNameList) stmt.partitionVals = partitionVals stmt.hints = parseHints(ctx.hints) stmt } else if (ctx is SparkSqlParser.InsertOverwriteTableContext) { val tableId = parseTableName(ctx.identifierReference()) val partitionVals = parsePartitionSpec(ctx.partitionSpec()) var columnNameList: List? = null if (ctx.identifierList() != null) { columnNameList = ctx.identifierList().identifierSeq().ident.map { ColumnRel(CommonUtils.cleanQuote(it.text)) } } val stmt = InsertTable(InsertMode.OVERWRITE, queryStmt, tableId, columnNameList) stmt.partitionVals = partitionVals stmt.hints = parseHints(ctx.hints) stmt } else if (ctx is SparkSqlParser.InsertIntoReplaceWhereContext) { val tableId = parseTableName(ctx.identifierReference()) InsertTable(InsertMode.INTO_REPLACE, queryStmt, tableId) } else if (ctx is SparkSqlParser.InsertOverwriteDirContext) { val path = if (ctx.path != null) CommonUtils.cleanQuote(ctx.path.STRING_LITERAL().text) else "" val properties = parseOptions(ctx.propertyList()) val fileFormat = ctx.tableProvider().multipartIdentifier().text val stmt = InsertTable(InsertMode.OVERWRITE_DIR, queryStmt, TableId(path)) stmt.properties = properties stmt.fileFormat = fileFormat stmt.hints = parseHints(ctx.hints) stmt } else if (ctx is SparkSqlParser.InsertOverwriteHiveDirContext) { val path = CommonUtils.cleanQuote(ctx.path.STRING_LITERAL().text) val stmt = InsertTable(InsertMode.OVERWRITE_HIVE_DIR, queryStmt, TableId(path)) stmt.hints = parseHints(ctx.hints) stmt } else { throw SQLParserException("not support insert into sql") } } // -----------------------------------delta sql------------------------------------------------- override fun visitDeleteFromTable(ctx: SparkSqlParser.DeleteFromTableContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.identifierReference()) super.visitWhereClause(ctx.whereClause()) return DeleteTable(tableId, inputTables) } override fun visitUpdateTable(ctx: SparkSqlParser.UpdateTableContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableName(ctx.identifierReference()) if (ctx.whereClause() != null) { super.visitWhereClause(ctx.whereClause()) } return UpdateTable(tableId, inputTables) } override fun visitMergeIntoTable(ctx: SparkSqlParser.MergeIntoTableContext): Statement { currentOptType = StatementType.MERGE val targetTable = parseTableName(ctx.target) val mergeTable = MergeTable(targetTable = targetTable) if (ctx.source != null) { val tableId = parseTableName(ctx.source) inputTables.add(tableId) } else if (ctx.sourceQuery != null && ctx.sourceQuery is QueryContext) { val query = ctx.sourceQuery as QueryContext super.visitQuery(query) } mergeTable.inputTables = inputTables return mergeTable } override fun visitManageResource(ctx: SparkSqlParser.ManageResourceContext): Statement { val resouceType = StringUtils.lowerCase(ctx.identifier().text) val rawArg = StringUtils.substring(command, ctx.identifier().stop.stopIndex + 1, ctx.stop.stopIndex + 1) val files = arrayListOf() if (StringUtils.isNotBlank(rawArg)) { val pattern = Pattern.compile("(\".*?[^\\\\]\"|'.*?[^\\\\]'|[^ \\n\\r\\t\"']+)") val matcher = pattern.matcher(rawArg) while (matcher.find()) { val match = matcher.group() files.add(CommonUtils.cleanQuote(match)) } } return if (ctx.ADD() != null) { AddResourceStatement(files, resouceType) } else { ListResourceStatement(files, resouceType) } } // -----------------------------------private // method------------------------------------------------- override fun visitFunctionCall(ctx: SparkSqlParser.FunctionCallContext): Statement? { val functionId = parseFunctionName(ctx.functionName()) if (functionId != null) { val args = ctx.functionArgument().map { CommonUtils.cleanQuote(it.text) }.toList() functionId.functionArguments = args functionNames.add(functionId) } return super.visitFunctionCall(ctx) } override fun visitFunctionTable(ctx: SparkSqlParser.FunctionTableContext): Statement? { val functionId = parseFunctionName(ctx.functionName()) if (functionId != null) { val args = ctx.functionTableArgument().map { CommonUtils.cleanQuote(it.text) }.toList() functionId.functionArguments = args functionId.funcType = "TVF" functionNames.add(functionId) } return super.visitFunctionTable(ctx) } private fun parseFunctionName(ctx: SparkSqlParser.FunctionNameContext): FunctionId? { if ( StatementType.SELECT == currentOptType || StatementType.CREATE_VIEW == currentOptType || StatementType.INSERT == currentOptType || StatementType.CREATE_TABLE_AS_SELECT == currentOptType || StatementType.MERGE == currentOptType || StatementType.EXPORT_TABLE == currentOptType || StatementType.DATATUNNEL == currentOptType ) { val names = ctx.qualifiedName().identifier() if (names.size == 3) { val catalog = StringUtils.lowerCase(names.get(0).text) val schema = StringUtils.lowerCase(names.get(1).text) val funcName = StringUtils.lowerCase(names.get(2).text) return FunctionId(catalog, schema, funcName) } else if (names.size == 2) { val schema = StringUtils.lowerCase(names.get(0).text) val funcName = StringUtils.lowerCase(names.get(1).text) return FunctionId(schema, funcName) } else if (names.size == 1) { val funcName = StringUtils.lowerCase(names.get(0).text) return FunctionId(funcName) } } return null } override fun visitCtes(ctx: SparkSqlParser.CtesContext): Statement? { inCte = true ctx.namedQuery().forEach { cteTempTables.add(TableId(it.name.text)) this.visitQuery(it.query()) } inCte = false return null } override fun visitMultipartIdentifier(ctx: SparkSqlParser.MultipartIdentifierContext): Statement? { val tableId = parseTableName(ctx) if ( currentOptType == StatementType.CREATE_TABLE_AS_SELECT || currentOptType == StatementType.SELECT || currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.INSERT || currentOptType == StatementType.MERGE || currentOptType == StatementType.EXPORT_TABLE || currentOptType == StatementType.DATATUNNEL || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentAlterActionType == ALTER_VIEW_QUERY ) { // 别名和表名一样的场景 if (inCte && cteTempTables.last() == tableId) { cteTempTables.remove(tableId) } if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } override fun visitRowConstructor(ctx: SparkSqlParser.RowConstructorContext): Statement? { val row = ctx.children .filter { it is SparkSqlParser.NamedExpressionContext } .map { var text = it.text text = CommonUtils.cleanQuote(text) text } .toList() rows.add(row) return null } override fun visitParenthesizedExpression(ctx: SparkSqlParser.ParenthesizedExpressionContext): Statement? { val row = ctx.children .filter { it is SparkSqlParser.ExpressionContext } .map { var text = it.text text = CommonUtils.cleanQuote(text) text } .toList() rows.add(row) return null } override fun visitFromClause(ctx: SparkSqlParser.FromClauseContext): Statement? { multiInsertToken = "from" return super.visitFromClause(ctx) } override fun visitMultiInsertQueryBody(ctx: SparkSqlParser.MultiInsertQueryBodyContext): Statement? { multiInsertToken = "insert" val obj = ctx.insertInto() if (obj is SparkSqlParser.InsertOverwriteTableContext) { val multipartIdentifier = obj.identifierReference() val tableId = parseTableName(multipartIdentifier) outputTables.add(tableId) } else if (obj is SparkSqlParser.InsertIntoTableContext) { val multipartIdentifier = obj.identifierReference() val tableId = parseTableName(multipartIdentifier) outputTables.add(tableId) } return null } override fun visitQueryOrganization(ctx: SparkSqlParser.QueryOrganizationContext): Statement? { limit = ctx.limit?.text?.toInt() offset = ctx.offset?.text?.toInt() return super.visitQueryOrganization(ctx) } override fun visitTypeConstructor(ctx: SparkSqlParser.TypeConstructorContext): Statement? { val valueType = ctx.literalType().getText().uppercase() if ( !("DATE".equals(valueType) || "TIME".equals(valueType) || "TIMESTAMP".equals(valueType) || "INTERVAL".equals(valueType) || "X".equals(valueType)) ) { throw SQLParserException("Literals of type " + valueType + " are currently not supported.") } return super.visitTypeConstructor(ctx) } private fun parseColDefinition(colDef: List): Triple { var nullable: Boolean = false var comment: String? = null var defaultExpr: String? = null if (colDef.size > 0) { colDef.forEach { col -> if (col.NULL() != null) { nullable = true } if (col.commentSpec() != null) { comment = CommonUtils.cleanQuote(col.commentSpec().stringLit().text) } if (col.defaultExpression() != null) { defaultExpr = StringUtils.substring( command, col.defaultExpression().start.startIndex, col.defaultExpression().stop.stopIndex + 1 ) if (defaultExpr != null) { defaultExpr = CommonUtils.cleanQuote(defaultExpr!!) } } } } return Triple(nullable, defaultExpr, comment) } private fun parseAlterColumnAction(context: AlterColumnActionContext): AlterColumnAction { val action = AlterColumnAction(ALTER_COLUMN) if (context.dataType() != null) { action.dataType = source(context.dataType()) } if (context.commentSpec() != null) { action.comment = CommonUtils.cleanQuote(context.commentSpec().stringLit().text) } if (context.colPosition() != null) { if (context.colPosition().FIRST() != null) { action.position = "first" } else if (context.colPosition().AFTER() != null) { action.position = "after" action.afterCol = context.colPosition().afterCol.text } } if (context.setOrDrop != null) { if (StringUtils.containsAnyIgnoreCase(context.setOrDrop.text, "drop")) { action.setOrDrop = "DROP" } else { action.setOrDrop = "SET" } if (context.NOT() != null) { action.nullable = false } } if (context.defaultExpression() != null) { val expr = context.defaultExpression().expression() action.defaultExpression = CommonUtils.cleanQuote(source(expr)) } if (context.dropDefault != null) { action.dropDefault = true } return action } /** 表列支持数据类型 */ private fun checkColumnDataType(dataType: String): Boolean { if (StringUtils.startsWithIgnoreCase(dataType, "decimal")) { return true } return when (dataType.lowercase()) { "string", "int", "bigint", "double", "date", "timestamp", "boolean" -> true else -> throw IllegalStateException("不支持数据类型:" + dataType) } } /** 分区支持数据类型 */ private fun checkPartitionDataType(dataType: String): Boolean { return when (dataType.lowercase()) { "string", "int", "bigint", "varchar", "date", "char" -> true else -> throw IllegalStateException("不支持数据类型:" + dataType) } } private fun parseOptions(ctx: PropertyListContext?): HashMap { val properties = HashMap() if (ctx != null) { ctx.property().forEach { item -> val property = item as SparkSqlParser.PropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } } return properties } private fun parsePartitionSpec(ctx: PartitionSpecContext?): LinkedHashMap { val partitions: LinkedHashMap = LinkedHashMap() if (ctx != null) { ctx.partitionVal().forEach { if (it.childCount == 1) { partitions.put(it.identifier().text, "__dynamic__") } else { var value = it.getChild(2).text value = CommonUtils.cleanQuote(value) partitions.put(it.identifier().text, value) } } } return partitions } private fun parseHints(hints: List): LinkedHashMap> { val partitions: LinkedHashMap> = LinkedHashMap() hints.forEach { it.hintStatements.forEach { if (it.parameters == null || it.parameters.size == 0) { partitions.put(it.hintName.text, Lists.newLinkedList()) } else { val parameters = Lists.newLinkedList() it.parameters.forEach { parameters.add(source(it)) } partitions.put(it.hintName.text, parameters) } } } return partitions } private fun parseColumRefs(columns: SparkSqlParser.IdentifierCommentListContext?): List? { var columnNameList: List? = null if (columns != null) { columnNameList = columns.identifierComment().map { val name = CommonUtils.cleanQuote(it.identifier().text) val commentText: String? = if (it.commentSpec() != null) CommonUtils.cleanQuote(it.commentSpec().stringLit().text) else null ColumnRel(name, comment = commentText) } } return columnNameList } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/SparkSqlHelper.kt ================================================ package io.github.melin.superior.parser.spark import com.github.melin.superior.sql.parser.util.CommonUtils.KEYWORD_REGEX import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.StatementType.* import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.spark.antlr4.SparkSqlLexer import io.github.melin.superior.parser.spark.antlr4.SparkSqlParser import io.github.melin.superior.parser.spark.antlr4.SparkSqlParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object SparkSqlHelper { @JvmStatic fun checkSupportedSQL(statementType: StatementType): Boolean { return when (statementType) { CREATE_DATABASE, CREATE_SCHEMA, CREATE_TABLE, CREATE_TABLE_AS_SELECT, CREATE_TABLE_AS_LIKE, TRUNCATE_TABLE, MERGE, REFRESH_TABLE, EXPORT_TABLE, ANALYZE_TABLE, ALTER_TABLE, REPAIR_TABLE, SELECT, INSERT, CREATE_FILE_VIEW, CREATE_VIEW, CREATE_FUNCTION, CREATE_TEMP_VIEW_USING, DROP_DATABASE, DROP_SCHEMA, DROP_VIEW, DROP_TABLE, DROP_FUNCTION, SHOW, CACHE, UNCACHE, CLEAR_CACHE, DATATUNNEL, CALL, HELP, MERGE_FILE, SYNC_META, SYNC_TABLE, SYNC_DATABASE, DELETE, UPDATE, VACUUM_TABLE, OPTIMIZE_TABLE, DESC_DELTA_DETAIL, DESC_DELTA_HISTORY, DESC_FUNCTION, DESC_CATALOG, DESC_SCHEMA, DESC_TABLE, DESC_QUERY, SET, EXPLAIN -> true else -> false } } @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until SparkSqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = SparkSqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = SparkSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = SparkSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = SparkSqlParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: SparkSqlParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = SparkSqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = SparkSqlParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.addParseListener(SparkSqlPostProcessor()) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visitSqlStatements(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visitSqlStatements(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/SparkStreamSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.spark import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.TableType import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.common.SetStatement import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.dml.InsertMode import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.parser.spark.antlr4.SparkStreamSqlParser import io.github.melin.superior.parser.spark.antlr4.SparkStreamSqlParserBaseVisitor class SparkStreamSqlAntlr4Visitor() : SparkStreamSqlParserBaseVisitor() { private val tableDatas = ArrayList() override fun visitSqlStatement(ctx: SparkStreamSqlParser.SqlStatementContext?): Statement { val tableData = super.visitSqlStatement(ctx) tableDatas.add(tableData) return tableData } override fun visitCreateStreamTable(ctx: SparkStreamSqlParser.CreateStreamTableContext): Statement { val tableName = ctx.tableName.table.ID().text val columns = if (ctx.columns != null) { ctx.columns.children .filter { it is SparkStreamSqlParser.ColTypeContext } .map { item -> val column = item as SparkStreamSqlParser.ColTypeContext val colName = column.ID().text val dataType = column.dataType().text val colComment = if (column.comment != null) CommonUtils.cleanQuote(column.comment.text) else null val jsonPath = if (column.jsonPath != null) CommonUtils.cleanQuote(column.jsonPath.text) else null // val pattern = if (column.pattern != null) // StringUtil.cleanQuote(column.pattern.text) else null val columnRel = ColumnRel(colName, dataType, colComment, true) columnRel.jsonPath = jsonPath columnRel } } else { emptyList() } val properties = HashMap() if (ctx.tableProps != null) { ctx.tableProps.children .filter { it is SparkStreamSqlParser.TablePropertyContext } .map { item -> val property = item as SparkStreamSqlParser.TablePropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } } return CreateTable(TableId(tableName), TableType.SPARK_STREAM, null, columns, false, properties) } override fun visitSetStatement(ctx: SparkStreamSqlParser.SetStatementContext): Statement { val key = ctx.setKeyExpr().text var value = CommonUtils.cleanQuote(ctx.valueKeyExpr().text) value = CommonUtils.cleanQuote(value) return SetStatement(key, value) } override fun visitInsertStatement(ctx: SparkStreamSqlParser.InsertStatementContext): Statement { val schemaName = if (ctx.tableName.db != null) ctx.tableName.db.ID().text else null val tableName = ctx.tableName.table.ID().text val tableId = TableId(schemaName, tableName) val queryStmt = QueryStmt() val querySql = source(ctx.select) queryStmt.setSql(querySql) val insertTable = InsertTable(InsertMode.INTO, queryStmt, tableId) return insertTable } fun getTableDatas(): ArrayList { return tableDatas } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/SparkStreamSqlHelper.kt ================================================ package io.github.melin.superior.parser.spark import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.spark.antlr4.SparkStreamSqlLexer import io.github.melin.superior.parser.spark.antlr4.SparkStreamSqlParser import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils object SparkStreamSqlHelper { @JvmStatic fun checkSupportedSQL(statementType: StatementType): Boolean { return when (statementType) { StatementType.CREATE_TABLE, StatementType.SET, StatementType.INSERT -> true else -> false } } @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until SparkStreamSqlLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = SparkStreamSqlLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): ArrayList { val trimCmd = StringUtils.trim(command) val charStream = UpperCaseCharStream(CharStreams.fromString(trimCmd)) val lexer = SparkStreamSqlLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = SparkStreamSqlParser(tokenStream) AbstractSparkStreamSqlParser.installCaches(parser) parser.addParseListener(SparkSqlPostProcessor()) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.interpreter.predictionMode = PredictionMode.LL val sqlVisitor = SparkStreamSqlAntlr4Visitor() try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sqlStatements()) return sqlVisitor.getTableDatas() } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.sqlStatements()) return sqlVisitor.getTableDatas() } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(trimCmd) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSparkStreamSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/CallHelp.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class CallHelp(val procedureName: String?) : Statement() { override val statementType = StatementType.HELP override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/CreateFileView.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class CreateFileView( override val tableId: TableId, val path: String, var properties: Map, var fileFormat: String? = null, val compression: String? = null, val sizeLimit: String? = null ) : AbsTableStatement() { override val statementType = StatementType.CREATE_FILE_VIEW override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/CreateTempViewUsing.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class CreateTempViewUsing( override val tableId: TableId, var fileFormat: String, var properties: Map, ) : AbsTableStatement() { override val statementType = StatementType.CREATE_TEMP_VIEW_USING override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DDL var replace: Boolean = false var global: Boolean = false } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/DataTunnelExpr.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class DataTunnelExpr( val sourceType: String, var sourceOptions: Map, val transformSql: String?, val sinkType: String, var sinkOptions: Map, var properties: Map, ) : Statement() { override val statementType = StatementType.DATATUNNEL override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DML val inputTables: ArrayList = arrayListOf() val functionNames: HashSet = hashSetOf() constructor( sourceType: String, sourceOptions: Map, transformSql: String?, sinkType: String, sinkOptions: Map ) : this(sourceType, sourceOptions, transformSql, sinkType, sinkOptions, mapOf()) } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/DataTunnelHelp.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class DataTunnelHelp(val type: String, val value: String) : Statement() { override val statementType = StatementType.HELP override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DDL } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/DistCpExpr.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class DistCpExpr(var options: Map, var properties: Map) : Statement() { override val statementType = StatementType.SPARK_DIST_CP override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML constructor(options: Map) : this(options, mapOf()) } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/LoadData.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement import io.github.melin.superior.common.relational.dml.InsertMode data class LoadData( override val tableId: TableId, val inPath: String, val local: Boolean, var partitionVals: LinkedHashMap, val mode: InsertMode = InsertMode.INTO ) : AbsTableStatement() { override val statementType = StatementType.LOAD_DATA override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/MergeFileData.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class MergeFileData( override val tableId: TableId, var properties: Map, var partitionVals: LinkedHashMap ) : AbsTableStatement() { override val statementType = StatementType.MERGE_FILE override val privilegeType = PrivilegeType.WRITE override val sqlType = SqlType.DML } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/RefreshStatement.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.abs.AbsTableStatement data class RefreshStatement(override val tableId: TableId) : AbsTableStatement() { override val statementType = StatementType.REFRESH_TABLE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.TCL } ================================================ FILE: superior-spark-parser/src/main/kotlin/io/github/melin/superior/parser/spark/relational/cache.kt ================================================ package io.github.melin.superior.parser.spark.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.dml.QueryStmt data class CacheTable(val tableId: TableId, var options: Map, val queryStmt: QueryStmt?) : Statement() { override val statementType = StatementType.CACHE override val privilegeType = PrivilegeType.READ override val sqlType = SqlType.DML constructor(tableId: TableId, options: Map) : this(tableId, options, null) } data class UnCacheTable(val tableId: TableId) : Statement() { override val statementType = StatementType.UNCACHE override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-spark-parser/src/test/kotlin/io/github/melin/superior/parser/spark/DeltaSqlExtensionsTest.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.common.DescDeltaDetail import io.github.melin.superior.common.relational.common.DescDeltaHistory import io.github.melin.superior.common.relational.delta.OptimizeTable import io.github.melin.superior.common.relational.delta.VacuumTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class DeltaSqlExtensionsTest { @Test fun vacuumTableTest() { val sql = """ VACUUM eventsTable DRY RUN; VACUUM eventsTable USING INVENTORY inventoryTable VACUUM eventsTable USING INVENTORY (select * from inventoryTable); """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) var vacuumTable = statements.first() as VacuumTable Assert.assertEquals(StatementType.VACUUM_TABLE, vacuumTable.statementType) Assert.assertEquals("eventsTable", vacuumTable.tableId.tableName) vacuumTable = statements.get(1) as VacuumTable Assert.assertEquals("eventsTable", vacuumTable.tableId.tableName) vacuumTable = statements.last() as VacuumTable Assert.assertEquals("eventsTable", vacuumTable.tableId.tableName) } @Test fun optimizeTableTest() { val sql = """ OPTIMIZE delta_table_name WHERE date >= '2017-01-01' OPTIMIZE delta_table_name ZORDER BY (eventType) """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) var optimizeTable = statements.first() as OptimizeTable Assert.assertEquals(StatementType.OPTIMIZE_TABLE, optimizeTable.statementType) Assert.assertEquals("delta_table_name", optimizeTable.tableId.tableName) optimizeTable = statements.last() as OptimizeTable Assert.assertEquals("delta_table_name", optimizeTable.tableId.tableName) } @Test fun descDeltaDetailTest() { val sql = """ DESCRIBE DETAIL eventsTable """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DescDeltaDetail) { Assert.assertEquals(StatementType.DESC_DELTA_DETAIL, statement.statementType) Assert.assertEquals("eventsTable", statement.tableId.tableName) } else { Assert.fail() } } @Test fun descDeltaHistoryTest() { val sql = """ DESCRIBE HISTORY eventsTable """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DescDeltaHistory) { Assert.assertEquals(StatementType.DESC_DELTA_HISTORY, statement.statementType) Assert.assertEquals("eventsTable", statement.tableId.tableName) } else { Assert.fail() } } } ================================================ FILE: superior-spark-parser/src/test/kotlin/io/github/melin/superior/parser/spark/IcebergSqlExtensionsTest.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.alter.* import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class IcebergSqlExtensionsTest { @Test fun createTagTest() { val sql = "ALTER TABLE prod.db.sample CREATE TAG `historical-tag`" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("sample", statement.tableId.tableName) Assert.assertEquals(AlterActionType.CREATE_TAG, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun dropTagTest() { val sql = "ALTER TABLE prod.db.sample DROP TAG `historical-tag`" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("sample", statement.tableId.tableName) Assert.assertEquals(AlterActionType.DROP_TAG, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun setIdentifierTest() { val sql = "ALTER TABLE prod.db.sample SET IDENTIFIER FIELDS id, data" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterSetIdentifierFieldsAction Assert.assertEquals(2, action.fields.size) Assert.assertEquals(AlterActionType.SET_IDENTIFIER_FIELDS, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun writeSpecTest() { val sql = "ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION LOCALLY ORDERED BY category, id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("sample", statement.tableId.tableName) Assert.assertEquals(AlterActionType.SET_WRITE_DISTRIBUTION_AND_ORDERING, statement.firstAction().alterType) } else { Assert.fail() } } } ================================================ FILE: superior-spark-parser/src/test/kotlin/io/github/melin/superior/parser/spark/SparkSqlParserTest.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.* import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.* import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.create.CreateView import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.* import io.github.melin.superior.common.relational.io.ExportTable import io.github.melin.superior.common.relational.table.* import io.github.melin.superior.parser.spark.relational.* import java.io.File import org.apache.commons.io.FileUtils import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class SparkSqlParserTest { @Test fun splitSqlTest() { val sql = """ CREATE DATABASE IF NOT EXISTS bigdata1; drop DATABASE IF EXISTS bigdata2 """ .trimIndent() val statements = SparkSqlHelper.splitSql(sql) Assert.assertEquals(2, statements.size) Assert.assertEquals("CREATE DATABASE IF NOT EXISTS bigdata1", statements.get(0)) } @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE IF NOT EXISTS bigdata1; drop DATABASE IF EXISTS bigdata2 """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("bigdata1", createDatabse.databaseName) Assert.assertEquals("CREATE DATABASE IF NOT EXISTS bigdata1", createDatabse.getSql()) } if (dropDatabase is CreateDatabase) { Assert.assertEquals("bigdata2", dropDatabase.databaseName) Assert.assertEquals("drop DATABASE IF EXISTS bigdata2", dropDatabase.getSql()) } } @Test fun createDatabaseTest2() { val sql = "CREATE DATABASE IF NOT EXISTS bigdata location 's3a://hive/s3/'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateDatabase) { Assert.assertEquals("bigdata", statement.databaseName) val location = statement.location Assert.assertEquals("s3a://hive/s3/", location) } else { Assert.fail() } } @Test fun dropDatabaseTest() { val sql = "drop DATABASE IF EXISTS bigdata" val statement = SparkSqlHelper.parseStatement(sql) if (statement is DropDatabase) { Assert.assertEquals("bigdata", statement.databaseName) } else { Assert.fail() } } @Test fun createTableTest() { val sql = """CREATE TABLE if not exists test.users ( name STRING COMMENT 'Employee name', address int COMMENT 'address', item1 double, item2 DECIMAL(9, 2), item3 TIMESTAMP, item4 BIGINT, item5 BOOLEAN ) COMMENT 'hello world' PARTITIONED BY (ds varchar(50) COMMENT 'part sdf') STORED AS ORC TBLPROPERTIES ('dataCenter'='hangzhou') lifecycle 7 """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val schemaName = statement.tableId.schemaName Assert.assertEquals("test", schemaName) Assert.assertEquals("hello world", statement.comment) Assert.assertNull(statement.location) Assert.assertFalse(statement.external) Assert.assertEquals(statement.fileFormat, "ORC") Assert.assertFalse(statement.temporary) Assert.assertEquals(7, statement.lifeCycle) Assert.assertEquals(PartitionType.LIST, statement.partitionType) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("ds", statement.partitionColumnNames.get(0)) Assert.assertEquals("part sdf", statement.partitionColumnRels?.get(0)?.comment) Assert.assertEquals(PartitionType.LIST, statement.partitionType) } else { Assert.fail() } } @Test fun createTableTest1() { val sql = """create table if not exists platformtool.test_users_dt( name string comment '姓名', address string comment '地址', image binary comment 'image' ) comment 'user info' PARTITIONED BY (ds string, event_type string) lifecycle 7 """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val schemaName = statement.tableId.schemaName Assert.assertEquals("platformtool", schemaName) Assert.assertEquals(7, statement.lifeCycle) Assert.assertEquals("姓名", statement.columnRels?.get(0)?.comment) Assert.assertEquals(TableType.HIVE, statement.tableType) Assert.assertEquals(2, statement.partitionColumnNames.size) Assert.assertEquals("ds", statement.partitionColumnNames.get(0)) Assert.assertEquals("event_type", statement.partitionColumnNames.get(1)) Assert.assertEquals(PartitionType.LIST, statement.partitionType) } else { Assert.fail() } } @Test fun createTableTest2() { val sql = """ CREATE TABLE dc_cluster_compute ( id bigint comment 'id', data_center string comment '数据中心', code string comment 'code', name string comment '集群名称' ) comment '计算集群' lifecycle 100; """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("dc_cluster_compute", tableName) Assert.assertEquals(100, statement.lifeCycle) Assert.assertEquals(TableType.HIVE, statement.tableType) Assert.assertEquals("数据中心", statement.columnRels?.get(1)?.comment) Assert.assertNull(statement.partitionType) } else { Assert.fail() } } @Test fun createTableTest3() { val sql = """ CREATE TABLE bigdata.iceberg_test_dt ( id bigint, data string) stored as iceberg PARTITIONED BY (ds string) lifecycle 100; """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("iceberg_test_dt", tableName) Assert.assertEquals(100, statement.lifeCycle) Assert.assertEquals(TableType.HIVE, statement.tableType) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("ds", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun createTableTest4() { val sql = """ CREATE TABLE `bigdata`.`export_test_dt` ( `message` STRING COMMENT '', `collect_time` TIMESTAMP COMMENT '', `ds` STRING COMMENT '') USING orc LOCATION 's3a://superior2025/iceberg/warehouse/aws_iceberg.db/iceberg_demo_1' PARTITIONED BY (ds) TBLPROPERTIES ( 'transient_lastDdlTime' = '1627281671') lifeCycle 100 """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("export_test_dt", tableName) Assert.assertEquals(100, statement.lifeCycle) Assert.assertEquals("orc", statement.fileFormat) Assert.assertEquals("spark", statement.modelType) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("ds", statement.partitionColumnNames.get(0)) Assert.assertEquals(statement.location, "s3a://superior2025/iceberg/warehouse/aws_iceberg.db/iceberg_demo_1") } else { Assert.fail() } } @Test fun createTableTest5() { val sql = """ CREATE TABLE `bigdata`.`export_test_dt` ( `message` STRING COMMENT '', `collect_time` TIMESTAMP COMMENT '', `the_date` STRING COMMENT '', `the_nums` STRING COMMENT '') USING orc PARTITIONED BY (the_date, the_nums) TBLPROPERTIES ( 'transient_lastDdlTime' = '1627288235') lifeCycle 100 """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("export_test_dt", tableName) Assert.assertEquals(100, statement.lifeCycle) Assert.assertEquals("orc", statement.fileFormat) Assert.assertEquals("spark", statement.modelType) Assert.assertEquals(2, statement.partitionColumnNames.size) Assert.assertEquals("the_date", statement.partitionColumnNames.get(0)) Assert.assertEquals("the_nums", statement.partitionColumnNames.get(1)) } else { Assert.fail() } } @Test fun createTableTest7() { val sql = """ CREATE TABLE test_demo_test (name string, age int) using orc LIFECYCLE 10; """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("test_demo_test", tableName) Assert.assertEquals(10, statement.lifeCycle) Assert.assertEquals("orc", statement.fileFormat) Assert.assertEquals("spark", statement.modelType) } else { Assert.fail() } } @Test fun createTableTest9() { val sql = """ create table dzlog_test_dt ( message string, collect_time timestamp ) using parquet partitioned by (ds string) lifeCycle 14; """ try { SparkSqlHelper.parseStatement(sql) Assert.fail() } catch (e: Exception) { Assert.assertTrue(true) } } @Test fun createTableTest10() { val sql = """ CREATE TABLE my_table USING io.github.spark_redshift_community.spark.redshift OPTIONS ( dbtable 'my_table', tempdir 's3n://path/for/temp/data', url 'jdbc:redshift://redshifthost:5439/database?user=username&password=pass' ); """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("io.github.spark_redshift_community.spark.redshift", statement.fileFormat) Assert.assertEquals("my_table", tableName) Assert.assertEquals(3, statement.options?.size) } else { Assert.fail() } } @Test fun createTableTest11() { val sql = """ CREATE TABLE my_table USING io.github.spark_redshift_community.spark.redshift OPTIONS ( dbtable 'my_table', tempdir 's3n://path/for/temp/data', url 'jdbc:redshift://redshifthost:5439/database?user=username&password=pass' ) AS SELECT * FROM tabletosave; """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertEquals("io.github.spark_redshift_community.spark.redshift", statement.fileFormat) Assert.assertEquals("my_table", tableName) Assert.assertEquals(3, statement.options?.size) Assert.assertEquals("SELECT * FROM tabletosave", statement.queryStmt.getSql()) } else { Assert.fail() } } @Test fun createTableTest12() { val sql = """ create table user(id Int, info String) clustered by (id) sorted by (id) into 4 buckets; """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("user", tableName) } else { Assert.fail() } } @Test fun createTableTest13() { val sql = """ CREATE TABLE cyj123.pipeline_normal99 ( id int, name string, class string, area_code int, pt string, is_delete int, age int ) STORED BY 'org.apache.paimon.hive.PaimonStorageHandler' TBLPROPERTIES ( 'table_type' = 'PAIMON', 'bucket' = '2', 'transient_lastDdlTime' = '1717400524' ) """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("pipeline_normal99", tableName) Assert.assertEquals("org.apache.paimon.hive.PaimonStorageHandler", statement.storageHandler) } else { Assert.fail() } } @Test fun createHudiTableTest5() { val sql = """ create table test_hudi_table ( id int, name string, price double, ts long, dt string) using hudi tblproperties ( type = 'MOR', primaryKey = 'id, name', preCombineField = 'ts' ) partitioned by (dt) lifeCycle 300 """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("test_hudi_table", tableName) Assert.assertEquals("id, name", statement.properties?.get("primaryKey")) Assert.assertEquals("MOR", statement.properties?.get("type")) Assert.assertEquals(300, statement.lifeCycle) Assert.assertEquals("hudi", statement.fileFormat) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("dt", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun createHudiTableTest6() { val sql = """ create table test_hudi_table ( id int, name string, price double, ts long, dt string) using hudi tblproperties ( type = 'cow', primaryKey = 'id, name', preCombineField = 'ts' ) partitioned by (dt) lifeCycle 300 """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val name = statement.tableId.tableName Assert.assertEquals("test_hudi_table", name) Assert.assertEquals("id, name", statement.properties?.get("primaryKey")) Assert.assertEquals("cow", statement.properties?.get("type")) Assert.assertEquals(300, statement.lifeCycle) Assert.assertEquals("hudi", statement.fileFormat) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("dt", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun createIcebergTable() { val sql = """ CREATE TABLE IF NOT EXISTS iceberg_melin.test_table_02 ( id bigint, data string, ds timestamp) USING iceberg PARTITIONED BY (days(ts)) lifeCycle 300 """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertEquals("test_table_02", tableName) Assert.assertEquals(300, statement.lifeCycle) Assert.assertEquals("iceberg", statement.fileFormat) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("days(ts)", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun replaceHudiTableTest() { val sql = """ create or replace table test_hudi_table ( id int, name string, price double, ts long, dt string) using hudi tblproperties ( type = 'mor', primaryKey = 'id, name', preCombineField = 'ts' ) partitioned by (dt) lifeCycle 300 """ val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) if (statement is CreateTable) { val tableName = statement.tableId.tableName Assert.assertTrue(statement.replace) Assert.assertEquals("test_hudi_table", tableName) Assert.assertEquals("id, name", statement.properties?.get("primaryKey")) Assert.assertEquals("mor", statement.properties?.get("type")) Assert.assertEquals(300, statement.lifeCycle) Assert.assertEquals("hudi", statement.fileFormat) Assert.assertEquals(1, statement.partitionColumnNames.size) Assert.assertEquals("dt", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun descTableTest0() { val sql = "desc table users" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.DESC_TABLE, statement.statementType) } @Test fun createTableLikeTest() { val sql = "create table IF NOT EXISTS test.sale_detail_like like demo.sale_detail" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableLike) { Assert.assertEquals(TableId("demo", "sale_detail"), statement.oldTableId) Assert.assertEquals(TableId("test", "sale_detail_like"), statement.tableId) } else { Assert.fail() } } @Test fun createTableSelectTest() { val sql = "create table \nIF NOT EXISTS tdl_users_1 STORED AS ORC as select *, bigdata.TEST(name) from bigdata.users a left outer join address b on a.addr_id = b.id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals(statement.fileFormat, "ORC") Assert.assertEquals("tdl_users_1", statement.tableId.tableName) Assert.assertEquals( "select *, bigdata.TEST(name) from bigdata.users a left outer join address b on a.addr_id = b.id", statement.queryStmt.getSql() ) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("users", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) Assert.assertTrue(statement.ifNotExists) Assert.assertEquals(FunctionId("bigdata", "test"), statement.queryStmt.functionNames.first()) } else { Assert.fail() } } @Test fun createTableSelectTest1() { val sql = """ CREATE TABLE t USING ICEBERG PARTITIONED BY (b) AS SELECT 1 as a, "a" as b """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("ICEBERG", statement.fileFormat) Assert.assertEquals("t", tableName) Assert.assertEquals("SELECT 1 as a, \"a\" as b", statement.queryStmt.getSql()) Assert.assertEquals("b", statement.partitionColumnNames.get(0)) } else { Assert.fail() } } @Test fun createTableSelectTest2() { val sql = "create table \nIF NOT EXISTS tdl_users_1 using parquet as (select * from users a left outer join address b on a.addr_id = b.id)" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("tdl_users_1", tableName) Assert.assertEquals( "select * from users a left outer join address b on a.addr_id = b.id", statement.queryStmt.getSql() ) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("parquet", statement.fileFormat) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) } else { Assert.fail() } } @Test fun createTableSelectTest3() { val sql = "create table \nIF NOT EXISTS tdl_users_1 using parquet as (select * from users a left outer join address b on a.addr_id = b.id" + " left outer join `bigdata`.users c on c.userid_id = a.id)" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("tdl_users_1", tableName) // Assert.assertEquals("select * from users a left outer join address b on a.addr_id = // b.id", // statement.querySql) Assert.assertEquals(3, statement.queryStmt.inputTables.size) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) } else { Assert.fail() } } @Test fun createTableSelectTest4() { val sql = "create table huaixin_rp.bigdata.test_iceberg_1 using iceberg PARTITIONED BY(ds) as " + "SELECT 'xxx' as name, 23 as price, '20211203' as ds" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("test_iceberg_1", tableName) Assert.assertEquals("SELECT 'xxx' as name, 23 as price, '20211203' as ds", statement.queryStmt.getSql()) } else { Assert.fail() } } @Test fun replaceTableSelectTest() { val sql = "create or replace table tdl_users_1 STORED AS ORC as select * from bigdata.users a left outer join address b on a.addr_id = b.id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { val tableName = statement.tableId.tableName Assert.assertTrue(statement.replace) Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals(statement.fileFormat, "ORC") Assert.assertEquals("tdl_users_1", tableName) Assert.assertEquals( "select * from bigdata.users a left outer join address b on a.addr_id = b.id", statement.queryStmt.getSql() ) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("users", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) } else { Assert.fail() } } @Test fun dropTableTest() { val sql = "drop table if exists sale_detail_drop2" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) if (statement is DropTable) { val name = statement.tableId?.tableName Assert.assertEquals("sale_detail_drop2", name) } else { Assert.fail() } } @Test fun dropViewTest() { val sql = "drop view if exists sale_detail_drop2" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.DROP_VIEW, statement.statementType) if (statement is DropView) { Assert.assertEquals("sale_detail_drop2", statement.tableId?.tableName) } else { Assert.fail() } } @Test fun truncateTableTest() { val sql = "TRUNCATE TABLE test.user partition(ds='20170403')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is TruncateTable) { val name = statement.tableId.tableName Assert.assertEquals("user", name) } else { Assert.fail() } } @Test fun msckTableTest() { val sql = "MSCK REPAIR TABLE test.user" val statement = SparkSqlHelper.parseStatement(sql) if (statement is RepairTable) { val name = statement.tableId.tableName Assert.assertEquals("user", name) } else { Assert.fail() } } @Test fun createViewTest0() { val sql = """CREATE View view_users comment 'view test' as select * from account """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("view_users", statement.tableId.tableName) Assert.assertEquals("view test", statement.comment) Assert.assertEquals("select * from account", statement.queryStmt.getSql()) } else { Assert.fail() } } @Test fun createViewTest1() { val sql = """CREATE View if not exists view_users comment 'view test' as select *, bigdata.test(name) from account """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(StatementType.CREATE_VIEW, statement.statementType) Assert.assertEquals("view_users", statement.tableId.tableName) Assert.assertEquals("view test", statement.comment) Assert.assertEquals(1, statement.queryStmt.functionNames.size) Assert.assertEquals(FunctionId("bigdata", "test"), statement.queryStmt.functionNames.first()) Assert.assertEquals("select *, bigdata.test(name) from account", statement.queryStmt.getSql()) Assert.assertEquals("account", statement.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun createTemporaryViewTest0() { val sql = """ CREATE TEMPORARY VIEW jdbcTable USING org.apache.spark.sql.jdbc OPTIONS ( url "jdbc:postgresql:dbserver", dbtable "schema.tablename", user 'username', password 'password' ) """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTempViewUsing) { Assert.assertEquals(StatementType.CREATE_TEMP_VIEW_USING, statement.statementType) Assert.assertEquals("jdbcTable", statement.tableId.tableName) Assert.assertEquals("org.apache.spark.sql.jdbc", statement.fileFormat) Assert.assertEquals(4, statement.properties.size) } else { Assert.fail() } } @Test fun alterViewTest0() { val sql = "ALTER VIEW v1 AS SELECT x, UPPER(s) s FROM t2" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("v1", statement.tableId.tableName) val action = statement.firstAction() as AlterViewAction Assert.assertEquals(AlterActionType.ALTER_VIEW_QUERY, statement.firstAction().alterType) Assert.assertEquals("SELECT x, UPPER(s) s FROM t2", action.queryStmt.getSql()) Assert.assertEquals("t2", action.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun renameTableTest() { val sql = "alter table test.table_name rename to new_table_name" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { val action = statement.firstAction() as RenameAction Assert.assertEquals(AlterActionType.RENAME, action.alterType) Assert.assertEquals("new_table_name", action.newTableId.tableName) } else { Assert.fail() } } @Test fun touchTableTest() { val sql = "alter table test.table_name TOUCH" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("table_name", statement.tableId.tableName) Assert.assertEquals(AlterActionType.TOUCH_TABLE, statement.firstAction().alterType) } else { Assert.fail() } } @Test fun touchTablePrtitionTest() { val sql = "alter table test.table_name TOUCH partition(ds=20210812, type='login')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("table_name", statement.tableId.tableName) val action = statement.firstAction() as AlterTouchPartitionAction Assert.assertEquals(AlterActionType.TOUCH_TABLE, action.alterType) Assert.assertEquals(2, action.partitionVals?.size) } else { Assert.fail() } } @Test fun alterTablePropertiesTest() { var sql = "ALTER TABLE test.sale_detail SET TBLPROPERTIES ('comment' = 'new coments for statement sale_detail', 'lifeCycle' = '7')" var statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sale_detail", statement.tableId.tableName) val action = statement.firstAction() as AlterPropsAction Assert.assertEquals(2, action.properties.size) } else { Assert.fail() } sql = "ALTER TABLE aaa.bbb SET SERDEPROPERTIES ('field.delim' = ',')" statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("bbb", statement.tableId.tableName) val action = statement.firstAction() as AlterSerDeAction Assert.assertEquals(1, action.properties.size) } else { Assert.fail() } } @Test fun addColumnsTest() { val sql = "alter table test.sale_detail add columns (col_name1 string comment 'col_name1', col_name2 string comment 'col_name2')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sale_detail", statement.tableId.tableName) val cols = statement.actions as List Assert.assertEquals(2, cols.size) } else { Assert.fail() } } @Test fun addColumnTest() { val sql = "ALTER TABLE db.sample ADD COLUMN age int FIRST" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("first", action.position) } else { Assert.fail() } } @Test fun renameColumnTest() { val sql = "ALTER TABLE db.sample RENAME COLUMN data TO payload" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("payload", action.newColumName) } else { Assert.fail() } } @Test fun changeColumnTest() { var sql = "ALTER TABLE db.sample ALTER COLUMN location.lat TYPE double" var statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("double", action.dataType) } else { Assert.fail() } sql = "ALTER TABLE db.sample ALTER COLUMN id DROP NOT NULL" statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("id", action.columName) } else { Assert.fail() } sql = "ALTER TABLE db.sample ALTER COLUMN point.z AFTER y" statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("after", action.position) Assert.assertEquals("y", action.afterCol) } else { Assert.fail() } sql = "ALTER TABLE db.sample ALTER COLUMN id COMMENT 'unique id'" statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("unique id", action.comment) } else { Assert.fail() } sql = "ALTER TABLE demo CHANGE COLUMN price Type float COMMENT '价格'" statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("demo", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("float", action.dataType) Assert.assertEquals("价格", action.comment) } else { Assert.fail() } } @Test fun changeColumnTest1() { val sql = "ALTER TABLE test_user11_dt ALTER COLUMN ds comment 'ddd'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("test_user11_dt", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("ds", action.columName) Assert.assertNull(action.newColumName) Assert.assertNull(action.dataType) Assert.assertEquals("ddd", action.comment) } else { Assert.fail() } } @Test fun dropColumnTest() { val sql = "ALTER TABLE db.sample DROP COLUMN id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("sample", statement.tableId.tableName) val action = statement.firstAction() as DropColumnAction Assert.assertEquals("id", action.columNames.get(0)) } else { Assert.fail() } } @Test fun setTableLocationTest() { val sql = "alter table demo partition(ds='20180317') set location '/user/hive'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) Assert.assertEquals("demo", statement.tableId.tableName) val action = statement.firstAction() as AlterPropsAction Assert.assertEquals("/user/hive", action.location) } else { Assert.fail() } } @Test fun updateColumnTest() { val sql = "ALTER TABLE sale_detail CHANGE COLUMN old_col_name new_col_name string comment 'sdsd'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals("sale_detail", statement.tableId.tableName) val action = statement.firstAction() as AlterColumnAction Assert.assertEquals("new_col_name", action.newColumName) Assert.assertEquals("sdsd", action.comment) } else { Assert.fail() } val sql1 = "ALTER TABLE test_users_dt CHANGE age2 age3 int" val statement1 = SparkSqlHelper.parseStatement(sql1) if (statement1 is AlterTable) { Assert.assertEquals("test_users_dt", statement1.tableId.tableName) val action = statement1.firstAction() as AlterColumnAction Assert.assertEquals("age3", action.newColumName) } else { Assert.fail() } } @Test fun dropPartitionTest0() { val sql = "ALTER TABLE page_view DROP IF EXISTS PARTITION (dt='2008-08-08', country='us'), PARTITION (dt='2008-08-09', country='us')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as DropPartitionAction Assert.assertTrue(action.ifExists) Assert.assertEquals(AlterActionType.DROP_PARTITION, action.alterType) // Assert.assertEquals(2, action.partitions.size) } else { Assert.fail() } } @Test fun dropPartitionTest1() { val sql = "ALTER TABLE page_view DROP PARTITION (dt='2008-08-08', country='us'), PARTITION (dt='2008-08-09', country='us')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as DropPartitionAction Assert.assertFalse(action.ifExists) Assert.assertEquals(AlterActionType.DROP_PARTITION, action.alterType) // Assert.assertEquals(2, action.partitions.size) } else { Assert.fail() } } @Test fun dropPartitionTest2() { val sql = "ALTER TABLE page_view DROP PARTITION (dt<'2008-08-08')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as DropPartitionAction Assert.assertFalse(action.ifExists) Assert.assertEquals(AlterActionType.DROP_PARTITION, action.alterType) // Assert.assertEquals(2, action.partitions.size) } else { Assert.fail() } } @Test fun addPartitionTest0() { val sql = "ALTER TABLE page_view ADD PARTITION (partCol = 'value1') " val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as AddPartitionAction Assert.assertFalse(action.ifNotExists) Assert.assertEquals(AlterActionType.ADD_PARTITION, action.alterType) Assert.assertEquals(1, action.partitions.size) } else { Assert.fail() } } @Test fun addPartitionTest1() { val sql = "ALTER TABLE page_view add IF NOT EXISTS PARTITION (dt='2008-08-08', country='us')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as AddPartitionAction Assert.assertTrue(action.ifNotExists) Assert.assertEquals(AlterActionType.ADD_PARTITION, action.alterType) Assert.assertEquals(1, action.partitions.size) } else { Assert.fail() } } @Test fun renamePartitionTest() { val sql = "ALTER TABLE page_view PARTITION (dt='2008-08-08') RENAME TO PARTITION (dt='20080808')" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals("page_view", statement.tableId.tableName) val action = statement.firstAction() as RenamePartitionAction Assert.assertEquals(AlterActionType.RENAME_PARTITION, action.alterType) Assert.assertEquals(1, action.fromPartitionVals.size) Assert.assertEquals(1, action.toPartitionVals.size) } else { Assert.fail() } } @Test fun createFuncTest() { val sql = "CREATE FUNCTION test.train_perceptron AS 'hivemall.classifier.PerceptronUDTF' " + "using jar 'hdfs://tdhdfs/user/datacompute/platformtool/resources/132/latest/hivemall-spark.jar'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals("test", statement.functionId.schemaName) Assert.assertEquals("train_perceptron", statement.functionId.functionName) } else { Assert.fail() } } @Test fun createFuncTest1() { val sql = "CREATE TEMPORARY FUNCTION IF NOT EXISTS stream_json_extract_value " + "AS 'com.dataworker.spark.jobserver.driver.udf.GenericUDTFJsonExtractValue'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals("stream_json_extract_value", statement.functionId.functionName) } else { Assert.fail() } } @Test fun dropFuncTest() { val sql = "drop FUNCTION train_perceptron" val statement = SparkSqlHelper.parseStatement(sql) if (statement is DropFunction) { Assert.assertEquals("train_perceptron", statement.functionId.functionName) } else { Assert.fail() } } @Test fun queryTest0() { val sql = """ select * from `demo_rp`.bigdata.users a join address b on a.addr_id=b.id limit 101 OFFSET 10 select * from `demo_rp`.bigdata.users1 a join address1 b on a.addr_id=b.id limit 102 select transform(name,idcard) USING 'python udf-python.py' AS (name,id_card,gre) from db_mxy.person """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(3, statements.size) val query0 = statements.get(0) val query1 = statements.get(1) if (query0 is QueryStmt) { Assert.assertEquals(StatementType.SELECT, query0.statementType) Assert.assertEquals(2, query0.inputTables.size) Assert.assertEquals("users", query0.inputTables.get(0).tableName) Assert.assertEquals("demo_rp.bigdata.users", query0.inputTables.get(0).getFullTableName()) Assert.assertEquals("address", query0.inputTables.get(1).tableName) Assert.assertEquals(101, query0.limit) Assert.assertEquals(10, query0.offset) } if (query1 is QueryStmt) { Assert.assertEquals(StatementType.SELECT, query1.statementType) Assert.assertEquals(2, query1.inputTables.size) Assert.assertEquals("users1", query1.inputTables.get(0).tableName) Assert.assertEquals("demo_rp.bigdata.users1", query1.inputTables.get(0).getFullTableName()) Assert.assertEquals("address1", query1.inputTables.get(1).tableName) Assert.assertEquals(102, query1.limit) Assert.assertNull(query1.offset) } } @Test fun queryTest1() { val sql = "select * from (select * from users where name='melin') a limit 1001" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("users", statement.inputTables.get(0).tableName) Assert.assertEquals(1001, statement.limit) } else { Assert.fail() } } @Test fun queryTest2() { val sql = "select * from users a join (select * from address where type='hangzhou') b on a.addr_id=b.id limit 101" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals("users", statement.inputTables.get(0).tableName) Assert.assertEquals("address", statement.inputTables.get(1).tableName) Assert.assertEquals(101, statement.limit) } else { Assert.fail() } } @Test fun queryTest3() { val sql = """ select bzdys, bzhyyh, bzdy, week, round((bzdy-bzdys)*100/bzdys, 2) from ( select lag(bzdy) over (order by week) bzdys, bzhyyh, bzdy, week from ( select count(distinct partner_code) bzhyyh, count(1) bzdy, week from tdl_dt2x_table ) a ) b limit 111 """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("tdl_dt2x_table", statement.inputTables.get(0).tableName) Assert.assertEquals(111, statement.limit) } else { Assert.fail() } } @Test fun queryTest4() { val sql = "select 2-1" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) } else { Assert.fail() } } @Test fun queryTest5() { val sql = "select \n" + " t.table_name\n" + " ,concat_ws('.',t.database_name,t.table_name) tab_name\n" + " ,t.database_name\n" + " ,t.owner \n" + " ,count(distinct t2.project_code) prj_cnt\n" + " ,count(distinct t1.obj_name) app_user_cnt\n" + " from tidb_datacompute.t_table t \n" + " left join tidb_datacompute.sec_table_privs t1\n" + " on t.table_name = t1.table_name\n" + " and t1.status=1\n" + " and t1.expire_date >= current_date()\n" + " left join tidb_datacompute.dc_project_member t2\n" + " on t1.obj_id = t2.user_id\n" + " where t.`lifecycle` == 1" + " group by t.table_name,t.owner,t.database_name " val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(3, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryTest6() { val sql = "select * from test" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryTest7() { val sql = "select true is false" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) } else { Assert.fail() } } @Test fun queryTest8() { val sql = "select 'test' as name" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) } else { Assert.fail() } } @Test fun insertIntoTest0() { val sql = "insert into TABLE users PARTITION(ds='20170220') values('libinsong', 12, 'test'), ('libinsong', 13, 'test')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals("users", statement.tableId.tableName) Assert.assertEquals(2, statement.rows?.size) } else { Assert.fail() } } @Test fun insertIntoTest1() { val sql = "insert into bigdata.delta_lsw_test values('lsw'),('lsw1')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals("delta_lsw_test", statement.tableId.tableName) Assert.assertEquals(2, statement.rows?.size) } else { Assert.fail() } } @Test fun insertIntoTest2() { val sql = "insert into demo SELECT * FROM hudi_table_changes('db.table', 'latest_state', 'earliest')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals("demo", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.functionNames.size) Assert.assertEquals("hudi_table_changes", statement.queryStmt.functionNames.first().functionName) Assert.assertEquals("TVF", statement.queryStmt.functionNames.first().funcType) Assert.assertEquals(3, statement.queryStmt.functionNames.first().functionArguments.size) } else { Assert.fail() } } @Test fun insertTableCustomColumn() { val sql = "INSERT INTO test_demo_test (name) VALUES('lisi')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals("test_demo_test", statement.tableId?.tableName) } else { Assert.fail() } } @Test fun insertOverwriteTest0() { val sql = "insert OVERWRITE TABLE users PARTITION(ds='20170220', type='login') values('libinsong')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.OVERWRITE, statement.mode) Assert.assertEquals(2, statement.partitionVals?.size) Assert.assertEquals("users", statement.tableId.tableName) } else { Assert.fail() } } @Test fun insertOverwriteTest1() { val sql = "insert OVERWRITE TABLE users PARTITION(ds) values('libinsong', '20170220')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(InsertMode.OVERWRITE, statement.mode) Assert.assertEquals(1, statement.partitionVals?.size) Assert.assertEquals("users", statement.tableId.tableName) } else { Assert.fail() } } @Test fun insertOverwriteQueryTest2() { val sql = "insert /*+ primarys(t1, t2) */ INTO users PARTITION(ds='20170220', type='login') select * from account a join address b on a.addr_id=b.id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("users", statement.tableId.tableName) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals(2, statement.partitionVals?.size) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("account", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) Assert.assertEquals(1, statement.hints?.size) Assert.assertEquals(2, statement.hints?.get("primarys")?.size) } else { Assert.fail() } } @Test fun insertOverwriteQueryTest3() { val sql = "insert INTO users select *, bigdata.Test(id) from account a join address b on a.addr_id=b.id" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("users", statement.tableId?.tableName) Assert.assertEquals(InsertMode.INTO, statement.mode) Assert.assertEquals(0, statement.partitionVals?.size) Assert.assertEquals( statement.queryStmt.getSql(), "select *, bigdata.Test(id) from account a join address b on a.addr_id=b.id" ) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("account", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("address", statement.queryStmt.inputTables.get(1).tableName) Assert.assertEquals(FunctionId("bigdata", "test"), statement.queryStmt.functionNames.first()) } else { Assert.fail() } } @Test fun insertOverwriteQueryTest4() { val sql = "insert OVERWRITE TABLE users PARTITION(ds='20170220') select * from account1 union all " + "select * from account2" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("users", statement.tableId?.tableName) Assert.assertEquals(InsertMode.OVERWRITE, statement.mode) Assert.assertEquals(1, statement.partitionVals?.size) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals("account1", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("account2", statement.queryStmt.inputTables.get(1).tableName) } else { Assert.fail() } } @Test fun mutilInsertTest() { val sql = "FROM default.sample_07\n" + "\n" + "INSERT OVERWRITE TABLE toodey1 SELECT sample_07.code,sample_07.salary\n" + "\n" + "INSERT OVERWRITE TABLE toodey2 SELECT sample_07.code,sample_07.salary WHERE sample_07.salary >= 50000\n" + "\n" + "INSERT OVERWRITE TABLE toodey3 SELECT sample_07.total_emp,sample_07.salary WHERE sample_07.salary <= 50000" val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(3, statement.outputTables.size) Assert.assertEquals("sample_07", statement.queryStmt.inputTables.get(0).tableName) Assert.assertEquals("toodey3", statement.outputTables.get(2).tableName) } else { Assert.fail() } } @Test fun useTest() { val sql = "use bigdata" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.USE, statement.statementType) if (statement is UseDatabase) { Assert.assertEquals("bigdata", statement.databaseName) } else { Assert.fail() } } @Test fun setTest() { val sql = """ set spark.executor.memory = 30g set spark.sql.enabled=true; set spark.sql.test="ddsd"; set spark.sql.test2; reset spark.sql.test; """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(5, statements.size) } @Test fun mergeTest() { val sql = "merge table test OPTIONS (mergefile=2)" SparkSqlHelper.parseStatement(sql) } @Test fun substrFile() { val sql = "SELECT substring('Spark SQL' from 5)" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) } @Test fun druidSql() { val sql = "SELECT * from druid.`select * from test`" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) if (statement is QueryStmt) { Assert.assertEquals("druid", statement.inputTables.get(0).schemaName) } else { Assert.fail() } } @Test fun druidSql1() { val sql = "SELECT * from tdl_xdsd_sd" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.SELECT, statement.statementType) if (statement is QueryStmt) { Assert.assertNull(statement.inputTables.get(0).schemaName) } else { Assert.fail() } } @Test fun deleteTest() { val sql = """ DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo'); """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation'); """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId?.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun updateTest1() { val sql = "update user set name='xxx'" val statement = SparkSqlHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("user", statement.tableId?.tableName) } else { Assert.fail() } } @Test fun deltaMergeTest() { val sql = """ MERGE INTO logs USING updates ON logs.uniqueId = updates.uniqueId WHEN NOT MATCHED THEN INSERT * """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("logs", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest0() { val sql = """ MERGE INTO logs USING updates ON logs.uniqueId = updates.uniqueId AND logs.date > current_date() - INTERVAL 7 DAYS WHEN NOT MATCHED AND updates.date > current_date() - INTERVAL 7 DAYS THEN INSERT * """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("logs", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest1() { val sql = """ MERGE INTO customers USING ( SELECT updates.customerId as mergeKey, updates.* FROM updates UNION ALL SELECT NULL as mergeKey, updates.* FROM updates JOIN customers ON updates.customerid = customers.customerid WHERE customers.current = true AND updates.address <> customers.address ) staged_updates ON customers.customerId = mergeKey WHEN MATCHED AND customers.current = true AND customers.address <> staged_updates.address THEN UPDATE SET current = false, endDate = staged_updates.effectiveDate WHEN NOT MATCHED THEN INSERT(customerid, address, current, effectivedate, enddate) VALUES(staged_updates.customerId, staged_updates.address, true, staged_updates.effectiveDate, null) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("customers", statement.targetTable.tableName) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest2() { val sql = """ MERGE INTO target t USING ( SELECT key, latest.newValue as newValue, latest.deleted as deleted FROM ( SELECT key, max(struct(time, newValue, deleted)) as latest FROM changes GROUP BY key ) ) s ON s.key = t.key WHEN MATCHED AND s.deleted = true THEN DELETE WHEN MATCHED THEN UPDATE SET key = s.key, value = s.newValue WHEN NOT MATCHED AND s.deleted = false THEN INSERT (key, value) VALUES (key, newValue) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("target", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun deltaMergeTest3() { val sql = """ MERGE INTO bigdata.merge_test a1 USING bigdata.merge_test1 a2 ON a1.name = a2.name WHEN MATCHED THEN UPDATE SET a1.age = a2.age """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("merge_test", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun cetSelectTest0() { val sql = """ with q1 as ( select key from q2 where key = '5'), q2 as ( select key from test where key = '5') select * from (select key from q1) a """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals(StatementType.SELECT, statement.statementType) } else { Assert.fail() } } @Test fun cetInsertTest0() { val sql = """ with a as (select * from src where key is not null), b as (select * from src2 where value>0), c as (select * from src3 where value>0), d as (select a.key,b.value from a join b on a.key=b.key), e as (select a.key,c.value from a left outer join c on a.key=c.key and c.key is not null) insert overwrite table srcp partition (p='abc') select * from d union all select * from e """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(3, statement.queryStmt.inputTables.size) Assert.assertEquals(StatementType.INSERT, statement.statementType) } else { Assert.fail() } } @Test fun exportTest0() { val sql = """ with a as (select * from test), druid_result as (select * from a) export table druid_result TO 'druid_result.csv' """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is ExportTable) { Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(StatementType.EXPORT_TABLE, statement.statementType) Assert.assertEquals("druid_result", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createExternalTableTest1() { val sql = """CREATE EXTERNAL TABLE s3Db.test_zc_s3( name String COMMENT 'name', cnt INT COMMENT 'cnt' ) COMMENT '原始数据表' LOCATION 's3a://hive/test/' """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val schemaName = statement.tableId.schemaName Assert.assertEquals(statement.location, "s3a://hive/test/") Assert.assertEquals("s3Db", schemaName) } else { Assert.fail() } } @Test fun createTableTbl() { val sql = """create table bigdata.test_orc9_dt ( name string comment '', name2 String comment '' ) TBLPROPERTIES ('compression'='ZSTD', 'fileFormat'='orc', 'encryption'='0', "orc.encrypt"="hz_admin_key:name2", "orc.mask"='nullify:name') STORED AS orc comment 'orc测试' lifecycle 7 """ val statement = SparkSqlHelper.parseStatement(sql) if (statement is CreateTable) { val prop = statement.properties Assert.assertEquals("ZSTD", prop?.get("compression")) } else { Assert.fail() } } @Test fun countCondTest() { val sql = "select count(type='mac' or null) From test_table where a=2" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals("test_table", statement.inputTables.get(0).tableName) } else { Assert.fail() } } // @Test fun queryLakeTableMetaTest0() { val sql = "select * from dc.user.history limit 101" val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("user", statement.inputTables.get(0).tableName) // Assert.assertEquals("history", statement.inputTables.get(0).metaAction) Assert.assertEquals(101, statement.limit) } else { Assert.fail() } } // @Test fun queryLakeTableMetaTest1() { val sql = """ select h.made_current_at, s.operation, h.snapshot_id, h.is_current_ancestor, s.summary['spark.app.id'] from db.table.history h join db.table.snapshots s on h.snapshot_id = s.snapshot_id order by made_current_at """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) Assert.assertEquals("table", statement.inputTables.get(0).tableName) // Assert.assertEquals("history", statement.inputTables.get(0).metaAction) Assert.assertEquals("table", statement.inputTables.get(1).tableName) // Assert.assertEquals("snapshots", statement.inputTables.get(1).metaAction) } else { Assert.fail() } } @Test fun dtunnelTest0() { val sql = "datatunnel source('sftp') options(host='x.x.x.x') sink('hive') options(table='demo', columns=['id', 'name'])" val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelExpr) { Assert.assertEquals(StatementType.DATATUNNEL, statement.statementType) Assert.assertEquals("sftp", statement.sourceType) Assert.assertEquals("x.x.x.x", statement.sourceOptions.get("host")) Assert.assertEquals("hive", statement.sinkType) Assert.assertEquals("demo", statement.sinkOptions.get("table")) val list = statement.sinkOptions.get("columns") as List Assert.assertEquals(2, list.size) } else { Assert.fail() } } @Test fun dtunnelTest1() { val sql = """ datatunnel source('sftp') options(host='x.x.x.x') transform = "select * from result where type='sql'" sink('hive') options(table='demo', columns=['id', 'name']) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelExpr) { Assert.assertEquals(StatementType.DATATUNNEL, statement.statementType) Assert.assertEquals("sftp", statement.sourceType) Assert.assertEquals("x.x.x.x", statement.sourceOptions.get("host")) Assert.assertEquals("select * from result where type='sql'", statement.transformSql) Assert.assertEquals("hive", statement.sinkType) Assert.assertEquals("demo", statement.sinkOptions.get("table")) val list = statement.sinkOptions.get("columns") as List Assert.assertEquals(2, list.size) } else { Assert.fail() } } @Test fun dtunnelTest2() { val sql = "datatunnel source('sftp') options(host='x.x.x.x') sink('log')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelExpr) { Assert.assertEquals(StatementType.DATATUNNEL, statement.statementType) Assert.assertEquals("sftp", statement.sourceType) Assert.assertEquals("x.x.x.x", statement.sourceOptions.get("host")) Assert.assertEquals("log", statement.sinkType) } else { Assert.fail() } } @Test fun dtunnelTest3() { val sql = """ WITH tmp_demo_test2 AS (SELECT *, test(id) FROM bigdata.test_demo_test2 where name is not null), tmp_demo_test3 AS (select * from tmp_demo_test2) datatunnel SOURCE('hive') OPTIONS( databaseName='bigdata', tableName='tmp_demo_test2', columns=['*']) SINK('log') OPTIONS(numRows = 10) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelExpr) { Assert.assertEquals(StatementType.DATATUNNEL, statement.statementType) Assert.assertEquals("hive", statement.sourceType) Assert.assertEquals("log", statement.sinkType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(1, statement.functionNames.size) } else { Assert.fail() } } @Test fun dtunnelTest4() { val sql = """ DATATUNNEL SOURCE('oracle') OPTIONS( username='flinkuser', password='flinkpw', host='172.18.1.56', port=1521, serviceName='XE', databaseName='FLINKUSER', tableName='ORDERS', columns=[{'name' : "pk", "type" : "id"}, { "name" : "col_ip","type" : "ip" }, { "name" : "col_double","type" : "double" }, { "name" : "col_long","type" : "long" }, { "name" : "col_keyword", "type" : "keyword" }, { "name" : "col_text", "type" : "text", "analyzer" : "ik_max_word"}, { "name" : "col_geo_point", "type" : "geo_point" }, { "name" : "col_date", "type" : "date", "format" : "yyyy-MM-dd HH:mm:ss"}, { "name" : "col_nested1", "type" : "nested" }, { "name" : "col_object1", "type" : "object" }, { "name" : "col_integer_array", "type" : "integer", "array" : TRUE}, { "name" : "col_geo_shape", "type" : "geo_shape", "tree" : "quadtree", "precision" : "10m"} ]) SINK('log') OPTIONS(numRows = 10) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelExpr) { Assert.assertEquals(StatementType.DATATUNNEL, statement.statementType) Assert.assertEquals("oracle", statement.sourceType) Assert.assertEquals("log", statement.sinkType) val list = statement.sourceOptions.get("columns") as List> Assert.assertEquals(12, list.size) } else { Assert.fail() } } @Test fun dtunnelHelpTest() { val sql = "datatunnel help source('sftp')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is DataTunnelHelp) { Assert.assertEquals(StatementType.HELP, statement.statementType) Assert.assertEquals("source", statement.type) Assert.assertEquals("sftp", statement.value) } else { Assert.fail() } } @Test fun callTest0() { val sql = "CALL catalog_name.system.create_savepoint(table => 'test_hudi_table', instant_time => '20220109225319449')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallProcedure) { Assert.assertEquals(StatementType.CALL, statement.statementType) Assert.assertEquals("catalog_name", statement.procedureIds.first().catalogName) Assert.assertEquals("system", statement.procedureIds.first().schemaName) Assert.assertEquals("create_savepoint", statement.procedureIds.first().procedureName) Assert.assertEquals(2, statement.properties.size) } else { Assert.fail() } } @Test fun callTest1() { val sql = "call stats_file_sizes(table => 'test_hudi_demo')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallProcedure) { Assert.assertEquals(StatementType.CALL, statement.statementType) Assert.assertEquals("stats_file_sizes", statement.procedureIds.first().procedureName) Assert.assertEquals(1, statement.properties.size) } else { Assert.fail() } } @Test fun callTest2() { val sql = """ CALL system.remove_orphan_files( table => 'bigdata.ods_iceberg_01', older_than => CURRENT_TIMESTAMP - INTERVAL '5' DAYS, dry_run => true ) """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallProcedure) { Assert.assertEquals(StatementType.CALL, statement.statementType) Assert.assertEquals("remove_orphan_files", statement.procedureIds.first().procedureName) Assert.assertEquals(3, statement.properties.size) } else { Assert.fail() } } @Test fun callHelpTest1() { val sql = "CALL help" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallHelp) { Assert.assertEquals(StatementType.HELP, statement.statementType) } else { Assert.fail() } } @Test fun callHelpTest2() { val sql = "CALL help(cmd => 'show_commits')" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallHelp) { Assert.assertEquals(StatementType.HELP, statement.statementType) Assert.assertEquals("show_commits", statement.procedureName) } else { Assert.fail() } } @Test fun callHelpTest3() { val sql = "CALL help show_commits" val statement = SparkSqlHelper.parseStatement(sql) if (statement is CallHelp) { Assert.assertEquals(StatementType.HELP, statement.statementType) Assert.assertEquals("show_commits", statement.procedureName) } else { Assert.fail() } } @Test fun syncSchemaTest() { val sql = "SYNC Database FROM hive_metastore.my_db SET OWNER wangwu" val statement = SparkSqlHelper.parseStatement(sql) if (statement is SyncDatabaseMetadata) { Assert.assertEquals(StatementType.SYNC_META, statement.statementType) Assert.assertEquals("hive_metastore", statement.catalogName) Assert.assertEquals("my_db", statement.databaseName) Assert.assertEquals("wangwu", statement.owner) } else { Assert.fail() } } @Test fun syncTableMetaTest() { val sql = "SYNC TABLE FROM hive_metastore.default.my_tbl" val statement = SparkSqlHelper.parseStatement(sql) if (statement is SyncTableMetadata) { Assert.assertEquals(StatementType.SYNC_META, statement.statementType) Assert.assertEquals("hive_metastore", statement.tableId.catalogName) Assert.assertEquals("default", statement.tableId.schemaName) Assert.assertEquals("my_tbl", statement.tableId.tableName) } else { Assert.fail() } } @Test fun typeConstructor() { var sql = "select date '20220-02-13' as demo" SparkSqlHelper.parseStatement(sql) sql = "select timestamp '20220-02-13' as demo" SparkSqlHelper.parseStatement(sql) sql = "select time '20220-02-13' as demo" SparkSqlHelper.parseStatement(sql) } @Test fun createIndexTest() { val sql = "CREATE INDEX test_index ON demo.orders (column_name)" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("demo", "orders"), statement.tableId) val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals("test_index", createIndex.indexName) } } @Test fun dropIndexTest() { val sql = "DROP INDEX test_index ON demo.orders" val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.ALTER_TABLE, statement.statementType) if (statement is AlterTable) { Assert.assertEquals(TableId("demo", "orders"), statement.tableId) val dropIndex = statement.firstAction() as DropIndex Assert.assertEquals("test_index", dropIndex.indexName) } } @Test fun createFileViewTest() { val sql = """ create view tdl_spark_test using csv File '/user/dataworks/users/qianxiao/demo.csv' Options( delimiter=',',header='true') COMPRESSION gz; """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) Assert.assertEquals(StatementType.CREATE_FILE_VIEW, statement.statementType) if (statement is CreateFileView) { Assert.assertEquals("tdl_spark_test", statement.tableId.tableName) Assert.assertEquals("/user/dataworks/users/qianxiao/demo.csv", statement.path) Assert.assertEquals("csv", statement.fileFormat) Assert.assertEquals("gz", statement.compression) } } @Test fun tvfTest() { val sql = """ SELECT * FROM range(6 + cos(3)); """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(0, statement.inputTables.size) } } @Test fun cacheTest() { val sql = """ cache lazy table fire_service_calls_tbl_cache OPTIONS ('storageLevel' 'DISK_ONLY') as select * from (select * from demo.db.fire_service_calls_tbl) a """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is CacheTable) { Assert.assertEquals("fire_service_calls_tbl_cache", statement.tableId.tableName) Assert.assertEquals(1, statement.options.size) Assert.assertEquals(1, statement.queryStmt?.inputTables?.size) } else { Assert.fail() } } @Test fun uncacheTest() { val sql = """ uncache table fire_service_calls_tbl_cache; """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is UnCacheTable) { Assert.assertEquals("fire_service_calls_tbl_cache", statement.tableId.tableName) } else { Assert.fail() } } @Test fun resourceManagerTest() { val sql = """ ADD ARCHIVE /tmp/test.tar.gz; ADD ARCHIVE "/path/to/some.zip"; ADD ARCHIVE '/some/other.tgz'; ADD ARCHIVE "/path with space/abc.tar"; ADD ARCHIVES "/path with space/def.tgz" '/path with space/ghi.zip'; LIST JAR; LIST JAR /tmp/test.jar /some/random.jar /another/random.jar; """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(7, statements.size) val addResource = statements.get(4) as AddResourceStatement Assert.assertEquals(2, addResource.fileNames.size) val listResource = statements.get(6) as ListResourceStatement Assert.assertEquals(3, listResource.fileNames.size) } @Test fun insertOverwriteDirTest() { val sql = """ with test as ( select a, b from aaa ) insert overwrite directory 'hdfs://xxx' row format delimited fields terminated by '\t' select a, b from test """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals("hdfs://xxx", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun loadDataTest() { val sql = """ load data inpath 'hdfs:///user/xxx.txt' into table aaa.bbb partition(ds='2024-02-27'); """ .trimIndent() val statement = SparkSqlHelper.parseStatement(sql) if (statement is LoadData) { Assert.assertEquals("hdfs:///user/xxx.txt", statement.inPath) Assert.assertEquals("aaa.bbb", statement.tableId.getFullTableName()) } else { Assert.fail() } } @Test fun distCpTest() { val sql = """ SET SPARK.HADOOP.FS.OSS.ENDPOINT = OSS-CN-HANGZHOU.ALIYUNCS.COM; set spark.hadoop.fs.oss.accessKeyId = xxx; set spark.hadoop.fs.oss.accessKeySecret = xxxx; set spark.hadoop.fs.oss.attempts.maximum = 3; set spark.hadoop.fs.oss.connection.timeout = 10000; set spark.hadoop.fs.oss.connection.establish.timeout = 10000; set spark.hadoop.fs.oss.impl = org.apache.hadoop.fs.aliyun.oss.AliyunOSSFileSystem; set spark.hadoop.fs.sftp.host = "172.24.5.213" set spark.hadoop.fs.sftp.host.port = 22 set spark.hadoop.fs.sftp.user.172.24.5.213 = root set "spark.hadoop.fs.sftp.password.172.24.5.213.root" = 123caoqwe DISTCP OPTIONS ( srcPaths = ['oss://melin1204/users'], destPath = "hdfs://cdh1:8020/temp", overwrite = true ) """ .trimIndent() val statements = SparkSqlHelper.parseMultiStatement(sql) Assert.assertEquals(12, statements.size) } @Test fun querySqlTest0() { val sql1 = FileUtils.readFileToString(File("./src/test/resources/demo.sql"), "UTF-8") val statement = SparkSqlHelper.parseStatement(sql1) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(10, statement.queryStmt.inputTables.size) Assert.assertEquals(TableId("DWB", "DWB_FOREX_TRADE_A_D"), statement.outputTables.get(0)) } else { Assert.fail() } } } ================================================ FILE: superior-spark-parser/src/test/kotlin/io/github/melin/superior/parser/spark/SparkStreamSqlParserTest.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.common.SetStatement import io.github.melin.superior.common.relational.create.CreateTable import io.github.melin.superior.common.relational.dml.InsertTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/3/15. */ class SparkStreamSqlParserTest { @Test fun createTableTest() { val sql = "CREATE Stream TABLE student_scores (\n" + " student_number string comment '学号', \n" + " student_name string comment '姓名', \n" + " subject string comment '学科',\n" + " score '/data/score' INT comment '成绩' \n" + ")\n" + "WITH (\n" + " type = \"dis\",\n" + " format = \"json\",\n" + " kafka.group.id = \"cn-north-1\"\n" + ")" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("student_scores", statement.tableId.tableName) Assert.assertEquals("cn-north-1", statement.properties?.get("kafka.group.id")) } else { Assert.fail() } } @Test fun createTableTest4() { val sql = """ CREATE Stream TABLE orders ( userid string, money bigint ) WITH ( type = 'kafka', topic = 'flink-topic-input', encode = 'json', kafka.bootstrap.servers = 'localhost:9092', kafka.group.id = 'flink-group' ); insert into stat_orders SELECT userid, SUM(money) as total_money FROM orders GROUP BY TUMBLE(proctime, INTERVAL '10' SECOND), userid; set spark.test = 'hello world'; set spark.test = setsd,sd,resr; set spark.test = hello world; set spark.test = hello-world; set spark.test = hello $\{usename} test; #set spark.test = hello comment; set spark.test = hello 'test' world; set spark.test = hello "test" world; set spark.test = hdfs://user/hive; set spark.test = 12,12; set spark.test = 3.45; set spark.test = ibdex.json; set spark.test = dw.eset_sdfe_sd; set spark.test = demo.test; set spark.test = dsd(id)%=2; """ val statementDatas = SparkStreamSqlHelper.parseStatement(sql) Assert.assertEquals(16, statementDatas.size) val statement = statementDatas.get(0) if (statement is CreateTable) { Assert.assertEquals("orders", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createTableTest5() { val sql = "CREATE Stream TABLE tdl_hudi_stream_json_dt\n" + " WITH (\n" + " type = 'hudi',\n" + " databaseName = \"bigdata\",\n" + " tableName = \"hudi_stream_json_dt\"" + " )" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is CreateTable) { Assert.assertEquals(StatementType.CREATE_TABLE, statement.statementType) Assert.assertEquals("tdl_hudi_stream_json_dt", statement.tableId.tableName) Assert.assertEquals("hudi", statement.properties?.get("type")) } else { Assert.fail() } } @Test fun setConfigTest() { val sql = "set spark.test = false" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is SetStatement) { Assert.assertEquals(StatementType.SET, statement.statementType) Assert.assertEquals("spark.test", statement.key) Assert.assertEquals("false", statement.value) } else { Assert.fail() } } @Test fun setConfigTest1() { val sql = "set spark.test = 'hello world'" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is SetStatement) { Assert.assertEquals(StatementType.SET, statement.statementType) Assert.assertEquals("spark.test", statement.key) Assert.assertEquals("hello world", statement.value) } else { Assert.fail() } } @Test fun setConfigTest2() { val sql = "set spark.test = 12 " val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is SetStatement) { Assert.assertEquals(StatementType.SET, statement.statementType) Assert.assertEquals("spark.test", statement.key) Assert.assertEquals("12", statement.value) } else { Assert.fail() } } @Test fun setConfigTest3() { val sql = "set spark.test = 'demo' " val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is SetStatement) { Assert.assertEquals(StatementType.SET, statement.statementType) Assert.assertEquals("spark.test", statement.key) Assert.assertEquals("demo", statement.value) } else { Assert.fail() } } @Test fun insertSqlTest() { val sql = "insert into bigdata.test_result1 select * from users" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("test_result1", statement.tableId?.tableName) Assert.assertEquals("select * from users", statement.queryStmt.getSql()) } else { Assert.fail() } } @Test fun insertUDTFSqlTest() { val sql = "insert into stat_orders_kafka\n" + "SELECT \n" + " TUMBLE_START(proctime, INTERVAL '10' SECOND),\n" + " TUMBLE_END(proctime, INTERVAL '10' SECOND),\n" + " userid, \n" + " SUM(money) as total_money \n" + "FROM (select userid, money, proctime from orders LEFT JOIN LATERAL TABLE(demoFunc(a)) as T(newuserid) ON TRUE) a\n" + "GROUP BY TUMBLE(proctime, INTERVAL '10' SECOND), userid;" val statement = SparkStreamSqlHelper.parseStatement(sql).get(0) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("stat_orders_kafka", statement.tableId?.tableName) } else { Assert.fail() } } } ================================================ FILE: superior-spark-parser/src/test/resources/demo.sql ================================================ WITH TMP_BS_FOREX_ORDER AS ( SELECT ORDER_ID, ATTR, SOURCE, DATA_FLAG FROM ( SELECT ID AS ORDER_ID, ATTR, SOURCE, 'TBNZ' AS DATA_FLAG FROM ODS.ALPHA_ONLINE_ORDERS A WHERE SEC_TYPE = 'FOREX' UNION ALL SELECT ID AS ORDER_ID, ATTR, SOURCE, 'TBSG' AS DATA_FLAG FROM ODS.SG_ALPHA_ONLINE_ORDERS A WHERE SEC_TYPE = 'FOREX' UNION ALL SELECT ID AS ORDER_ID, ATTR, SOURCE, 'TBAU' AS DATA_FLAG FROM ODS.AU_ALPHA_ONLINE_ORDERS A WHERE SEC_TYPE = 'FOREX' UNION ALL SELECT ID AS ORDER_ID, ATTR, SOURCE, 'TFNZ' AS DATA_FLAG FROM ODS.TFNZ_ALPHA_ONLINE_ORDERS A WHERE SEC_TYPE = 'FOREX' ) A GROUP BY ORDER_ID, ATTR, SOURCE, DATA_FLAG ) , TMP_BS_FOREX_COUPON_ORDER AS ( SELECT ORDER_ID, DATA_FLAG FROM ( SELECT ORDER_ID, 'TBNZ' AS DATA_FLAG FROM ODS.ALPHA_ONLINE_COUPON_ORDERS A INNER JOIN ODS.ALPHA_ONLINE_ORDERS B ON A.ORDER_ID = B.ID WHERE B.SEC_TYPE = 'FOREX' UNION ALL SELECT ORDER_ID, 'TBSG' AS DATA_FLAG FROM ODS.SG_ALPHA_ONLINE_COUPON_ORDERS A INNER JOIN ODS.SG_ALPHA_ONLINE_ORDERS B ON A.ORDER_ID = B.ID WHERE B.SEC_TYPE = 'FOREX' UNION ALL SELECT ORDER_ID, 'TBAU' AS DATA_FLAG FROM ODS.AU_ALPHA_ONLINE_COUPON_ORDERS A INNER JOIN ODS.AU_ALPHA_ONLINE_ORDERS B ON A.ORDER_ID = B.ID WHERE B.SEC_TYPE = 'FOREX' UNION ALL SELECT ORDER_ID, 'TFNZ' AS DATA_FLAG FROM ODS.TFNZ_ALPHA_ONLINE_COUPON_ORDERS A INNER JOIN ODS.TFNZ_ALPHA_ONLINE_ORDERS B ON A.ORDER_ID = B.ID WHERE B.SEC_TYPE = 'FOREX' ) A GROUP BY ORDER_ID, DATA_FLAG ) , RESULT AS ( SELECT A.PID , A.EXECUTING_BROKER , A.CLEARING_BROKER , A.REF_TYPE AS BEHAVIOR_TYPE , A.TRADE_DATE AS BEHAVIOR_DATE -- 当地时间 , A.TRANSACT_TIME AS BEHAVIOR_TIME -- 北京时间 , A.TRADE_ID , CAST (A.ORDER_ID AS STRING) AS ORDER_ID , B.SOURCE AS TRADE_ORDER_SOURCE , A.IS_AUTO_EXCHANGE , CASE WHEN CAST (B.ATTR AS BIGINT) & CAST (POW(2, 18) AS BIGINT)= CAST (POW(2, 18) AS BIGINT) THEN 1 ELSE 0 END AS IS_TRADE_GREY_MARKET , CASE WHEN C.ORDER_ID IS NOT NULL THEN 1 ELSE 0 END AS IS_COUPON_USED , CAST (A.ACCOUNT_ID AS STRING) AS ACCOUNT_ID , CAST (A.STOCK_ID AS STRING) AS STOCK_ID , A.`SYMBOL` , A.SEC_TYPE , A.MARKET , A.`EXCHANGE` , A.SIDE AS ACTION , A.CURRENCY , A.AVG_COST AS AVG_PRICE , A.DECIMAL_QTY AS QTY , A.MULTIPLIER , A.AMOUNT , A.FOREX_INCOME AS COMMISSION , A.FOREX_COST AS EXPENSE , A.FOREX_INCOME-NVL(A.FOREX_COST, 0) AS NET , A.CURRENCY AS COMMISSION_CURRENCY , A.DATA_FLAG , A.CREATED_AT , A.UPDATED_AT FROM DWD.DWD_BS_FOREX_TRADE_DETAIL_A_D A LEFT JOIN TMP_BS_FOREX_ORDER B ON A.ORDER_ID=B.ORDER_ID AND A.DATA_FLAG=B.DATA_FLAG LEFT JOIN TMP_BS_FOREX_COUPON_ORDER C ON A.ORDER_ID= C.ORDER_ID AND A.DATA_FLAG= C.DATA_FLAG UNION ALL SELECT PID , 'IB' AS EXECUTING_BROKER , 'IB' AS CLEARING_BROKER , A.BEHAVIOR_TYPE , A.BEHAVIOR_DATE -- 当地日期 , CAST (FROM_UTC_TIMESTAMP(TO_UTC_TIMESTAMP(A.TRADE_TIME, 'AMERICA/NEW_YORK'), 'ASIA/SHANGHAI') AS STRING) AS BEHAVIOR_TIME -- 美东转北京地时间 , A.TRADE_ID , A.ORDER_ID , A.TRADE_ORDER_SOURCE , 0 AS IS_AUTO_EXCHANGE , NULL AS IS_TRADE_GREY_MARKET , NULL AS IS_COUPON_USED , A.ACCOUNT AS ACCOUNT_ID , NULL AS STOCK_ID , A.`SYMBOL` , A.SEC_TYPE , A.MARKET , A.`EXCHANGE` , A.ACTION , A.CURRENCY , A.AVG_PRICE , A.QTY , A.MULTIPLIER , A.AMOUNT , A.COMMISSION , A.EXPENSE , A.NET , A.COMMISSION_CURRENCY , CASE WHEN LICENSE='TBNZ' THEN 'IB' WHEN LICENSE='US_IB' THEN 'US_IB' END AS DATA_FLAG , CAST (FROM_UTC_TIMESTAMP(TO_UTC_TIMESTAMP(A.TRADE_TIME, 'AMERICA/NEW_YORK'), 'ASIA/SHANGHAI') AS STRING) AS CREATED_AT , CAST (FROM_UTC_TIMESTAMP(TO_UTC_TIMESTAMP(A.TRADE_TIME, 'AMERICA/NEW_YORK'), 'ASIA/SHANGHAI') AS STRING) AS UPDATED_AT FROM DWD.DWD_IB_TRADE_DETAIL_A_D A WHERE A.SEC_TYPE='CASH' ) INSERT OVERWRITE TABLE DWB.DWB_FOREX_TRADE_A_D SELECT * FROM RESULT ================================================ FILE: superior-spark-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-sqlserver-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-sqlserver-parser superior-sqlserver-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-sqlserver-parser/src/main/antlr4/io/github/melin/superior/parser/sqlserver/antlr4/SqlServerLexer.g4 ================================================ /* T-SQL (Transact-SQL, MSSQL) grammar. The MIT License (MIT). Copyright (c) 2017, Mark Adams (madams51703@gmail.com) Copyright (c) 2015-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. Copyright (c) 2016, Scott Ure (scott@redstormsoftware.com). Copyright (c) 2016, Rui Zhang (ruizhang.ccs@gmail.com). Copyright (c) 2016, Marcus Henriksson (kuseman80@gmail.com). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ lexer grammar SqlServerLexer; // Basic keywords (from https://msdn.microsoft.com/en-us/library/ms189822.aspx) //Keywords that can exist in ID etc //More keywords that can also be used as IDs ABORT: 'ABORT'; ABORT_AFTER_WAIT: 'ABORT_AFTER_WAIT'; ABSENT: 'ABSENT'; ABSOLUTE: 'ABSOLUTE'; ACCELERATED_DATABASE_RECOVERY: 'ACCELERATED_DATABASE_RECOVERY'; ACCENT_SENSITIVITY: 'ACCENT_SENSITIVITY'; ACCESS: 'ACCESS'; ACTION: 'ACTION'; ACTIVATION: 'ACTIVATION'; ACTIVE: 'ACTIVE'; ADD: 'ADD'; ADDRESS: 'ADDRESS'; ADMINISTER: 'ADMINISTER'; AES: 'AES'; AES_128: 'AES_128'; AES_192: 'AES_192'; AES_256: 'AES_256'; AFFINITY: 'AFFINITY'; AFTER: 'AFTER'; AGGREGATE: 'AGGREGATE'; ALGORITHM: 'ALGORITHM'; ALL: 'ALL'; ALLOWED: 'ALLOWED'; ALLOW_CONNECTIONS: 'ALLOW_CONNECTIONS'; ALLOW_ENCRYPTED_VALUE_MODIFICATIONS: 'ALLOW_ENCRYPTED_VALUE_MODIFICATIONS'; ALLOW_MULTIPLE_EVENT_LOSS: 'ALLOW_MULTIPLE_EVENT_LOSS'; ALLOW_PAGE_LOCKS: 'ALLOW_PAGE_LOCKS'; ALLOW_ROW_LOCKS: 'ALLOW_ROW_LOCKS'; ALLOW_SINGLE_EVENT_LOSS: 'ALLOW_SINGLE_EVENT_LOSS'; ALLOW_SNAPSHOT_ISOLATION: 'ALLOW_SNAPSHOT_ISOLATION'; ALL_CONSTRAINTS: 'ALL_CONSTRAINTS'; ALL_ERRORMSGS: 'ALL_ERRORMSGS'; ALL_INDEXES: 'ALL_INDEXES'; ALL_LEVELS: 'ALL_LEVELS'; ALTER: 'ALTER'; ALWAYS: 'ALWAYS'; AND: 'AND'; ANONYMOUS: 'ANONYMOUS'; ANSI_DEFAULTS: 'ANSI_DEFAULTS'; ANSI_NULLS: 'ANSI_NULLS'; ANSI_NULL_DEFAULT: 'ANSI_NULL_DEFAULT'; ANSI_NULL_DFLT_OFF: 'ANSI_NULL_DFLT_OFF'; ANSI_NULL_DFLT_ON: 'ANSI_NULL_DFLT_ON'; ANSI_PADDING: 'ANSI_PADDING'; ANSI_WARNINGS: 'ANSI_WARNINGS'; ANY: 'ANY'; APPEND: 'APPEND'; APPLICATION: 'APPLICATION'; APPLICATION_LOG: 'APPLICATION_LOG'; APPLOCK_MODE: 'APPLOCK_MODE'; APPLOCK_TEST: 'APPLOCK_TEST'; APPLY: 'APPLY'; APP_NAME: 'APP_NAME'; ARITHABORT: 'ARITHABORT'; ARITHIGNORE: 'ARITHIGNORE'; AS: 'AS'; ASC: 'ASC'; ASCII: 'ASCII'; ASSEMBLY: 'ASSEMBLY'; ASSEMBLYPROPERTY: 'ASSEMBLYPROPERTY'; ASYMMETRIC: 'ASYMMETRIC'; ASYNCHRONOUS_COMMIT: 'ASYNCHRONOUS_COMMIT'; AT_KEYWORD: 'AT'; AUDIT: 'AUDIT'; AUDIT_GUID: 'AUDIT_GUID'; AUTHENTICATE: 'AUTHENTICATE'; AUTHENTICATION: 'AUTHENTICATION'; AUTHORIZATION: 'AUTHORIZATION'; AUTO: 'AUTO'; AUTOGROW_ALL_FILES: 'AUTOGROW_ALL_FILES'; AUTOGROW_SINGLE_FILE: 'AUTOGROW_SINGLE_FILE'; AUTOMATED_BACKUP_PREFERENCE: 'AUTOMATED_BACKUP_PREFERENCE'; AUTOMATIC: 'AUTOMATIC'; AUTO_CLEANUP: 'AUTO_CLEANUP'; AUTO_CLOSE: 'AUTO_CLOSE'; AUTO_CREATE_STATISTICS: 'AUTO_CREATE_STATISTICS'; AUTO_DROP: 'AUTO_DROP'; AUTO_SHRINK: 'AUTO_SHRINK'; AUTO_UPDATE_STATISTICS: 'AUTO_UPDATE_STATISTICS'; AUTO_UPDATE_STATISTICS_ASYNC: 'AUTO_UPDATE_STATISTICS_ASYNC'; AVAILABILITY: 'AVAILABILITY'; AVAILABILITY_MODE: 'AVAILABILITY_MODE'; AVG: 'AVG'; BACKSLASH: '\\'; BACKUP: 'BACKUP'; BACKUP_CLONEDB: 'BACKUP_CLONEDB'; BACKUP_PRIORITY: 'BACKUP_PRIORITY'; BASE64: 'BASE64'; BEFORE: 'BEFORE'; BEGIN: 'BEGIN'; BEGIN_DIALOG: 'BEGIN_DIALOG'; BETWEEN: 'BETWEEN'; BIGINT: 'BIGINT'; BINARY_CHECKSUM: 'BINARY_CHECKSUM'; BINARY_KEYWORD: 'BINARY'; BINDING: 'BINDING'; BLOB_STORAGE: 'BLOB_STORAGE'; BLOCK: 'BLOCK'; BLOCKERS: 'BLOCKERS'; BLOCKING_HIERARCHY: 'BLOCKING_HIERARCHY'; BLOCKSIZE: 'BLOCKSIZE'; BREAK: 'BREAK'; BROKER: 'BROKER'; BROKER_INSTANCE: 'BROKER_INSTANCE'; BROWSE: 'BROWSE'; BUFFER: 'BUFFER'; BUFFERCOUNT: 'BUFFERCOUNT'; BULK: 'BULK'; BULK_LOGGED: 'BULK_LOGGED'; BY: 'BY'; CACHE: 'CACHE'; CALLED: 'CALLED'; CALLER: 'CALLER'; CAP_CPU_PERCENT: 'CAP_CPU_PERCENT'; CASCADE: 'CASCADE'; CASE: 'CASE'; CAST: 'CAST'; CATALOG: 'CATALOG'; CATCH: 'CATCH'; CERTENCODED: 'CERTENCODED'; CERTIFICATE: 'CERTIFICATE'; CERTPRIVATEKEY: 'CERTPRIVATEKEY'; CERT_ID: 'CERT_ID'; CHANGE: 'CHANGE'; CHANGES: 'CHANGES'; CHANGETABLE: 'CHANGETABLE'; CHANGE_RETENTION: 'CHANGE_RETENTION'; CHANGE_TRACKING: 'CHANGE_TRACKING'; CHAR: 'CHAR'; CHARINDEX: 'CHARINDEX'; CHECK: 'CHECK'; CHECKALLOC: 'CHECKALLOC'; CHECKCATALOG: 'CHECKCATALOG'; CHECKCONSTRAINTS: 'CHECKCONSTRAINTS'; CHECKDB: 'CHECKDB'; CHECKFILEGROUP: 'CHECKFILEGROUP'; CHECKPOINT: 'CHECKPOINT'; CHECKSUM: 'CHECKSUM'; CHECKSUM_AGG: 'CHECKSUM_AGG'; CHECKTABLE: 'CHECKTABLE'; CHECK_EXPIRATION: 'CHECK_EXPIRATION'; CHECK_POLICY: 'CHECK_POLICY'; CLASSIFIER_FUNCTION: 'CLASSIFIER_FUNCTION'; CLEANTABLE: 'CLEANTABLE'; CLEANUP: 'CLEANUP'; CLONEDATABASE: 'CLONEDATABASE'; CLOSE: 'CLOSE'; CLUSTER: 'CLUSTER'; CLUSTERED: 'CLUSTERED'; COALESCE: 'COALESCE'; COLLATE: 'COLLATE'; COLLECTION: 'COLLECTION'; COLUMN: 'COLUMN'; COLUMNPROPERTY: 'COLUMNPROPERTY'; COLUMNS: 'COLUMNS'; COLUMNSTORE: 'COLUMNSTORE'; COLUMNSTORE_ARCHIVE: 'COLUMNSTORE_ARCHIVE'; COLUMN_ENCRYPTION_KEY: 'COLUMN_ENCRYPTION_KEY'; COLUMN_MASTER_KEY: 'COLUMN_MASTER_KEY'; COL_LENGTH: 'COL_LENGTH'; COL_NAME: 'COL_NAME'; COMMIT: 'COMMIT'; COMMITTED: 'COMMITTED'; COMPATIBILITY_LEVEL: 'COMPATIBILITY_LEVEL'; COMPRESS: 'COMPRESS'; COMPRESSION: 'COMPRESSION'; COMPRESSION_DELAY: 'COMPRESSION_DELAY'; COMPRESS_ALL_ROW_GROUPS: 'COMPRESS_ALL_ROW_GROUPS'; COMPUTE: 'COMPUTE'; CONCAT: 'CONCAT'; CONCAT_NULL_YIELDS_NULL: 'CONCAT_NULL_YIELDS_NULL'; CONCAT_WS: 'CONCAT_WS'; CONFIGURATION: 'CONFIGURATION'; CONNECT: 'CONNECT'; CONNECTION: 'CONNECTION'; CONNECTIONPROPERTY: 'CONNECTIONPROPERTY'; CONSTRAINT: 'CONSTRAINT'; CONTAINMENT: 'CONTAINMENT'; CONTAINS: 'CONTAINS'; CONTAINSTABLE: 'CONTAINSTABLE'; CONTENT: 'CONTENT'; CONTEXT: 'CONTEXT'; CONTEXT_INFO: 'CONTEXT_INFO'; CONTINUE: 'CONTINUE'; CONTINUE_AFTER_ERROR: 'CONTINUE_AFTER_ERROR'; CONTRACT: 'CONTRACT'; CONTRACT_NAME: 'CONTRACT_NAME'; CONTROL: 'CONTROL'; CONVERSATION: 'CONVERSATION'; CONVERT: 'TRY_'? 'CONVERT'; COOKIE: 'COOKIE'; COPY_ONLY: 'COPY_ONLY'; COUNT: 'COUNT'; COUNTER: 'COUNTER'; COUNT_BIG: 'COUNT_BIG'; CPU: 'CPU'; CREATE: 'CREATE'; CREATE_NEW: 'CREATE_NEW'; CREATION_DISPOSITION: 'CREATION_DISPOSITION'; CREDENTIAL: 'CREDENTIAL'; CROSS: 'CROSS'; CRYPTOGRAPHIC: 'CRYPTOGRAPHIC'; CUME_DIST: 'CUME_DIST'; CURRENT: 'CURRENT'; CURRENT_DATE: 'CURRENT_DATE'; CURRENT_REQUEST_ID: 'CURRENT_REQUEST_ID'; CURRENT_TIME: 'CURRENT_TIME'; CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'; CURRENT_TRANSACTION_ID: 'CURRENT_TRANSACTION_ID'; CURRENT_USER: 'CURRENT_USER'; CURSOR: 'CURSOR'; CURSOR_CLOSE_ON_COMMIT: 'CURSOR_CLOSE_ON_COMMIT'; CURSOR_DEFAULT: 'CURSOR_DEFAULT'; CURSOR_STATUS: 'CURSOR_STATUS'; CYCLE: 'CYCLE'; DATA: 'DATA'; DATABASE: 'DATABASE'; DATABASEPROPERTYEX: 'DATABASEPROPERTYEX'; DATABASE_MIRRORING: 'DATABASE_MIRRORING'; DATABASE_PRINCIPAL_ID: 'DATABASE_PRINCIPAL_ID'; DATALENGTH: 'DATALENGTH'; DATASPACE: 'DATASPACE'; DATA_COMPRESSION: 'DATA_COMPRESSION'; DATA_PURITY: 'DATA_PURITY'; DATA_SOURCE: 'DATA_SOURCE'; DATEADD: 'DATEADD'; DATEDIFF: 'DATEDIFF'; DATENAME: 'DATENAME'; DATEPART: 'DATEPART'; DATE_CORRELATION_OPTIMIZATION: 'DATE_CORRELATION_OPTIMIZATION'; DAYS: 'DAYS'; DBCC: 'DBCC'; DBREINDEX: 'DBREINDEX'; DB_CHAINING: 'DB_CHAINING'; DB_FAILOVER: 'DB_FAILOVER'; DB_ID: 'DB_ID'; DB_NAME: 'DB_NAME'; DDL: 'DDL'; DEALLOCATE: 'DEALLOCATE'; DECLARE: 'DECLARE'; DECOMPRESS: 'DECOMPRESS'; DECRYPTION: 'DECRYPTION'; DEFAULT: 'DEFAULT'; DEFAULT_DATABASE: 'DEFAULT_DATABASE'; DEFAULT_DOUBLE_QUOTE: ["]'DEFAULT'["]; DEFAULT_FULLTEXT_LANGUAGE: 'DEFAULT_FULLTEXT_LANGUAGE'; DEFAULT_LANGUAGE: 'DEFAULT_LANGUAGE'; DEFAULT_SCHEMA: 'DEFAULT_SCHEMA'; DEFINITION: 'DEFINITION'; DELAY: 'DELAY'; DELAYED_DURABILITY: 'DELAYED_DURABILITY'; DELETE: 'DELETE'; DELETED: 'DELETED'; DENSE_RANK: 'DENSE_RANK'; DENY: 'DENY'; DEPENDENTS: 'DEPENDENTS'; DES: 'DES'; DESC: 'DESC'; DESCRIPTION: 'DESCRIPTION'; DESX: 'DESX'; DETERMINISTIC: 'DETERMINISTIC'; DHCP: 'DHCP'; DIAGNOSTICS: 'DIAGNOSTICS'; DIALOG: 'DIALOG'; DIFFERENCE: 'DIFFERENCE'; DIFFERENTIAL: 'DIFFERENTIAL'; DIRECTORY_NAME: 'DIRECTORY_NAME'; DISABLE: 'DISABLE'; DISABLED: 'DISABLED'; DISABLE_BROKER: 'DISABLE_BROKER'; DISK: 'DISK'; DISTINCT: 'DISTINCT'; DISTRIBUTED: 'DISTRIBUTED'; DISTRIBUTION: 'DISTRIBUTION'; DOCUMENT: 'DOCUMENT'; DOLLAR_PARTITION: '$PARTITION'; DOUBLE: 'DOUBLE'; DOUBLE_BACK_SLASH: '\\\\'; DOUBLE_FORWARD_SLASH: '//'; DROP: 'DROP'; DROPCLEANBUFFERS: 'DROPCLEANBUFFERS'; DROP_EXISTING: 'DROP_EXISTING'; DTC_SUPPORT: 'DTC_SUPPORT'; DUMP: 'DUMP'; DYNAMIC: 'DYNAMIC'; ELEMENTS: 'ELEMENTS'; ELSE: 'ELSE'; EMERGENCY: 'EMERGENCY'; EMPTY: 'EMPTY'; ENABLE: 'ENABLE'; ENABLED: 'ENABLED'; ENABLE_BROKER: 'ENABLE_BROKER'; ENCRYPTED: 'ENCRYPTED'; ENCRYPTED_VALUE: 'ENCRYPTED_VALUE'; ENCRYPTION: 'ENCRYPTION'; ENCRYPTION_TYPE: 'ENCRYPTION_TYPE'; END: 'END'; ENDPOINT: 'ENDPOINT'; ENDPOINT_URL: 'ENDPOINT_URL'; ERRLVL: 'ERRLVL'; ERROR: 'ERROR'; ERROR_BROKER_CONVERSATIONS: 'ERROR_BROKER_CONVERSATIONS'; ERROR_LINE: 'ERROR_LINE'; ERROR_MESSAGE: 'ERROR_MESSAGE'; ERROR_NUMBER: 'ERROR_NUMBER'; ERROR_PROCEDURE: 'ERROR_PROCEDURE'; ERROR_SEVERITY: 'ERROR_SEVERITY'; ERROR_STATE: 'ERROR_STATE'; ESCAPE: 'ESCAPE'; ESTIMATEONLY: 'ESTIMATEONLY'; EVENT: 'EVENT'; EVENTDATA: 'EVENTDATA'; EVENT_RETENTION_MODE: 'EVENT_RETENTION_MODE'; EXCEPT: 'EXCEPT'; EXCLUSIVE: 'EXCLUSIVE'; EXECUTABLE: 'EXECUTABLE'; EXECUTABLE_FILE: 'EXECUTABLE_FILE'; EXECUTE: 'EXEC' 'UTE'?; EXIST: 'EXIST'; EXISTS: 'EXISTS'; EXIST_SQUARE_BRACKET: '[EXIST]'; EXIT: 'EXIT'; EXPAND: 'EXPAND'; EXPIREDATE: 'EXPIREDATE'; EXPIRY_DATE: 'EXPIRY_DATE'; EXPLICIT: 'EXPLICIT'; EXTENDED_LOGICAL_CHECKS: 'EXTENDED_LOGICAL_CHECKS'; EXTENSION: 'EXTENSION'; EXTERNAL: 'EXTERNAL'; EXTERNAL_ACCESS: 'EXTERNAL_ACCESS'; FAILOVER: 'FAILOVER'; FAILOVER_MODE: 'FAILOVER_MODE'; FAILURE: 'FAILURE'; FAILURECONDITIONLEVEL: 'FAILURECONDITIONLEVEL'; FAILURE_CONDITION_LEVEL: 'FAILURE_CONDITION_LEVEL'; FAIL_OPERATION: 'FAIL_OPERATION'; FAN_IN: 'FAN_IN'; FAST: 'FAST'; FAST_FORWARD: 'FAST_FORWARD'; FETCH: 'FETCH'; FILE: 'FILE'; FILEGROUP: 'FILEGROUP'; FILEGROUPPROPERTY: 'FILEGROUPPROPERTY'; FILEGROUP_ID: 'FILEGROUP_ID'; FILEGROUP_NAME: 'FILEGROUP_NAME'; FILEGROWTH: 'FILEGROWTH'; FILENAME: 'FILENAME'; FILEPATH: 'FILEPATH'; FILEPROPERTY: 'FILEPROPERTY'; FILEPROPERTYEX: 'FILEPROPERTYEX'; FILESTREAM: 'FILESTREAM'; FILESTREAM_ON: 'FILESTREAM_ON'; FILE_ID: 'FILE_ID'; FILE_IDEX: 'FILE_IDEX'; FILE_NAME: 'FILE_NAME'; FILE_SNAPSHOT: 'FILE_SNAPSHOT'; FILLFACTOR: 'FILLFACTOR'; FILTER: 'FILTER'; FIRST: 'FIRST'; FIRST_VALUE: 'FIRST_VALUE'; FMTONLY: 'FMTONLY'; FOLLOWING: 'FOLLOWING'; FOR: 'FOR'; FORCE: 'FORCE'; FORCED: 'FORCED'; FORCEPLAN: 'FORCEPLAN'; FORCESCAN: 'FORCESCAN'; FORCESEEK: 'FORCESEEK'; FORCE_FAILOVER_ALLOW_DATA_LOSS: 'FORCE_FAILOVER_ALLOW_DATA_LOSS'; FORCE_SERVICE_ALLOW_DATA_LOSS: 'FORCE_SERVICE_ALLOW_DATA_LOSS'; FOREIGN: 'FOREIGN'; FORMAT: 'FORMAT'; FORMATMESSAGE: 'FORMATMESSAGE'; FORWARD_ONLY: 'FORWARD_ONLY'; FREE: 'FREE'; FREETEXT: 'FREETEXT'; FREETEXTTABLE: 'FREETEXTTABLE'; FROM: 'FROM'; FULL: 'FULL'; FULLSCAN: 'FULLSCAN'; FULLTEXT: 'FULLTEXT'; FULLTEXTCATALOGPROPERTY: 'FULLTEXTCATALOGPROPERTY'; FULLTEXTSERVICEPROPERTY: 'FULLTEXTSERVICEPROPERTY'; FUNCTION: 'FUNCTION'; GB: 'GB'; GENERATED: 'GENERATED'; GET: 'GET'; GETANCESTOR: 'GETANCESTOR'; GETANSINULL: 'GETANSINULL'; GETDATE: 'GETDATE'; GETDESCENDANT: 'GETDESCENDANT'; GETLEVEL: 'GETLEVEL'; GETREPARENTEDVALUE: 'GETREPARENTEDVALUE'; GETROOT: 'GETROOT'; GETUTCDATE: 'GETUTCDATE'; GET_FILESTREAM_TRANSACTION_CONTEXT: 'GET_FILESTREAM_TRANSACTION_CONTEXT'; GLOBAL: 'GLOBAL'; GO: 'GO'; GOTO: 'GOTO'; GOVERNOR: 'GOVERNOR'; GRANT: 'GRANT'; GREATEST: 'GREATEST'; GROUP: 'GROUP'; GROUPING: 'GROUPING'; GROUPING_ID: 'GROUPING_ID'; GROUP_MAX_REQUESTS: 'GROUP_MAX_REQUESTS'; HADR: 'HADR'; HASH: 'HASH'; HASHED: 'HASHED'; HAS_DBACCESS: 'HAS_DBACCESS'; HAS_PERMS_BY_NAME: 'HAS_PERMS_BY_NAME'; HAVING: 'HAVING'; HEALTHCHECKTIMEOUT: 'HEALTHCHECKTIMEOUT'; HEALTH_CHECK_TIMEOUT: 'HEALTH_CHECK_TIMEOUT'; HEAP: 'HEAP'; HIDDEN_KEYWORD: 'HIDDEN'; HIERARCHYID: 'HIERARCHYID'; HIGH: 'HIGH'; HOLDLOCK: 'HOLDLOCK'; HONOR_BROKER_PRIORITY: 'HONOR_BROKER_PRIORITY'; HOST_ID: 'HOST_ID'; HOST_NAME: 'HOST_NAME'; HOURS: 'HOURS'; IDENTITY: 'IDENTITY'; IDENTITYCOL: 'IDENTITYCOL'; IDENTITY_INSERT: 'IDENTITY_INSERT'; IDENTITY_VALUE: 'IDENTITY_VALUE'; IDENT_CURRENT: 'IDENT_CURRENT'; IDENT_INCR: 'IDENT_INCR'; IDENT_SEED: 'IDENT_SEED'; IF: 'IF'; IGNORE_CONSTRAINTS: 'IGNORE_CONSTRAINTS'; IGNORE_DUP_KEY: 'IGNORE_DUP_KEY'; IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX: 'IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX'; IGNORE_REPLICATED_TABLE_CACHE: 'IGNORE_REPLICATED_TABLE_CACHE'; IGNORE_TRIGGERS: 'IGNORE_TRIGGERS'; IIF: 'IIF'; IMMEDIATE: 'IMMEDIATE'; IMPERSONATE: 'IMPERSONATE'; IMPLICIT_TRANSACTIONS: 'IMPLICIT_TRANSACTIONS'; IMPORTANCE: 'IMPORTANCE'; IN: 'IN'; INCLUDE: 'INCLUDE'; INCLUDE_NULL_VALUES: 'INCLUDE_NULL_VALUES'; INCREMENT: 'INCREMENT'; INCREMENTAL: 'INCREMENTAL'; INDEX: 'INDEX'; INDEXKEY_PROPERTY: 'INDEXKEY_PROPERTY'; INDEXPROPERTY: 'INDEXPROPERTY'; INDEX_COL: 'INDEX_COL'; INFINITE: 'INFINITE'; INIT: 'INIT'; INITIATOR: 'INITIATOR'; INNER: 'INNER'; INPUT: 'INPUT'; INSENSITIVE: 'INSENSITIVE'; INSERT: 'INSERT'; INSERTED: 'INSERTED'; INSTEAD: 'INSTEAD'; INT: 'INT'; INTERSECT: 'INTERSECT'; INTO: 'INTO'; IO: 'IO'; IP: 'IP'; IS: 'IS'; ISDESCENDANTOF: 'ISDESCENDANTOF'; ISJSON: 'ISJSON'; ISNULL: 'ISNULL'; ISNUMERIC: 'ISNUMERIC'; ISOLATION: 'ISOLATION'; IS_MEMBER: 'IS_MEMBER'; IS_ROLEMEMBER: 'IS_ROLEMEMBER'; IS_SRVROLEMEMBER: 'IS_SRVROLEMEMBER'; JOB: 'JOB'; JOIN: 'JOIN'; JSON: 'JSON'; JSON_ARRAY: 'JSON_ARRAY'; JSON_MODIFY: 'JSON_MODIFY'; JSON_OBJECT: 'JSON_OBJECT'; JSON_PATH_EXISTS: 'JSON_PATH_EXISTS'; JSON_QUERY: 'JSON_QUERY'; JSON_VALUE: 'JSON_VALUE'; KB: 'KB'; KEEP: 'KEEP'; KEEPDEFAULTS: 'KEEPDEFAULTS'; KEEPFIXED: 'KEEPFIXED'; KEEPIDENTITY: 'KEEPIDENTITY'; KERBEROS: 'KERBEROS'; KEY: 'KEY'; KEYS: 'KEYS'; KEYSET: 'KEYSET'; KEY_PATH: 'KEY_PATH'; KEY_SOURCE: 'KEY_SOURCE'; KEY_STORE_PROVIDER_NAME: 'KEY_STORE_PROVIDER_NAME'; KILL: 'KILL'; LAG: 'LAG'; LANGUAGE: 'LANGUAGE'; LAST: 'LAST'; LAST_VALUE: 'LAST_VALUE'; LEAD: 'LEAD'; LEAST: 'LEAST'; LEFT: 'LEFT'; LEN: 'LEN'; LEVEL: 'LEVEL'; LIBRARY: 'LIBRARY'; LIFETIME: 'LIFETIME'; LIKE: 'LIKE'; LINENO: 'LINENO'; LINKED: 'LINKED'; LINUX: 'LINUX'; LIST: 'LIST'; LISTENER: 'LISTENER'; LISTENER_IP: 'LISTENER_IP'; LISTENER_PORT: 'LISTENER_PORT'; LISTENER_URL: 'LISTENER_URL'; LOAD: 'LOAD'; LOB_COMPACTION: 'LOB_COMPACTION'; LOCAL: 'LOCAL'; LOCAL_SERVICE_NAME: 'LOCAL_SERVICE_NAME'; LOCATION: 'LOCATION'; LOCK: 'LOCK'; LOCK_ESCALATION: 'LOCK_ESCALATION'; LOG: 'LOG'; LOGIN: 'LOGIN'; LOGINPROPERTY: 'LOGINPROPERTY'; LOOP: 'LOOP'; LOW: 'LOW'; LOWER: 'LOWER'; LTRIM: 'LTRIM'; MANUAL: 'MANUAL'; MARK: 'MARK'; MASK: 'MASK'; MASKED: 'MASKED'; MASTER: 'MASTER'; MATCHED: 'MATCHED'; MATERIALIZED: 'MATERIALIZED'; MAX: 'MAX'; MAXDOP: 'MAXDOP'; MAXRECURSION: 'MAXRECURSION'; MAXSIZE: 'MAXSIZE'; MAXTRANSFER: 'MAXTRANSFER'; MAXVALUE: 'MAXVALUE'; MAX_CPU_PERCENT: 'MAX_CPU_PERCENT'; MAX_DISPATCH_LATENCY: 'MAX_DISPATCH_LATENCY'; MAX_DOP: 'MAX_DOP'; MAX_DURATION: 'MAX_DURATION'; MAX_EVENT_SIZE: 'MAX_EVENT_SIZE'; MAX_FILES: 'MAX_FILES'; MAX_IOPS_PER_VOLUME: 'MAX_IOPS_PER_VOLUME'; MAX_MEMORY: 'MAX_MEMORY'; MAX_MEMORY_PERCENT: 'MAX_MEMORY_PERCENT'; MAX_OUTSTANDING_IO_PER_VOLUME: 'MAX_OUTSTANDING_IO_PER_VOLUME'; MAX_PROCESSES: 'MAX_PROCESSES'; MAX_QUEUE_READERS: 'MAX_QUEUE_READERS'; MAX_ROLLOVER_FILES: 'MAX_ROLLOVER_FILES'; MAX_SIZE: 'MAX_SIZE'; MB: 'MB'; MEDIADESCRIPTION: 'MEDIADESCRIPTION'; MEDIANAME: 'MEDIANAME'; MEDIUM: 'MEDIUM'; MEMBER: 'MEMBER'; MEMORY_OPTIMIZED_DATA: 'MEMORY_OPTIMIZED_DATA'; MEMORY_PARTITION_MODE: 'MEMORY_PARTITION_MODE'; MERGE: 'MERGE'; MESSAGE: 'MESSAGE'; MESSAGE_FORWARDING: 'MESSAGE_FORWARDING'; MESSAGE_FORWARD_SIZE: 'MESSAGE_FORWARD_SIZE'; MIN: 'MIN'; MINUTES: 'MINUTES'; MINVALUE: 'MINVALUE'; MIN_ACTIVE_ROWVERSION: 'MIN_ACTIVE_ROWVERSION'; MIN_CPU_PERCENT: 'MIN_CPU_PERCENT'; MIN_IOPS_PER_VOLUME: 'MIN_IOPS_PER_VOLUME'; MIN_MEMORY_PERCENT: 'MIN_MEMORY_PERCENT'; MIRROR: 'MIRROR'; MIRROR_ADDRESS: 'MIRROR_ADDRESS'; MIXED_PAGE_ALLOCATION: 'MIXED_PAGE_ALLOCATION'; MODE: 'MODE'; MODIFY: 'MODIFY'; MODIFY_SQUARE_BRACKET: '[MODIFY]'; MOVE: 'MOVE'; MULTI_USER: 'MULTI_USER'; MUST_CHANGE: 'MUST_CHANGE'; NAME: 'NAME'; NATIONAL: 'NATIONAL'; NCHAR: 'NCHAR'; NEGOTIATE: 'NEGOTIATE'; NESTED_TRIGGERS: 'NESTED_TRIGGERS'; NEWID: 'NEWID'; NEWNAME: 'NEWNAME'; NEWSEQUENTIALID: 'NEWSEQUENTIALID'; NEW_ACCOUNT: 'NEW_ACCOUNT'; NEW_BROKER: 'NEW_BROKER'; NEW_PASSWORD: 'NEW_PASSWORD'; NEXT: 'NEXT'; NO: 'NO'; NOCHECK: 'NOCHECK'; NOCOUNT: 'NOCOUNT'; NODES: 'NODES'; NOEXEC: 'NOEXEC'; NOEXPAND: 'NOEXPAND'; NOFORMAT: 'NOFORMAT'; NOHOLDLOCK: 'NOHOLDLOCK'; NOINDEX: 'NOINDEX'; NOINIT: 'NOINIT'; NOLOCK: 'NOLOCK'; NONCLUSTERED: 'NONCLUSTERED'; NONE: 'NONE'; NON_TRANSACTED_ACCESS: 'NON_TRANSACTED_ACCESS'; NORECOMPUTE: 'NORECOMPUTE'; NORECOVERY: 'NORECOVERY'; NOREWIND: 'NOREWIND'; NOSKIP: 'NOSKIP'; NOT: 'NOT'; NOTIFICATION: 'NOTIFICATION'; NOTIFICATIONS: 'NOTIFICATIONS'; NOUNLOAD: 'NOUNLOAD'; NOWAIT: 'NOWAIT'; NO_CHECKSUM: 'NO_CHECKSUM'; NO_COMPRESSION: 'NO_COMPRESSION'; NO_EVENT_LOSS: 'NO_EVENT_LOSS'; NO_INFOMSGS: 'NO_INFOMSGS'; NO_QUERYSTORE: 'NO_QUERYSTORE'; NO_STATISTICS: 'NO_STATISTICS'; NO_TRUNCATE: 'NO_TRUNCATE'; NO_WAIT: 'NO_WAIT'; NTILE: 'NTILE'; NTLM: 'NTLM'; NULLIF: 'NULLIF'; NULL_: 'NULL'; NULL_DOUBLE_QUOTE: ["]'NULL'["]; NUMANODE: 'NUMANODE'; NUMBER: 'NUMBER'; NUMERIC_ROUNDABORT: 'NUMERIC_ROUNDABORT'; OBJECT: 'OBJECT'; OBJECTPROPERTY: 'OBJECTPROPERTY'; OBJECTPROPERTYEX: 'OBJECTPROPERTYEX'; OBJECT_DEFINITION: 'OBJECT_DEFINITION'; OBJECT_ID: 'OBJECT_ID'; OBJECT_NAME: 'OBJECT_NAME'; OBJECT_SCHEMA_NAME: 'OBJECT_SCHEMA_NAME'; OF: 'OF'; OFF: 'OFF'; OFFLINE: 'OFFLINE'; OFFSET: 'OFFSET'; OFFSETS: 'OFFSETS'; OLD_ACCOUNT: 'OLD_ACCOUNT'; OLD_PASSWORD: 'OLD_PASSWORD'; ON: 'ON'; ONLINE: 'ONLINE'; ONLY: 'ONLY'; ON_FAILURE: 'ON_FAILURE'; OPEN: 'OPEN'; OPENDATASOURCE: 'OPENDATASOURCE'; OPENJSON: 'OPENJSON'; OPENQUERY: 'OPENQUERY'; OPENROWSET: 'OPENROWSET'; OPENXML: 'OPENXML'; OPEN_EXISTING: 'OPEN_EXISTING'; OPERATIONS: 'OPERATIONS'; OPTIMISTIC: 'OPTIMISTIC'; OPTIMIZE: 'OPTIMIZE'; OPTIMIZE_FOR_SEQUENTIAL_KEY: 'OPTIMIZE_FOR_SEQUENTIAL_KEY'; OPTION: 'OPTION'; OR: 'OR'; ORDER: 'ORDER'; ORIGINAL_DB_NAME: 'ORIGINAL_DB_NAME'; ORIGINAL_LOGIN: 'ORIGINAL_LOGIN'; OUT: 'OUT'; OUTER: 'OUTER'; OUTPUT: 'OUTPUT'; OVER: 'OVER'; OVERRIDE: 'OVERRIDE'; OWNER: 'OWNER'; OWNERSHIP: 'OWNERSHIP'; PAD_INDEX: 'PAD_INDEX'; PAGE: 'PAGE'; PAGECOUNT: 'PAGECOUNT'; PAGE_VERIFY: 'PAGE_VERIFY'; PAGLOCK: 'PAGLOCK'; PARAMETERIZATION: 'PARAMETERIZATION'; PARAM_NODE: 'PARAM_NODE'; PARSE: 'TRY_'? 'PARSE'; PARSENAME: 'PARSENAME'; PARSEONLY: 'PARSEONLY'; PARTIAL: 'PARTIAL'; PARTITION: 'PARTITION'; PARTITIONS: 'PARTITIONS'; PARTNER: 'PARTNER'; PASSWORD: 'PASSWORD'; PATH: 'PATH'; PATINDEX: 'PATINDEX'; PAUSE: 'PAUSE'; PDW_SHOWSPACEUSED: 'PDW_SHOWSPACEUSED'; PERCENT: 'PERCENT'; PERCENTILE_CONT: 'PERCENTILE_CONT'; PERCENTILE_DISC: 'PERCENTILE_DISC'; PERCENT_RANK: 'PERCENT_RANK'; PERMISSIONS: 'PERMISSIONS'; PERMISSION_SET: 'PERMISSION_SET'; PERSISTED: 'PERSISTED'; PERSIST_SAMPLE_PERCENT: 'PERSIST_SAMPLE_PERCENT'; PER_CPU: 'PER_CPU'; PER_DB: 'PER_DB'; PER_NODE: 'PER_NODE'; PHYSICAL_ONLY: 'PHYSICAL_ONLY'; PIVOT: 'PIVOT'; PLAN: 'PLAN'; PLATFORM: 'PLATFORM'; POISON_MESSAGE_HANDLING: 'POISON_MESSAGE_HANDLING'; POLICY: 'POLICY'; POOL: 'POOL'; PORT: 'PORT'; PRECEDING: 'PRECEDING'; PRECISION: 'PRECISION'; PREDICATE: 'PREDICATE'; PRIMARY: 'PRIMARY'; PRIMARY_ROLE: 'PRIMARY_ROLE'; PRINT: 'PRINT'; PRIOR: 'PRIOR'; PRIORITY: 'PRIORITY'; PRIORITY_LEVEL: 'PRIORITY_LEVEL'; PRIVATE: 'PRIVATE'; PRIVATE_KEY: 'PRIVATE_KEY'; PRIVILEGES: 'PRIVILEGES'; PROC: 'PROC'; PROCCACHE: 'PROCCACHE'; PROCEDURE: 'PROCEDURE'; PROCEDURE_NAME: 'PROCEDURE_NAME'; PROCESS: 'PROCESS'; PROFILE: 'PROFILE'; PROPERTY: 'PROPERTY'; PROVIDER: 'PROVIDER'; PROVIDER_KEY_NAME: 'PROVIDER_KEY_NAME'; PUBLIC: 'PUBLIC'; PWDCOMPARE: 'PWDCOMPARE'; PWDENCRYPT: 'PWDENCRYPT'; PYTHON: 'PYTHON'; QUERY: 'QUERY'; QUERY_SQUARE_BRACKET: '[QUERY]'; QUEUE: 'QUEUE'; QUEUE_DELAY: 'QUEUE_DELAY'; QUOTED_IDENTIFIER: 'QUOTED_IDENTIFIER'; QUOTENAME: 'QUOTENAME'; R: 'R'; RAISERROR: 'RAISERROR'; RANDOMIZED: 'RANDOMIZED'; RANGE: 'RANGE'; RANK: 'RANK'; RAW: 'RAW'; RC2: 'RC2'; RC4: 'RC4'; RC4_128: 'RC4_128'; READ: 'READ'; READCOMMITTED: 'READCOMMITTED'; READCOMMITTEDLOCK: 'READCOMMITTEDLOCK'; READONLY: 'READONLY'; READPAST: 'READPAST'; READTEXT: 'READTEXT'; READUNCOMMITTED: 'READUNCOMMITTED'; READWRITE: 'READWRITE'; READ_COMMITTED_SNAPSHOT: 'READ_COMMITTED_SNAPSHOT'; READ_ONLY: 'READ_ONLY'; READ_ONLY_ROUTING_LIST: 'READ_ONLY_ROUTING_LIST'; READ_WRITE: 'READ_WRITE'; READ_WRITE_FILEGROUPS: 'READ_WRITE_FILEGROUPS'; REBUILD: 'REBUILD'; RECEIVE: 'RECEIVE'; RECOMPILE: 'RECOMPILE'; RECONFIGURE: 'RECONFIGURE'; RECOVERY: 'RECOVERY'; RECURSIVE_TRIGGERS: 'RECURSIVE_TRIGGERS'; REFERENCES: 'REFERENCES'; REGENERATE: 'REGENERATE'; RELATED_CONVERSATION: 'RELATED_CONVERSATION'; RELATED_CONVERSATION_GROUP: 'RELATED_CONVERSATION_GROUP'; RELATIVE: 'RELATIVE'; REMOTE: 'REMOTE'; REMOTE_PROC_TRANSACTIONS: 'REMOTE_PROC_TRANSACTIONS'; REMOTE_SERVICE_NAME: 'REMOTE_SERVICE_NAME'; REMOVE: 'REMOVE'; REORGANIZE: 'REORGANIZE'; REPAIR_ALLOW_DATA_LOSS: 'REPAIR_ALLOW_DATA_LOSS'; REPAIR_FAST: 'REPAIR_FAST'; REPAIR_REBUILD: 'REPAIR_REBUILD'; REPEATABLE: 'REPEATABLE'; REPEATABLEREAD: 'REPEATABLEREAD'; REPLACE: 'REPLACE'; REPLICA: 'REPLICA'; REPLICATE: 'REPLICATE'; REPLICATION: 'REPLICATION'; REQUEST_MAX_CPU_TIME_SEC: 'REQUEST_MAX_CPU_TIME_SEC'; REQUEST_MAX_MEMORY_GRANT_PERCENT: 'REQUEST_MAX_MEMORY_GRANT_PERCENT'; REQUEST_MEMORY_GRANT_TIMEOUT_SEC: 'REQUEST_MEMORY_GRANT_TIMEOUT_SEC'; REQUIRED: 'REQUIRED'; REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT: 'REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT'; RESAMPLE: 'RESAMPLE'; RESERVE_DISK_SPACE: 'RESERVE_DISK_SPACE'; RESET: 'RESET'; RESOURCE: 'RESOURCE'; RESOURCES: 'RESOURCES'; RESOURCE_MANAGER_LOCATION: 'RESOURCE_MANAGER_LOCATION'; RESTART: 'RESTART'; RESTORE: 'RESTORE'; RESTRICT: 'RESTRICT'; RESTRICTED_USER: 'RESTRICTED_USER'; RESUMABLE: 'RESUMABLE'; RESUME: 'RESUME'; RETAINDAYS: 'RETAINDAYS'; RETENTION: 'RETENTION'; RETURN: 'RETURN'; RETURNS: 'RETURNS'; REVERSE: 'REVERSE'; REVERT: 'REVERT'; REVOKE: 'REVOKE'; REWIND: 'REWIND'; RIGHT: 'RIGHT'; ROBUST: 'ROBUST'; ROLE: 'ROLE'; ROLLBACK: 'ROLLBACK'; ROOT: 'ROOT'; ROUND_ROBIN: 'ROUND_ROBIN'; ROUTE: 'ROUTE'; ROW: 'ROW'; ROWCOUNT: 'ROWCOUNT'; ROWCOUNT_BIG: 'ROWCOUNT_BIG'; ROWGUID: 'ROWGUID'; ROWGUIDCOL: 'ROWGUIDCOL'; ROWLOCK: 'ROWLOCK'; ROWS: 'ROWS'; ROW_NUMBER: 'ROW_NUMBER'; RSA_1024: 'RSA_1024'; RSA_2048: 'RSA_2048'; RSA_3072: 'RSA_3072'; RSA_4096: 'RSA_4096'; RSA_512: 'RSA_512'; RTRIM: 'RTRIM'; RULE: 'RULE'; SAFE: 'SAFE'; SAFETY: 'SAFETY'; SAMPLE: 'SAMPLE'; SAVE: 'SAVE'; SCHEDULER: 'SCHEDULER'; SCHEMA: 'SCHEMA'; SCHEMABINDING: 'SCHEMABINDING'; SCHEMA_ID: 'SCHEMA_ID'; SCHEMA_NAME: 'SCHEMA_NAME'; SCHEME: 'SCHEME'; SCOPED: 'SCOPED'; SCOPE_IDENTITY: 'SCOPE_IDENTITY'; SCRIPT: 'SCRIPT'; SCROLL: 'SCROLL'; SCROLL_LOCKS: 'SCROLL_LOCKS'; SEARCH: 'SEARCH'; SECONDARY: 'SECONDARY'; SECONDARY_ONLY: 'SECONDARY_ONLY'; SECONDARY_ROLE: 'SECONDARY_ROLE'; SECONDS: 'SECONDS'; SECRET: 'SECRET'; SECURABLES: 'SECURABLES'; SECURITY: 'SECURITY'; SECURITYAUDIT: 'SECURITYAUDIT'; SECURITY_LOG: 'SECURITY_LOG'; SEEDING_MODE: 'SEEDING_MODE'; SELECT: 'SELECT'; SELF: 'SELF'; SEMANTICKEYPHRASETABLE: 'SEMANTICKEYPHRASETABLE'; SEMANTICSIMILARITYDETAILSTABLE: 'SEMANTICSIMILARITYDETAILSTABLE'; SEMANTICSIMILARITYTABLE: 'SEMANTICSIMILARITYTABLE'; SEMI_SENSITIVE: 'SEMI_SENSITIVE'; SEND: 'SEND'; SENT: 'SENT'; SEQUENCE: 'SEQUENCE'; SEQUENCE_NUMBER: 'SEQUENCE_NUMBER'; SERIALIZABLE: 'SERIALIZABLE'; SERVER: 'SERVER'; SERVERPROPERTY: 'SERVERPROPERTY'; SERVICE: 'SERVICE'; SERVICEBROKER: 'SERVICEBROKER'; SERVICE_BROKER: 'SERVICE_BROKER'; SERVICE_NAME: 'SERVICE_NAME'; SESSION: 'SESSION'; SESSIONPROPERTY: 'SESSIONPROPERTY'; SESSION_CONTEXT: 'SESSION_CONTEXT'; SESSION_TIMEOUT: 'SESSION_TIMEOUT'; SESSION_USER: 'SESSION_USER'; SET: 'SET'; SETERROR: 'SETERROR'; SETS: 'SETS'; SETTINGS: 'SETTINGS'; SETUSER: 'SETUSER'; SHARE: 'SHARE'; SHARED: 'SHARED'; SHOWCONTIG: 'SHOWCONTIG'; SHOWPLAN: 'SHOWPLAN'; SHOWPLAN_ALL: 'SHOWPLAN_ALL'; SHOWPLAN_TEXT: 'SHOWPLAN_TEXT'; SHOWPLAN_XML: 'SHOWPLAN_XML'; SHRINKLOG: 'SHRINKLOG'; SHUTDOWN: 'SHUTDOWN'; SID: 'SID'; SIGNATURE: 'SIGNATURE'; SIMPLE: 'SIMPLE'; SINGLE_USER: 'SINGLE_USER'; SIZE: 'SIZE'; SKIP_KEYWORD: 'SKIP'; SMALLINT: 'SMALLINT'; SNAPSHOT: 'SNAPSHOT'; SOFTNUMA: 'SOFTNUMA'; SOME: 'SOME'; SORT_IN_TEMPDB: 'SORT_IN_TEMPDB'; SOUNDEX: 'SOUNDEX'; SOURCE: 'SOURCE'; SPACE_KEYWORD: 'SPACE'; SPARSE: 'SPARSE'; SPATIAL_WINDOW_MAX_CELLS: 'SPATIAL_WINDOW_MAX_CELLS'; SPECIFICATION: 'SPECIFICATION'; SPLIT: 'SPLIT'; SQL: 'SQL'; SQLDUMPERFLAGS: 'SQLDUMPERFLAGS'; SQLDUMPERPATH: 'SQLDUMPERPATH'; SQLDUMPERTIMEOUT: 'SQLDUMPERTIMEOUT'; SQL_VARIANT_PROPERTY: 'SQL_VARIANT_PROPERTY'; STANDBY: 'STANDBY'; START: 'START'; STARTED: 'STARTED'; STARTUP_STATE: 'STARTUP_STATE'; START_DATE: 'START_DATE'; STATE: 'STATE'; STATIC: 'STATIC'; STATISTICS: 'STATISTICS'; STATISTICS_INCREMENTAL: 'STATISTICS_INCREMENTAL'; STATISTICS_NORECOMPUTE: 'STATISTICS_NORECOMPUTE'; STATS: 'STATS'; STATS_DATE: 'STATS_DATE'; STATS_STREAM: 'STATS_STREAM'; STATUS: 'STATUS'; STATUSONLY: 'STATUSONLY'; STDEV: 'STDEV'; STDEVP: 'STDEVP'; STOP: 'STOP'; STOPLIST: 'STOPLIST'; STOPPED: 'STOPPED'; STOP_ON_ERROR: 'STOP_ON_ERROR'; STR: 'STR'; STRING_AGG: 'STRING_AGG'; STRING_ESCAPE: 'STRING_ESCAPE'; STUFF: 'STUFF'; SUBJECT: 'SUBJECT'; SUBSCRIBE: 'SUBSCRIBE'; SUBSCRIPTION: 'SUBSCRIPTION'; SUBSTRING: 'SUBSTRING'; SUM: 'SUM'; SUPPORTED: 'SUPPORTED'; SUSER_ID: 'SUSER_ID'; SUSER_NAME: 'SUSER_NAME'; SUSER_SID: 'SUSER_SID'; SUSER_SNAME: 'SUSER_SNAME'; SUSPEND: 'SUSPEND'; SWITCH: 'SWITCH'; SYMMETRIC: 'SYMMETRIC'; SYNCHRONOUS_COMMIT: 'SYNCHRONOUS_COMMIT'; SYNONYM: 'SYNONYM'; SYSTEM: 'SYSTEM'; SYSTEM_USER: 'SYSTEM_USER'; TABLE: 'TABLE'; TABLERESULTS: 'TABLERESULTS'; TABLESAMPLE: 'TABLESAMPLE'; TABLOCK: 'TABLOCK'; TABLOCKX: 'TABLOCKX'; TAKE: 'TAKE'; TAPE: 'TAPE'; TARGET: 'TARGET'; TARGET_RECOVERY_TIME: 'TARGET_RECOVERY_TIME'; TB: 'TB'; TCP: 'TCP'; TEXTIMAGE_ON: 'TEXTIMAGE_ON'; TEXTSIZE: 'TEXTSIZE'; THEN: 'THEN'; THROW: 'THROW'; TIES: 'TIES'; TIME: 'TIME'; TIMEOUT: 'TIMEOUT'; TIMER: 'TIMER'; TINYINT: 'TINYINT'; TO: 'TO'; TOP: 'TOP'; TORN_PAGE_DETECTION: 'TORN_PAGE_DETECTION'; TOSTRING: 'TOSTRING'; TRACE: 'TRACE'; TRACKING: 'TRACKING'; TRACK_CAUSALITY: 'TRACK_CAUSALITY'; TRAN: 'TRAN'; TRANSACTION: 'TRANSACTION'; TRANSACTION_ID: 'TRANSACTION_ID'; TRANSFER: 'TRANSFER'; TRANSFORM_NOISE_WORDS: 'TRANSFORM_NOISE_WORDS'; TRANSLATE: 'TRANSLATE'; TRIGGER: 'TRIGGER'; TRIM: 'TRIM'; TRIPLE_DES: 'TRIPLE_DES'; TRIPLE_DES_3KEY: 'TRIPLE_DES_3KEY'; TRUNCATE: 'TRUNCATE'; TRUSTWORTHY: 'TRUSTWORTHY'; TRY: 'TRY'; TRY_CAST: 'TRY_CAST'; TSEQUAL: 'TSEQUAL'; TSQL: 'TSQL'; TWO_DIGIT_YEAR_CUTOFF: 'TWO_DIGIT_YEAR_CUTOFF'; TYPE: 'TYPE'; TYPEPROPERTY: 'TYPEPROPERTY'; TYPE_ID: 'TYPE_ID'; TYPE_NAME: 'TYPE_NAME'; TYPE_WARNING: 'TYPE_WARNING'; UNBOUNDED: 'UNBOUNDED'; UNCHECKED: 'UNCHECKED'; UNCOMMITTED: 'UNCOMMITTED'; UNICODE: 'UNICODE'; UNION: 'UNION'; UNIQUE: 'UNIQUE'; UNKNOWN: 'UNKNOWN'; UNLIMITED: 'UNLIMITED'; UNLOCK: 'UNLOCK'; UNMASK: 'UNMASK'; UNPIVOT: 'UNPIVOT'; UNSAFE: 'UNSAFE'; UOW: 'UOW'; UPDATE: 'UPDATE'; UPDATETEXT: 'UPDATETEXT'; UPDLOCK: 'UPDLOCK'; UPPER: 'UPPER'; URL: 'URL'; USE: 'USE'; USED: 'USED'; USER: 'USER'; USER_ID: 'USER_ID'; USER_NAME: 'USER_NAME'; USING: 'USING'; VALIDATION: 'VALIDATION'; VALID_XML: 'VALID_XML'; VALUE: 'VALUE'; VALUES: 'VALUES'; VALUE_SQUARE_BRACKET: '[VALUE]'; VAR: 'VAR'; VARBINARY_KEYWORD: 'VARBINARY'; VARP: 'VARP'; VARYING: 'VARYING'; VERBOSELOGGING: 'VERBOSELOGGING'; VERIFY_CLONEDB: 'VERIFY_CLONEDB'; VERSION: 'VERSION'; VIEW: 'VIEW'; VIEWS: 'VIEWS'; VIEW_METADATA: 'VIEW_METADATA'; VISIBILITY: 'VISIBILITY'; WAIT: 'WAIT'; WAITFOR: 'WAITFOR'; WAIT_AT_LOW_PRIORITY: 'WAIT_AT_LOW_PRIORITY'; WELL_FORMED_XML: 'WELL_FORMED_XML'; WHEN: 'WHEN'; WHERE: 'WHERE'; WHILE: 'WHILE'; WINDOWS: 'WINDOWS'; WITH: 'WITH'; WITHIN: 'WITHIN'; WITHOUT: 'WITHOUT'; WITHOUT_ARRAY_WRAPPER: 'WITHOUT_ARRAY_WRAPPER'; WITNESS: 'WITNESS'; WORK: 'WORK'; WORKLOAD: 'WORKLOAD'; WRITETEXT: 'WRITETEXT'; XACT_ABORT: 'XACT_ABORT'; XACT_STATE: 'XACT_STATE'; XLOCK: 'XLOCK'; XML: 'XML'; XMLDATA: 'XMLDATA'; XMLNAMESPACES: 'XMLNAMESPACES'; XMLSCHEMA: 'XMLSCHEMA'; XML_COMPRESSION: 'XML_COMPRESSION'; XSINIL: 'XSINIL'; ZONE: 'ZONE'; ABS: 'ABS'; ACOS: 'ACOS'; ASIN: 'ASIN'; ATAN: 'ATAN'; ATN2: 'ATN2'; CEILING: 'CEILING'; COS: 'COS'; COT: 'COT'; DEGREES: 'DEGREES'; EXP: 'EXP'; FLOOR: 'FLOOR'; LOG10: 'LOG10'; PI: 'PI'; POWER: 'POWER'; RADIANS: 'RADIANS'; RAND: 'RAND'; ROUND: 'ROUND'; SIGN: 'SIGN'; SIN: 'SIN'; SQRT: 'SQRT'; SQUARE: 'SQUARE'; TAN: 'TAN'; CURRENT_TIMEZONE: 'CURRENT_TIMEZONE'; CURRENT_TIMEZONE_ID: 'CURRENT_TIMEZONE_ID'; DATE_BUCKET: 'DATE_BUCKET'; DATEDIFF_BIG: 'DATEDIFF_BIG'; DATEFROMPARTS: 'DATEFROMPARTS'; DATETIME2FROMPARTS: 'DATETIME2FROMPARTS'; DATETIMEFROMPARTS: 'DATETIMEFROMPARTS'; DATETIMEOFFSETFROMPARTS: 'DATETIMEOFFSETFROMPARTS'; DATETRUNC: 'DATETRUNC'; DAY: 'DAY'; EOMONTH: 'EOMONTH'; ISDATE: 'ISDATE'; MONTH: 'MONTH'; SMALLDATETIMEFROMPARTS: 'SMALLDATETIMEFROMPARTS'; SWITCHOFFSET: 'SWITCHOFFSET'; SYSDATETIME: 'SYSDATETIME'; SYSDATETIMEOFFSET: 'SYSDATETIMEOFFSET'; SYSUTCDATETIME: 'SYSUTCDATETIME'; TIMEFROMPARTS: 'TIMEFROMPARTS'; TODATETIMEOFFSET: 'TODATETIMEOFFSET'; YEAR: 'YEAR'; QUARTER: 'QUARTER'; DAYOFYEAR: 'DAYOFYEAR'; WEEK: 'WEEK'; HOUR: 'HOUR'; MINUTE: 'MINUTE'; SECOND: 'SECOND'; MILLISECOND: 'MILLISECOND'; MICROSECOND: 'MICROSECOND'; NANOSECOND: 'NANOSECOND'; TZOFFSET: 'TZOFFSET'; ISO_WEEK: 'ISO_WEEK'; WEEKDAY: 'WEEKDAY'; YEAR_ABBR: 'yy' | 'yyyy'; QUARTER_ABBR: 'qq' | 'q'; MONTH_ABBR: 'mm' | 'm'; DAYOFYEAR_ABBR: 'dy' | 'y'; DAY_ABBR: 'dd' | 'd'; WEEK_ABBR: 'wk' | 'ww'; HOUR_ABBR: 'hh'; MINUTE_ABBR: 'mi' | 'n'; SECOND_ABBR: 'ss' | 's'; MILLISECOND_ABBR: 'ms'; MICROSECOND_ABBR: 'mcs'; NANOSECOND_ABBR: 'ns'; TZOFFSET_ABBR: 'tz'; ISO_WEEK_ABBR: 'isowk' | 'isoww'; WEEKDAY_ABBR: 'dw'; SP_EXECUTESQL: 'SP_EXECUTESQL'; //Build-ins: VARCHAR: 'VARCHAR'; NVARCHAR: 'NVARCHAR'; //Combinations that cannot be used as IDs DISK_DRIVE: [A-Z][:]; DOLLAR_ACTION: '$ACTION'; // Functions starting with double at signs // https://learn.microsoft.com/en-us/sql/t-sql/language-elements/variables-transact-sql?view=sql-server-ver16 CURSOR_ROWS: '@@CURSOR_ROWS'; FETCH_STATUS: '@@FETCH_STATUS'; IPV4_ADDR: DEC_DIGIT+ '.' DEC_DIGIT+ '.' DEC_DIGIT+ '.' DEC_DIGIT+; SPACE: [ \t\r\n]+ -> skip; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/slash-star-comment-transact-sql COMMENT: '/*' (COMMENT | .)*? '*/' -> channel(HIDDEN); LINE_COMMENT: '--' ~[\r\n]* -> channel(HIDDEN); // TODO: ID can be not only Latin. DOUBLE_QUOTE_ID: '"' ~'"'+ '"'; DOUBLE_QUOTE_BLANK: '""'; SINGLE_QUOTE: '\''; SQUARE_BRACKET_ID: '[' (~']' | ']' ']')* ']'; LOCAL_ID: '@' ([A-Z_$@#0-9] | FullWidthLetter)*; TEMP_ID: '#' ([A-Z_$@#0-9] | FullWidthLetter)*; DECIMAL: DEC_DIGIT+; ID: ( [A-Z_#] | FullWidthLetter) ( [A-Z_#$@0-9] | FullWidthLetter )*; STRING : 'N'? '\'' (~'\'' | '\'\'')* '\''; BINARY: '0' 'X' HEX_DIGIT*; FLOAT: DEC_DOT_DEC; REAL: (DECIMAL | DEC_DOT_DEC) ('E' [+-]? DEC_DIGIT+); EQUAL: '='; GREATER: '>'; LESS: '<'; EXCLAMATION: '!'; PLUS_ASSIGN: '+='; MINUS_ASSIGN: '-='; MULT_ASSIGN: '*='; DIV_ASSIGN: '/='; MOD_ASSIGN: '%='; AND_ASSIGN: '&='; XOR_ASSIGN: '^='; OR_ASSIGN: '|='; DOUBLE_BAR: '||'; DOT: '.'; UNDERLINE: '_'; AT: '@'; SHARP: '#'; DOLLAR: '$'; LR_BRACKET: '('; RR_BRACKET: ')'; COMMA: ','; SEMI: ';'; COLON: ':'; DOUBLE_COLON: '::'; STAR: '*'; DIVIDE: '/'; MODULE: '%'; PLUS: '+'; MINUS: '-'; BIT_NOT: '~'; BIT_OR: '|'; BIT_AND: '&'; BIT_XOR: '^'; PLACEHOLDER: '?'; fragment LETTER: [A-Z_]; fragment DEC_DOT_DEC: (DEC_DIGIT+ '.' DEC_DIGIT+ | DEC_DIGIT+ '.' | '.' DEC_DIGIT+); fragment HEX_DIGIT: [0-9A-F]; fragment DEC_DIGIT: [0-9]; fragment FullWidthLetter : '\u00c0'..'\u00d6' | '\u00d8'..'\u00f6' | '\u00f8'..'\u00ff' | '\u0100'..'\u1fff' | '\u2c00'..'\u2fff' | '\u3040'..'\u318f' | '\u3300'..'\u337f' | '\u3400'..'\u3fff' | '\u4e00'..'\u9fff' | '\ua000'..'\ud7ff' | '\uf900'..'\ufaff' | '\uff00'..'\ufff0' // | '\u10000'..'\u1F9FF' //not support four bytes chars // | '\u20000'..'\u2FA1F' ; ================================================ FILE: superior-sqlserver-parser/src/main/antlr4/io/github/melin/superior/parser/sqlserver/antlr4/SqlServerParser.g4 ================================================ /* T-SQL (Transact-SQL, MSSQL) grammar. The MIT License (MIT). Copyright (c) 2017, Mark Adams (madams51703@gmail.com) Copyright (c) 2015-2017, Ivan Kochurkin (kvanttt@gmail.com), Positive Technologies. Copyright (c) 2016, Scott Ure (scott@redstormsoftware.com). Copyright (c) 2016, Rui Zhang (ruizhang.ccs@gmail.com). Copyright (c) 2016, Marcus Henriksson (kuseman80@gmail.com). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ parser grammar SqlServerParser; options { tokenVocab=SqlServerLexer; } tsql_file : batch* EOF | execute_body_batch go_statement* EOF ; batch : go_statement | execute_body_batch? (go_statement | sql_clauses+) go_statement* | batch_level_statement go_statement* ; batch_level_statement : create_or_alter_function | create_or_alter_procedure | create_or_alter_trigger | create_view ; sql_clauses : dml_clause SEMI? | cfl_statement SEMI? | another_statement SEMI? | ddl_clause SEMI? | dbcc_clause SEMI? | backup_statement SEMI? | SEMI ; // Data Manipulation Language: https://msdn.microsoft.com/en-us/library/ff848766(v=sql.120).aspx dml_clause : merge_statement | delete_statement | insert_statement | select_statement_standalone | update_statement ; // Data Definition Language: https://msdn.microsoft.com/en-us/library/ff848799.aspx) ddl_clause : alter_application_role | alter_assembly | alter_asymmetric_key | alter_authorization | alter_authorization_for_azure_dw | alter_authorization_for_parallel_dw | alter_authorization_for_sql_database | alter_availability_group | alter_certificate | alter_column_encryption_key | alter_credential | alter_cryptographic_provider | alter_database | alter_database_audit_specification | alter_db_role | alter_endpoint | alter_external_data_source | alter_external_library | alter_external_resource_pool | alter_fulltext_catalog | alter_fulltext_stoplist | alter_index | alter_login_azure_sql | alter_login_azure_sql_dw_and_pdw | alter_login_sql_server | alter_master_key_azure_sql | alter_master_key_sql_server | alter_message_type | alter_partition_function | alter_partition_scheme | alter_remote_service_binding | alter_resource_governor | alter_schema_azure_sql_dw_and_pdw | alter_schema_sql | alter_sequence | alter_server_audit | alter_server_audit_specification | alter_server_configuration | alter_server_role | alter_server_role_pdw | alter_service | alter_service_master_key | alter_symmetric_key | alter_table | alter_user | alter_user_azure_sql | alter_workload_group | alter_xml_schema_collection | create_application_role | create_assembly | create_asymmetric_key | create_column_encryption_key | create_column_master_key | create_columnstore_index | create_credential | create_cryptographic_provider | create_database | create_database_audit_specification | create_db_role | create_endpoint | create_event_notification | create_external_library | create_external_resource_pool | create_fulltext_catalog | create_fulltext_stoplist | create_index | create_login_azure_sql | create_login_pdw | create_login_sql_server | create_master_key_azure_sql | create_master_key_sql_server | create_nonclustered_columnstore_index | create_or_alter_broker_priority | create_or_alter_event_session | create_partition_function | create_partition_scheme | create_remote_service_binding | create_resource_pool | create_route | create_rule | create_schema | create_schema_azure_sql_dw_and_pdw | create_search_property_list | create_security_policy | create_sequence | create_server_audit | create_server_audit_specification | create_server_role | create_service | create_statistics | create_synonym | create_table | create_type | create_user | create_user_azure_sql_dw | create_workload_group | create_xml_index | create_xml_schema_collection | disable_trigger | drop_aggregate | drop_application_role | drop_assembly | drop_asymmetric_key | drop_availability_group | drop_broker_priority | drop_certificate | drop_column_encryption_key | drop_column_master_key | drop_contract | drop_credential | drop_cryptograhic_provider | drop_database | drop_database_audit_specification | drop_database_encryption_key | drop_database_scoped_credential | drop_db_role | drop_default | drop_endpoint | drop_event_notifications | drop_event_session | drop_external_data_source | drop_external_file_format | drop_external_library | drop_external_resource_pool | drop_external_table | drop_fulltext_catalog | drop_fulltext_index | drop_fulltext_stoplist | drop_function | drop_index | drop_login | drop_master_key | drop_message_type | drop_partition_function | drop_partition_scheme | drop_procedure | drop_queue | drop_remote_service_binding | drop_resource_pool | drop_route | drop_rule | drop_schema | drop_search_property_list | drop_security_policy | drop_sequence | drop_server_audit | drop_server_audit_specification | drop_server_role | drop_service | drop_signature | drop_statistics | drop_statistics_name_azure_dw_and_pdw | drop_symmetric_key | drop_synonym | drop_table | drop_trigger | drop_type | drop_user | drop_view | drop_workload_group | drop_xml_schema_collection | enable_trigger | lock_table | truncate_table | update_statistics ; backup_statement : backup_database | backup_log | backup_certificate | backup_master_key | backup_service_master_key ; // Control-of-Flow Language: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/control-of-flow cfl_statement : block_statement | break_statement | continue_statement | goto_statement | if_statement | print_statement | raiseerror_statement | return_statement | throw_statement | try_catch_statement | waitfor_statement | while_statement ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/begin-end-transact-sql block_statement : BEGIN ';'? sql_clauses* END ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/break-transact-sql break_statement : BREAK ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/continue-transact-sql continue_statement : CONTINUE ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/goto-transact-sql goto_statement : GOTO id_ ';'? | id_ ':' ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/return-transact-sql return_statement : RETURN expression? ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/if-else-transact-sql if_statement : IF search_condition sql_clauses (ELSE sql_clauses)? ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql throw_statement : THROW (throw_error_number ',' throw_message ',' throw_state)? ';'? ; throw_error_number : DECIMAL | LOCAL_ID ; throw_message : STRING | LOCAL_ID ; throw_state : DECIMAL | LOCAL_ID ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/try-catch-transact-sql try_catch_statement : BEGIN TRY ';'? try_clauses=sql_clauses+ END TRY ';'? BEGIN CATCH ';'? catch_clauses=sql_clauses* END CATCH ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql waitfor_statement : WAITFOR receive_statement? ','? ((DELAY | TIME | TIMEOUT) time)? expression? ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/while-transact-sql while_statement : WHILE search_condition (sql_clauses | BREAK ';'? | CONTINUE ';'?) ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/print-transact-sql print_statement : PRINT (expression | DOUBLE_QUOTE_ID) (',' LOCAL_ID)* ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql raiseerror_statement : RAISERROR '(' msg=(DECIMAL | STRING | LOCAL_ID) ',' severity=constant_LOCAL_ID ',' state=constant_LOCAL_ID (',' (constant_LOCAL_ID | NULL_))* ')' (WITH (LOG | SETERROR | NOWAIT))? ';'? | RAISERROR DECIMAL formatstring=(STRING | LOCAL_ID | DOUBLE_QUOTE_ID) (',' argument=(DECIMAL | STRING | LOCAL_ID))* ; empty_statement : ';' ; another_statement : alter_queue | checkpoint_statement | conversation_statement | create_contract | create_queue | cursor_statement | declare_statement | execute_statement | kill_statement | message_statement | reconfigure_statement | security_statement | set_statement | setuser_statement | shutdown_statement | transaction_statement | use_statement ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-application-role-transact-sql alter_application_role : ALTER APPLICATION ROLE appliction_role=id_ WITH (COMMA? NAME EQUAL new_application_role_name=id_)? (COMMA? PASSWORD EQUAL application_role_password=STRING)? (COMMA? DEFAULT_SCHEMA EQUAL app_role_default_schema=id_)? ; // https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-xml-schema-collection-transact-sql?view=sql-server-ver16 alter_xml_schema_collection : ALTER XML SCHEMA COLLECTION (id_ '.')? id_ ADD STRING ; create_application_role : CREATE APPLICATION ROLE appliction_role=id_ WITH (COMMA? PASSWORD EQUAL application_role_password=STRING)? (COMMA? DEFAULT_SCHEMA EQUAL app_role_default_schema=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-aggregate-transact-sql drop_aggregate : DROP AGGREGATE ( IF EXISTS )? ( schema_name=id_ DOT )? aggregate_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-application-role-transact-sql drop_application_role : DROP APPLICATION ROLE rolename=id_ ; alter_assembly : alter_assembly_start assembly_name=id_ alter_assembly_clause ; alter_assembly_start : ALTER ASSEMBLY ; alter_assembly_clause : alter_assembly_from_clause? alter_assembly_with_clause? alter_assembly_drop_clause? alter_assembly_add_clause? ; alter_assembly_from_clause : alter_assembly_from_clause_start (client_assembly_specifier | alter_assembly_file_bits ) ; alter_assembly_from_clause_start : FROM ; alter_assembly_drop_clause : alter_assembly_drop alter_assembly_drop_multiple_files ; alter_assembly_drop_multiple_files : ALL | multiple_local_files ; alter_assembly_drop : DROP ; alter_assembly_add_clause : alter_asssembly_add_clause_start alter_assembly_client_file_clause ; alter_asssembly_add_clause_start : ADD FILE FROM ; // need to implement alter_assembly_client_file_clause : alter_assembly_file_name (alter_assembly_as id_)? ; alter_assembly_file_name : STRING ; //need to implement alter_assembly_file_bits : alter_assembly_as id_ ; alter_assembly_as : AS ; alter_assembly_with_clause : alter_assembly_with assembly_option ; alter_assembly_with : WITH ; client_assembly_specifier : network_file_share | local_file | STRING ; assembly_option : PERMISSION_SET EQUAL (SAFE|EXTERNAL_ACCESS|UNSAFE) | VISIBILITY EQUAL on_off | UNCHECKED DATA | assembly_option COMMA ; network_file_share : network_file_start network_computer file_path ; network_computer : computer_name=id_ ; network_file_start : DOUBLE_BACK_SLASH ; file_path : file_directory_path_separator file_path | id_ ; file_directory_path_separator : '\\' ; local_file : local_drive file_path ; local_drive : DISK_DRIVE ; multiple_local_files : multiple_local_file_start local_file SINGLE_QUOTE COMMA | local_file ; multiple_local_file_start : SINGLE_QUOTE ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-assembly-transact-sql create_assembly : CREATE ASSEMBLY assembly_name=id_ (AUTHORIZATION owner_name=id_)? FROM (COMMA? (STRING|BINARY) )+ (WITH PERMISSION_SET EQUAL (SAFE|EXTERNAL_ACCESS|UNSAFE) )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-assembly-transact-sql drop_assembly : DROP ASSEMBLY ( IF EXISTS )? (COMMA? assembly_name=id_)+ ( WITH NO DEPENDENTS )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-asymmetric-key-transact-sql alter_asymmetric_key : alter_asymmetric_key_start Asym_Key_Name=id_ (asymmetric_key_option | REMOVE PRIVATE KEY ) ; alter_asymmetric_key_start : ALTER ASYMMETRIC KEY ; asymmetric_key_option : asymmetric_key_option_start asymmetric_key_password_change_option ( COMMA asymmetric_key_password_change_option)? RR_BRACKET ; asymmetric_key_option_start : WITH PRIVATE KEY LR_BRACKET ; asymmetric_key_password_change_option : DECRYPTION BY PASSWORD EQUAL STRING | ENCRYPTION BY PASSWORD EQUAL STRING ; //https://docs.microsoft.com/en-us/sql/t-sql/statements/create-asymmetric-key-transact-sql create_asymmetric_key : CREATE ASYMMETRIC KEY Asym_Key_Nam=id_ (AUTHORIZATION database_principal_name=id_)? ( FROM (FILE EQUAL STRING |EXECUTABLE_FILE EQUAL STRING|ASSEMBLY Assembly_Name=id_ | PROVIDER Provider_Name=id_) )? (WITH (ALGORITHM EQUAL ( RSA_4096 | RSA_3072 | RSA_2048 | RSA_1024 | RSA_512) |PROVIDER_KEY_NAME EQUAL provider_key_name=STRING | CREATION_DISPOSITION EQUAL (CREATE_NEW|OPEN_EXISTING) ) )? (ENCRYPTION BY PASSWORD EQUAL asymmetric_key_password=STRING )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-asymmetric-key-transact-sql drop_asymmetric_key : DROP ASYMMETRIC KEY key_name=id_ ( REMOVE PROVIDER KEY )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-authorization-transact-sql alter_authorization : alter_authorization_start (class_type colon_colon)? entity=entity_name entity_to authorization_grantee ; authorization_grantee : principal_name=id_ | SCHEMA OWNER ; entity_to : TO ; colon_colon : DOUBLE_COLON ; alter_authorization_start : ALTER AUTHORIZATION ON ; alter_authorization_for_sql_database : alter_authorization_start (class_type_for_sql_database colon_colon)? entity=entity_name entity_to authorization_grantee ; alter_authorization_for_azure_dw : alter_authorization_start (class_type_for_azure_dw colon_colon)? entity=entity_name_for_azure_dw entity_to authorization_grantee ; alter_authorization_for_parallel_dw : alter_authorization_start (class_type_for_parallel_dw colon_colon)? entity=entity_name_for_parallel_dw entity_to authorization_grantee ; class_type : OBJECT | ASSEMBLY | ASYMMETRIC KEY | AVAILABILITY GROUP | CERTIFICATE | CONTRACT | TYPE | DATABASE | ENDPOINT | FULLTEXT CATALOG | FULLTEXT STOPLIST | MESSAGE TYPE | REMOTE SERVICE BINDING | ROLE | ROUTE | SCHEMA | SEARCH PROPERTY LIST | SERVER ROLE | SERVICE | SYMMETRIC KEY | XML SCHEMA COLLECTION ; class_type_for_sql_database : OBJECT | ASSEMBLY | ASYMMETRIC KEY | CERTIFICATE | TYPE | DATABASE | FULLTEXT CATALOG | FULLTEXT STOPLIST | ROLE | SCHEMA | SEARCH PROPERTY LIST | SYMMETRIC KEY | XML SCHEMA COLLECTION ; class_type_for_azure_dw : SCHEMA | OBJECT ; class_type_for_parallel_dw : DATABASE | SCHEMA | OBJECT ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/grant-transact-sql?view=sql-server-ver15 // SELECT DISTINCT '| ' + CLASS_DESC // FROM sys.dm_audit_actions // ORDER BY 1 class_type_for_grant : APPLICATION ROLE | ASSEMBLY | ASYMMETRIC KEY | AUDIT | AVAILABILITY GROUP | BROKER PRIORITY | CERTIFICATE | COLUMN ( ENCRYPTION | MASTER ) KEY | CONTRACT | CREDENTIAL | CRYPTOGRAPHIC PROVIDER | DATABASE ( AUDIT SPECIFICATION | ENCRYPTION KEY | EVENT SESSION | SCOPED ( CONFIGURATION | CREDENTIAL | RESOURCE GOVERNOR ) )? | ENDPOINT | EVENT SESSION | NOTIFICATION (DATABASE | OBJECT | SERVER) | EXTERNAL ( DATA SOURCE | FILE FORMAT | LIBRARY | RESOURCE POOL | TABLE | CATALOG | STOPLIST ) | LOGIN | MASTER KEY | MESSAGE TYPE | OBJECT | PARTITION ( FUNCTION | SCHEME) | REMOTE SERVICE BINDING | RESOURCE GOVERNOR | ROLE | ROUTE | SCHEMA | SEARCH PROPERTY LIST | SERVER ( ( AUDIT SPECIFICATION? ) | ROLE )? | SERVICE | SQL LOGIN | SYMMETRIC KEY | TRIGGER ( DATABASE | SERVER) | TYPE | USER | XML SCHEMA COLLECTION ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-availability-group-transact-sql drop_availability_group : DROP AVAILABILITY GROUP group_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-availability-group-transact-sql alter_availability_group : alter_availability_group_start alter_availability_group_options ; alter_availability_group_start : ALTER AVAILABILITY GROUP group_name=id_ ; alter_availability_group_options : SET LR_BRACKET ( ( AUTOMATED_BACKUP_PREFERENCE EQUAL ( PRIMARY | SECONDARY_ONLY| SECONDARY | NONE ) | FAILURE_CONDITION_LEVEL EQUAL DECIMAL | HEALTH_CHECK_TIMEOUT EQUAL milliseconds=DECIMAL | DB_FAILOVER EQUAL ( ON | OFF ) | REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT EQUAL DECIMAL ) RR_BRACKET ) | ADD DATABASE database_name=id_ | REMOVE DATABASE database_name=id_ | ADD REPLICA ON server_instance=STRING (WITH LR_BRACKET ( (ENDPOINT_URL EQUAL STRING)? (COMMA? AVAILABILITY_MODE EQUAL (SYNCHRONOUS_COMMIT| ASYNCHRONOUS_COMMIT))? (COMMA? FAILOVER_MODE EQUAL (AUTOMATIC|MANUAL) )? (COMMA? SEEDING_MODE EQUAL (AUTOMATIC|MANUAL) )? (COMMA? BACKUP_PRIORITY EQUAL DECIMAL)? ( COMMA? PRIMARY_ROLE LR_BRACKET ALLOW_CONNECTIONS EQUAL ( READ_WRITE | ALL ) RR_BRACKET)? ( COMMA? SECONDARY_ROLE LR_BRACKET ALLOW_CONNECTIONS EQUAL ( READ_ONLY ) RR_BRACKET )? ) ) RR_BRACKET |SECONDARY_ROLE LR_BRACKET (ALLOW_CONNECTIONS EQUAL (NO|READ_ONLY|ALL) | READ_ONLY_ROUTING_LIST EQUAL ( LR_BRACKET ( ( STRING) ) RR_BRACKET ) ) |PRIMARY_ROLE LR_BRACKET (ALLOW_CONNECTIONS EQUAL (NO|READ_ONLY|ALL) | READ_ONLY_ROUTING_LIST EQUAL ( LR_BRACKET ( (COMMA? STRING)*|NONE ) RR_BRACKET ) | SESSION_TIMEOUT EQUAL session_timeout=DECIMAL ) | MODIFY REPLICA ON server_instance=STRING (WITH LR_BRACKET (ENDPOINT_URL EQUAL STRING| AVAILABILITY_MODE EQUAL (SYNCHRONOUS_COMMIT| ASYNCHRONOUS_COMMIT) | FAILOVER_MODE EQUAL (AUTOMATIC|MANUAL) | SEEDING_MODE EQUAL (AUTOMATIC|MANUAL) | BACKUP_PRIORITY EQUAL DECIMAL ) |SECONDARY_ROLE LR_BRACKET (ALLOW_CONNECTIONS EQUAL (NO|READ_ONLY|ALL) | READ_ONLY_ROUTING_LIST EQUAL ( LR_BRACKET ( ( STRING) ) RR_BRACKET ) ) |PRIMARY_ROLE LR_BRACKET (ALLOW_CONNECTIONS EQUAL (NO|READ_ONLY|ALL) | READ_ONLY_ROUTING_LIST EQUAL ( LR_BRACKET ( (COMMA? STRING)*|NONE ) RR_BRACKET ) | SESSION_TIMEOUT EQUAL session_timeout=DECIMAL ) ) RR_BRACKET | REMOVE REPLICA ON STRING | JOIN | JOIN AVAILABILITY GROUP ON (COMMA? ag_name=STRING WITH LR_BRACKET ( LISTENER_URL EQUAL STRING COMMA AVAILABILITY_MODE EQUAL (SYNCHRONOUS_COMMIT|ASYNCHRONOUS_COMMIT) COMMA FAILOVER_MODE EQUAL MANUAL COMMA SEEDING_MODE EQUAL (AUTOMATIC|MANUAL) RR_BRACKET ) )+ | MODIFY AVAILABILITY GROUP ON (COMMA? ag_name_modified=STRING WITH LR_BRACKET (LISTENER_URL EQUAL STRING (COMMA? AVAILABILITY_MODE EQUAL (SYNCHRONOUS_COMMIT|ASYNCHRONOUS_COMMIT) )? (COMMA? FAILOVER_MODE EQUAL MANUAL )? (COMMA? SEEDING_MODE EQUAL (AUTOMATIC|MANUAL))? RR_BRACKET ) )+ |GRANT CREATE ANY DATABASE | DENY CREATE ANY DATABASE | FAILOVER | FORCE_FAILOVER_ALLOW_DATA_LOSS | ADD LISTENER listener_name=STRING LR_BRACKET ( WITH DHCP (ON LR_BRACKET ip_v4_failover ip_v4_failover RR_BRACKET ) | WITH IP LR_BRACKET ( (COMMA? LR_BRACKET ( ip_v4_failover COMMA ip_v4_failover | ip_v6_failover ) RR_BRACKET)+ RR_BRACKET (COMMA PORT EQUAL DECIMAL)? ) ) RR_BRACKET | MODIFY LISTENER (ADD IP LR_BRACKET (ip_v4_failover ip_v4_failover | ip_v6_failover) RR_BRACKET | PORT EQUAL DECIMAL ) |RESTART LISTENER STRING |REMOVE LISTENER STRING |OFFLINE | WITH LR_BRACKET DTC_SUPPORT EQUAL PER_DB RR_BRACKET ; ip_v4_failover : STRING ; ip_v6_failover : STRING ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-broker-priority-transact-sql // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-broker-priority-transact-sql create_or_alter_broker_priority : (CREATE | ALTER) BROKER PRIORITY ConversationPriorityName=id_ FOR CONVERSATION SET LR_BRACKET ( CONTRACT_NAME EQUAL ( ( id_) | ANY ) COMMA? )? ( LOCAL_SERVICE_NAME EQUAL (DOUBLE_FORWARD_SLASH? id_ | ANY ) COMMA? )? ( REMOTE_SERVICE_NAME EQUAL (RemoteServiceName=STRING | ANY ) COMMA? )? ( PRIORITY_LEVEL EQUAL ( PriorityValue=DECIMAL | DEFAULT ) ) ? RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-broker-priority-transact-sql drop_broker_priority : DROP BROKER PRIORITY ConversationPriorityName=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-certificate-transact-sql alter_certificate : ALTER CERTIFICATE certificate_name=id_ (REMOVE PRIVATE_KEY | WITH PRIVATE KEY LR_BRACKET ( FILE EQUAL STRING COMMA? | DECRYPTION BY PASSWORD EQUAL STRING COMMA?| ENCRYPTION BY PASSWORD EQUAL STRING COMMA?)+ RR_BRACKET | WITH ACTIVE FOR BEGIN_DIALOG EQUAL ( ON | OFF ) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-column-encryption-key-transact-sql alter_column_encryption_key : ALTER COLUMN ENCRYPTION KEY column_encryption_key=id_ (ADD | DROP) VALUE LR_BRACKET COLUMN_MASTER_KEY EQUAL column_master_key_name=id_ ( COMMA ALGORITHM EQUAL algorithm_name=STRING COMMA ENCRYPTED_VALUE EQUAL BINARY)? RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-column-encryption-key-transact-sql create_column_encryption_key : CREATE COLUMN ENCRYPTION KEY column_encryption_key=id_ WITH VALUES (LR_BRACKET COMMA? COLUMN_MASTER_KEY EQUAL column_master_key_name=id_ COMMA ALGORITHM EQUAL algorithm_name=STRING COMMA ENCRYPTED_VALUE EQUAL encrypted_value=BINARY RR_BRACKET COMMA?)+ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-certificate-transact-sql drop_certificate : DROP CERTIFICATE certificate_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-column-encryption-key-transact-sql drop_column_encryption_key : DROP COLUMN ENCRYPTION KEY key_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-column-master-key-transact-sql drop_column_master_key : DROP COLUMN MASTER KEY key_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-contract-transact-sql drop_contract : DROP CONTRACT dropped_contract_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-credential-transact-sql drop_credential : DROP CREDENTIAL credential_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-cryptographic-provider-transact-sql drop_cryptograhic_provider : DROP CRYPTOGRAPHIC PROVIDER provider_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-transact-sql drop_database : DROP DATABASE ( IF EXISTS )? (COMMA? database_name_or_database_snapshot_name=id_)+ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-audit-specification-transact-sql drop_database_audit_specification : DROP DATABASE AUDIT SPECIFICATION audit_specification_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-encryption-key-transact-sql?view=sql-server-ver15 drop_database_encryption_key : DROP DATABASE ENCRYPTION KEY ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-database-scoped-credential-transact-sql drop_database_scoped_credential : DROP DATABASE SCOPED CREDENTIAL credential_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-default-transact-sql drop_default : DROP DEFAULT ( IF EXISTS )? (COMMA? (schema_name=id_ DOT)? default_name=id_) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-endpoint-transact-sql drop_endpoint : DROP ENDPOINT endPointName=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-external-data-source-transact-sql drop_external_data_source : DROP EXTERNAL DATA SOURCE external_data_source_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-external-file-format-transact-sql drop_external_file_format : DROP EXTERNAL FILE FORMAT external_file_format_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-external-library-transact-sql drop_external_library : DROP EXTERNAL LIBRARY library_name=id_ ( AUTHORIZATION owner_name=id_ )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-external-resource-pool-transact-sql drop_external_resource_pool : DROP EXTERNAL RESOURCE POOL pool_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-external-table-transact-sql drop_external_table : DROP EXTERNAL TABLE (database_name=id_ DOT)? (schema_name=id_ DOT)? table=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-event-notification-transact-sql drop_event_notifications : DROP EVENT NOTIFICATION (COMMA? notification_name=id_)+ ON (SERVER|DATABASE|QUEUE queue_name=id_) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-event-session-transact-sql drop_event_session : DROP EVENT SESSION event_session_name=id_ ON SERVER ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-fulltext-catalog-transact-sql drop_fulltext_catalog : DROP FULLTEXT CATALOG catalog_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-fulltext-index-transact-sql drop_fulltext_index : DROP FULLTEXT INDEX ON (schema=id_ DOT)? table=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-fulltext-stoplist-transact-sql drop_fulltext_stoplist : DROP FULLTEXT STOPLIST stoplist_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-login-transact-sql drop_login : DROP LOGIN login_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-master-key-transact-sql drop_master_key : DROP MASTER KEY ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-message-type-transact-sql drop_message_type : DROP MESSAGE TYPE message_type_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-partition-function-transact-sql drop_partition_function : DROP PARTITION FUNCTION partition_function_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-partition-scheme-transact-sql drop_partition_scheme : DROP PARTITION SCHEME partition_scheme_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-queue-transact-sql drop_queue : DROP QUEUE (database_name=id_ DOT)? (schema_name=id_ DOT)? queue_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-remote-service-binding-transact-sql drop_remote_service_binding : DROP REMOTE SERVICE BINDING binding_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-resource-pool-transact-sql drop_resource_pool : DROP RESOURCE POOL pool_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-role-transact-sql drop_db_role : DROP ROLE ( IF EXISTS )? role_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-route-transact-sql drop_route : DROP ROUTE route_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-rule-transact-sql drop_rule : DROP RULE ( IF EXISTS )? (COMMA? (schema_name=id_ DOT)? rule_name=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-schema-transact-sql drop_schema : DROP SCHEMA ( IF EXISTS )? schema_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-search-property-list-transact-sql drop_search_property_list : DROP SEARCH PROPERTY LIST property_list_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-security-policy-transact-sql drop_security_policy : DROP SECURITY POLICY ( IF EXISTS )? (schema_name=id_ DOT )? security_policy_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-sequence-transact-sql drop_sequence : DROP SEQUENCE ( IF EXISTS )? ( COMMA? (database_name=id_ DOT)? (schema_name=id_ DOT)? sequence_name=id_ )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-server-audit-transact-sql drop_server_audit : DROP SERVER AUDIT audit_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-server-audit-specification-transact-sql drop_server_audit_specification : DROP SERVER AUDIT SPECIFICATION audit_specification_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-server-role-transact-sql drop_server_role : DROP SERVER ROLE role_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-service-transact-sql drop_service : DROP SERVICE dropped_service_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-signature-transact-sql drop_signature : DROP ( COUNTER )? SIGNATURE FROM (schema_name=id_ DOT)? module_name=id_ BY (COMMA? CERTIFICATE cert_name=id_ | COMMA? ASYMMETRIC KEY Asym_key_name=id_ )+ ; drop_statistics_name_azure_dw_and_pdw : DROP STATISTICS (schema_name=id_ DOT)? object_name=id_ DOT statistics_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-symmetric-key-transact-sql drop_symmetric_key : DROP SYMMETRIC KEY symmetric_key_name=id_ (REMOVE PROVIDER KEY)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-synonym-transact-sql drop_synonym : DROP SYNONYM ( IF EXISTS )? ( schema=id_ DOT )? synonym_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-user-transact-sql drop_user : DROP USER ( IF EXISTS )? user_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-workload-group-transact-sql drop_workload_group : DROP WORKLOAD GROUP group_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-xml-schema-collection-transact-sql drop_xml_schema_collection : DROP XML SCHEMA COLLECTION ( relational_schema=id_ DOT )? sql_identifier=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/disable-trigger-transact-sql disable_trigger : DISABLE TRIGGER ( ( COMMA? (schema_name=id_ DOT)? trigger_name=id_ )+ | ALL) ON ((schema_id=id_ DOT)? object_name=id_|DATABASE|ALL SERVER) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/enable-trigger-transact-sql enable_trigger : ENABLE TRIGGER ( ( COMMA? (schema_name=id_ DOT)? trigger_name=id_ )+ | ALL) ON ( (schema_id=id_ DOT)? object_name=id_|DATABASE|ALL SERVER) ; lock_table : LOCK TABLE table_name IN (SHARE | EXCLUSIVE) MODE (WAIT seconds=DECIMAL | NOWAIT)? ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql truncate_table : TRUNCATE TABLE table_name ( WITH LR_BRACKET PARTITIONS LR_BRACKET (COMMA? (DECIMAL|DECIMAL TO DECIMAL) )+ RR_BRACKET RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-column-master-key-transact-sql create_column_master_key : CREATE COLUMN MASTER KEY key_name=id_ WITH LR_BRACKET KEY_STORE_PROVIDER_NAME EQUAL key_store_provider_name=STRING COMMA KEY_PATH EQUAL key_path=STRING RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-credential-transact-sql alter_credential : ALTER CREDENTIAL credential_name=id_ WITH IDENTITY EQUAL identity_name=STRING ( COMMA SECRET EQUAL secret=STRING )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-credential-transact-sql create_credential : CREATE CREDENTIAL credential_name=id_ WITH IDENTITY EQUAL identity_name=STRING ( COMMA SECRET EQUAL secret=STRING )? ( FOR CRYPTOGRAPHIC PROVIDER cryptographic_provider_name=id_ )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-cryptographic-provider-transact-sql alter_cryptographic_provider : ALTER CRYPTOGRAPHIC PROVIDER provider_name=id_ (FROM FILE EQUAL crypto_provider_ddl_file=STRING)? (ENABLE | DISABLE)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-cryptographic-provider-transact-sql create_cryptographic_provider : CREATE CRYPTOGRAPHIC PROVIDER provider_name=id_ FROM FILE EQUAL path_of_DLL=STRING ; // https://learn.microsoft.com/en-us/sql/t-sql/statements/create-endpoint-transact-sql?view=sql-server-ver16 create_endpoint : CREATE ENDPOINT endpointname=id_ (AUTHORIZATION login=id_)? (STATE EQUAL state=(STARTED | STOPPED | DISABLED))? AS TCP LR_BRACKET endpoint_listener_clause RR_BRACKET ( FOR TSQL LR_BRACKET RR_BRACKET | FOR SERVICE_BROKER LR_BRACKET endpoint_authentication_clause (COMMA? endpoint_encryption_alogorithm_clause)? (COMMA? MESSAGE_FORWARDING EQUAL (ENABLED | DISABLED))? (COMMA? MESSAGE_FORWARD_SIZE EQUAL DECIMAL)? RR_BRACKET | FOR DATABASE_MIRRORING LR_BRACKET endpoint_authentication_clause (COMMA? endpoint_encryption_alogorithm_clause)? COMMA? ROLE EQUAL (WITNESS | PARTNER | ALL) RR_BRACKET ) ; endpoint_encryption_alogorithm_clause : ENCRYPTION EQUAL (DISABLED | SUPPORTED | REQUIRED) (ALGORITHM (AES RC4? | RC4 AES?))? ; endpoint_authentication_clause : AUTHENTICATION EQUAL ( WINDOWS (NTLM | KERBEROS | NEGOTIATE)? (CERTIFICATE cert_name=id_)? | CERTIFICATE cert_name=id_ WINDOWS? (NTLM | KERBEROS | NEGOTIATE)? ) ; endpoint_listener_clause : LISTENER_PORT EQUAL port=DECIMAL (COMMA LISTENER_IP EQUAL (ALL | '(' (ipv4=IPV4_ADDR | ipv6=STRING) ')'))? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-event-notification-transact-sql create_event_notification : CREATE EVENT NOTIFICATION event_notification_name=id_ ON (SERVER|DATABASE|QUEUE queue_name=id_) (WITH FAN_IN)? FOR (COMMA? event_type_or_group=id_)+ TO SERVICE broker_service=STRING COMMA broker_service_specifier_or_current_database=STRING ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-event-session-transact-sql // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-event-session-transact-sql // todo: not implemented create_or_alter_event_session : (CREATE | ALTER) EVENT SESSION event_session_name=id_ ON SERVER (COMMA? ADD EVENT ( (event_module_guid=id_ DOT)? event_package_name=id_ DOT event_name=id_) (LR_BRACKET (SET ( COMMA? event_customizable_attributue=id_ EQUAL (DECIMAL|STRING) )* )? ( ACTION LR_BRACKET (COMMA? (event_module_guid=id_ DOT)? event_package_name=id_ DOT action_name=id_)+ RR_BRACKET)+ (WHERE event_session_predicate_expression)? RR_BRACKET )* )* (COMMA? DROP EVENT (event_module_guid=id_ DOT)? event_package_name=id_ DOT event_name=id_ )* ( (ADD TARGET (event_module_guid=id_ DOT)? event_package_name=id_ DOT target_name=id_ ) ( LR_BRACKET SET (COMMA? target_parameter_name=id_ EQUAL (LR_BRACKET? DECIMAL RR_BRACKET? |STRING) )+ RR_BRACKET )* )* (DROP TARGET (event_module_guid=id_ DOT)? event_package_name=id_ DOT target_name=id_ )* (WITH LR_BRACKET (COMMA? MAX_MEMORY EQUAL max_memory=DECIMAL (KB|MB) )? (COMMA? EVENT_RETENTION_MODE EQUAL (ALLOW_SINGLE_EVENT_LOSS | ALLOW_MULTIPLE_EVENT_LOSS | NO_EVENT_LOSS ) )? (COMMA? MAX_DISPATCH_LATENCY EQUAL (max_dispatch_latency_seconds=DECIMAL SECONDS | INFINITE) )? (COMMA? MAX_EVENT_SIZE EQUAL max_event_size=DECIMAL (KB|MB) )? (COMMA? MEMORY_PARTITION_MODE EQUAL (NONE | PER_NODE | PER_CPU) )? (COMMA? TRACK_CAUSALITY EQUAL (ON|OFF) )? (COMMA? STARTUP_STATE EQUAL (ON|OFF) )? RR_BRACKET )? (STATE EQUAL (START|STOP) )? ; event_session_predicate_expression : ( COMMA? (AND|OR)? NOT? ( event_session_predicate_factor | LR_BRACKET event_session_predicate_expression RR_BRACKET) )+ ; event_session_predicate_factor : event_session_predicate_leaf | LR_BRACKET event_session_predicate_expression RR_BRACKET ; event_session_predicate_leaf : (event_field_name=id_ | (event_field_name=id_ |( (event_module_guid=id_ DOT)? event_package_name=id_ DOT predicate_source_name=id_ ) ) (EQUAL |(LESS GREATER) | (EXCLAMATION EQUAL) | GREATER | (GREATER EQUAL)| LESS | LESS EQUAL) (DECIMAL | STRING) ) | (event_module_guid=id_ DOT)? event_package_name=id_ DOT predicate_compare_name=id_ LR_BRACKET (event_field_name=id_ |( (event_module_guid=id_ DOT)? event_package_name=id_ DOT predicate_source_name=id_ ) COMMA (DECIMAL | STRING) ) RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-external-data-source-transact-sql alter_external_data_source : ALTER EXTERNAL DATA SOURCE data_source_name=id_ SET ( LOCATION EQUAL location=STRING COMMA? | RESOURCE_MANAGER_LOCATION EQUAL resource_manager_location=STRING COMMA? | CREDENTIAL EQUAL credential_name=id_ )+ | ALTER EXTERNAL DATA SOURCE data_source_name=id_ WITH LR_BRACKET TYPE EQUAL BLOB_STORAGE COMMA LOCATION EQUAL location=STRING (COMMA CREDENTIAL EQUAL credential_name=id_ )? RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-external-library-transact-sql alter_external_library : ALTER EXTERNAL LIBRARY library_name=id_ (AUTHORIZATION owner_name=id_)? (SET|ADD) ( LR_BRACKET CONTENT EQUAL (client_library=STRING | BINARY | NONE) (COMMA PLATFORM EQUAL (WINDOWS|LINUX)? RR_BRACKET) WITH (COMMA? LANGUAGE EQUAL (R|PYTHON) | DATA_SOURCE EQUAL external_data_source_name=id_ )+ RR_BRACKET ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-external-library-transact-sql create_external_library : CREATE EXTERNAL LIBRARY library_name=id_ (AUTHORIZATION owner_name=id_)? FROM (COMMA? LR_BRACKET? (CONTENT EQUAL)? (client_library=STRING | BINARY | NONE) (COMMA PLATFORM EQUAL (WINDOWS|LINUX)? RR_BRACKET)? ) ( WITH (COMMA? LANGUAGE EQUAL (R|PYTHON) | DATA_SOURCE EQUAL external_data_source_name=id_ )+ RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-external-resource-pool-transact-sql alter_external_resource_pool : ALTER EXTERNAL RESOURCE POOL (pool_name=id_ | DEFAULT_DOUBLE_QUOTE) WITH LR_BRACKET MAX_CPU_PERCENT EQUAL max_cpu_percent=DECIMAL ( COMMA? AFFINITY CPU EQUAL (AUTO|(COMMA? DECIMAL TO DECIMAL |COMMA DECIMAL )+ ) | NUMANODE EQUAL (COMMA? DECIMAL TO DECIMAL| COMMA? DECIMAL )+ ) (COMMA? MAX_MEMORY_PERCENT EQUAL max_memory_percent=DECIMAL)? (COMMA? MAX_PROCESSES EQUAL max_processes=DECIMAL)? RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-external-resource-pool-transact-sql create_external_resource_pool : CREATE EXTERNAL RESOURCE POOL pool_name=id_ WITH LR_BRACKET MAX_CPU_PERCENT EQUAL max_cpu_percent=DECIMAL ( COMMA? AFFINITY CPU EQUAL (AUTO|(COMMA? DECIMAL TO DECIMAL |COMMA DECIMAL )+ ) | NUMANODE EQUAL (COMMA? DECIMAL TO DECIMAL| COMMA? DECIMAL )+ ) (COMMA? MAX_MEMORY_PERCENT EQUAL max_memory_percent=DECIMAL)? (COMMA? MAX_PROCESSES EQUAL max_processes=DECIMAL)? RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-fulltext-catalog-transact-sql alter_fulltext_catalog : ALTER FULLTEXT CATALOG catalog_name=id_ (REBUILD (WITH ACCENT_SENSITIVITY EQUAL (ON|OFF) )? | REORGANIZE | AS DEFAULT ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-fulltext-catalog-transact-sql create_fulltext_catalog : CREATE FULLTEXT CATALOG catalog_name=id_ (ON FILEGROUP filegroup=id_)? (IN PATH rootpath=STRING)? (WITH ACCENT_SENSITIVITY EQUAL (ON|OFF) )? (AS DEFAULT)? (AUTHORIZATION owner_name=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-fulltext-stoplist-transact-sql alter_fulltext_stoplist : ALTER FULLTEXT STOPLIST stoplist_name=id_ (ADD stopword=STRING LANGUAGE (STRING|DECIMAL|BINARY) | DROP ( stopword=STRING LANGUAGE (STRING|DECIMAL|BINARY) |ALL (STRING|DECIMAL|BINARY) | ALL ) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-fulltext-stoplist-transact-sql create_fulltext_stoplist : CREATE FULLTEXT STOPLIST stoplist_name=id_ (FROM ( (database_name=id_ DOT)? source_stoplist_name=id_ |SYSTEM STOPLIST ) )? (AUTHORIZATION owner_name=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-login-transact-sql alter_login_sql_server : ALTER LOGIN login_name=id_ ( (ENABLE|DISABLE)? | WITH ( (PASSWORD EQUAL ( password=STRING | password_hash=BINARY HASHED ) ) (MUST_CHANGE|UNLOCK)* )? (OLD_PASSWORD EQUAL old_password=STRING (MUST_CHANGE|UNLOCK)* )? (DEFAULT_DATABASE EQUAL default_database=id_)? (DEFAULT_LANGUAGE EQUAL default_laguage=id_)? (NAME EQUAL login_name=id_)? (CHECK_POLICY EQUAL (ON|OFF) )? (CHECK_EXPIRATION EQUAL (ON|OFF) )? (CREDENTIAL EQUAL credential_name=id_)? (NO CREDENTIAL)? | (ADD|DROP) CREDENTIAL credential_name=id_ ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-login-transact-sql create_login_sql_server : CREATE LOGIN login_name=id_ ( WITH ( (PASSWORD EQUAL ( password=STRING | password_hash=BINARY HASHED ) ) (MUST_CHANGE|UNLOCK)* )? (COMMA? SID EQUAL sid=BINARY)? (COMMA? DEFAULT_DATABASE EQUAL default_database=id_)? (COMMA? DEFAULT_LANGUAGE EQUAL default_laguage=id_)? (COMMA? CHECK_EXPIRATION EQUAL (ON|OFF) )? (COMMA? CHECK_POLICY EQUAL (ON|OFF) )? (COMMA? CREDENTIAL EQUAL credential_name=id_)? |(FROM (WINDOWS (WITH (COMMA? DEFAULT_DATABASE EQUAL default_database=id_)? (COMMA? DEFAULT_LANGUAGE EQUAL default_language=STRING)? ) | CERTIFICATE certname=id_ | ASYMMETRIC KEY asym_key_name=id_ ) ) ) ; alter_login_azure_sql : ALTER LOGIN login_name=id_ ( (ENABLE|DISABLE)? | WITH (PASSWORD EQUAL password=STRING (OLD_PASSWORD EQUAL old_password=STRING)? | NAME EQUAL login_name=id_ ) ) ; create_login_azure_sql : CREATE LOGIN login_name=id_ WITH PASSWORD EQUAL STRING (SID EQUAL sid=BINARY)? ; alter_login_azure_sql_dw_and_pdw : ALTER LOGIN login_name=id_ ( (ENABLE|DISABLE)? | WITH (PASSWORD EQUAL password=STRING (OLD_PASSWORD EQUAL old_password=STRING (MUST_CHANGE|UNLOCK)* )? | NAME EQUAL login_name=id_ ) ) ; create_login_pdw : CREATE LOGIN loginName=id_ (WITH ( PASSWORD EQUAL password=STRING (MUST_CHANGE)? (CHECK_POLICY EQUAL (ON|OFF)? )? ) | FROM WINDOWS ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-master-key-transact-sql alter_master_key_sql_server : ALTER MASTER KEY ( (FORCE)? REGENERATE WITH ENCRYPTION BY PASSWORD EQUAL password=STRING |(ADD|DROP) ENCRYPTION BY (SERVICE MASTER KEY | PASSWORD EQUAL encryption_password=STRING) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-master-key-transact-sql create_master_key_sql_server : CREATE MASTER KEY ENCRYPTION BY PASSWORD EQUAL password=STRING ; alter_master_key_azure_sql : ALTER MASTER KEY ( (FORCE)? REGENERATE WITH ENCRYPTION BY PASSWORD EQUAL password=STRING |ADD ENCRYPTION BY (SERVICE MASTER KEY | PASSWORD EQUAL encryption_password=STRING) | DROP ENCRYPTION BY PASSWORD EQUAL encryption_password=STRING ) ; create_master_key_azure_sql : CREATE MASTER KEY (ENCRYPTION BY PASSWORD EQUAL password=STRING)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-message-type-transact-sql alter_message_type : ALTER MESSAGE TYPE message_type_name=id_ VALIDATION EQUAL (NONE | EMPTY | WELL_FORMED_XML | VALID_XML WITH SCHEMA COLLECTION schema_collection_name=id_) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-partition-function-transact-sql alter_partition_function : ALTER PARTITION FUNCTION partition_function_name=id_ LR_BRACKET RR_BRACKET (SPLIT|MERGE) RANGE LR_BRACKET DECIMAL RR_BRACKET ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-partition-scheme-transact-sql alter_partition_scheme : ALTER PARTITION SCHEME partition_scheme_name=id_ NEXT USED (file_group_name=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-remote-service-binding-transact-sql alter_remote_service_binding : ALTER REMOTE SERVICE BINDING binding_name=id_ WITH (USER EQUAL user_name=id_)? (COMMA ANONYMOUS EQUAL (ON|OFF) )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-remote-service-binding-transact-sql create_remote_service_binding : CREATE REMOTE SERVICE BINDING binding_name=id_ (AUTHORIZATION owner_name=id_)? TO SERVICE remote_service_name=STRING WITH (USER EQUAL user_name=id_)? (COMMA ANONYMOUS EQUAL (ON|OFF) )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-resource-pool-transact-sql create_resource_pool : CREATE RESOURCE POOL pool_name=id_ (WITH LR_BRACKET (COMMA? MIN_CPU_PERCENT EQUAL DECIMAL)? (COMMA? MAX_CPU_PERCENT EQUAL DECIMAL)? (COMMA? CAP_CPU_PERCENT EQUAL DECIMAL)? (COMMA? AFFINITY SCHEDULER EQUAL (AUTO | LR_BRACKET (COMMA? (DECIMAL|DECIMAL TO DECIMAL) )+ RR_BRACKET | NUMANODE EQUAL LR_BRACKET (COMMA? (DECIMAL|DECIMAL TO DECIMAL) )+ RR_BRACKET ) )? (COMMA? MIN_MEMORY_PERCENT EQUAL DECIMAL)? (COMMA? MAX_MEMORY_PERCENT EQUAL DECIMAL)? (COMMA? MIN_IOPS_PER_VOLUME EQUAL DECIMAL)? (COMMA? MAX_IOPS_PER_VOLUME EQUAL DECIMAL)? RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-resource-governor-transact-sql alter_resource_governor : ALTER RESOURCE GOVERNOR ( (DISABLE | RECONFIGURE) | WITH LR_BRACKET CLASSIFIER_FUNCTION EQUAL ( schema_name=id_ DOT function_name=id_ | NULL_ ) RR_BRACKET | RESET STATISTICS | WITH LR_BRACKET MAX_OUTSTANDING_IO_PER_VOLUME EQUAL max_outstanding_io_per_volume=DECIMAL RR_BRACKET ) ; // https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-audit-specification-transact-sql?view=sql-server-ver16 alter_database_audit_specification : ALTER DATABASE AUDIT SPECIFICATION audit_specification_name=id_ (FOR SERVER AUDIT audit_name=id_)? (audit_action_spec_group (',' audit_action_spec_group)*)? (WITH '(' STATE '=' (ON|OFF) ')')? ; audit_action_spec_group : (ADD|DROP) '(' (audit_action_specification | audit_action_group_name=id_) ')' ; audit_action_specification : action_specification (',' action_specification)* ON (audit_class_name '::')? audit_securable BY principal_id (',' principal_id)* ; action_specification : SELECT | INSERT | UPDATE | DELETE | EXECUTE | RECEIVE | REFERENCES ; audit_class_name : OBJECT | SCHEMA | TABLE ; audit_securable : ((id_ '.')? id_ '.')? id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-role-transact-sql alter_db_role : ALTER ROLE role_name=id_ ( (ADD|DROP) MEMBER database_principal=id_ | WITH NAME EQUAL new_role_name=id_ ) ; // https://learn.microsoft.com/en-us/sql/t-sql/statements/create-database-audit-specification-transact-sql?view=sql-server-ver16 create_database_audit_specification : CREATE DATABASE AUDIT SPECIFICATION audit_specification_name=id_ (FOR SERVER AUDIT audit_name=id_)? (audit_action_spec_group (',' audit_action_spec_group)*)? (WITH '(' STATE '=' (ON|OFF) ')')? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-role-transact-sql create_db_role : CREATE ROLE role_name=id_ (AUTHORIZATION owner_name = id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-route-transact-sql create_route : CREATE ROUTE route_name=id_ (AUTHORIZATION owner_name=id_)? WITH (COMMA? SERVICE_NAME EQUAL route_service_name=STRING)? (COMMA? BROKER_INSTANCE EQUAL broker_instance_identifier=STRING)? (COMMA? LIFETIME EQUAL DECIMAL)? COMMA? ADDRESS EQUAL STRING (COMMA MIRROR_ADDRESS EQUAL STRING )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-rule-transact-sql create_rule : CREATE RULE (schema_name=id_ DOT)? rule_name=id_ AS search_condition ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-schema-transact-sql alter_schema_sql : ALTER SCHEMA schema_name=id_ TRANSFER ((OBJECT|TYPE|XML SCHEMA COLLECTION) DOUBLE_COLON )? id_ (DOT id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-schema-transact-sql create_schema : CREATE SCHEMA (schema_name=id_ |AUTHORIZATION owner_name=id_ | schema_name=id_ AUTHORIZATION owner_name=id_ ) (create_table |create_view | (GRANT|DENY) (SELECT|INSERT|DELETE|UPDATE) ON (SCHEMA DOUBLE_COLON)? object_name=id_ TO owner_name=id_ | REVOKE (SELECT|INSERT|DELETE|UPDATE) ON (SCHEMA DOUBLE_COLON)? object_name=id_ FROM owner_name=id_ )* ; create_schema_azure_sql_dw_and_pdw : CREATE SCHEMA schema_name=id_ (AUTHORIZATION owner_name=id_ )? ; alter_schema_azure_sql_dw_and_pdw : ALTER SCHEMA schema_name=id_ TRANSFER (OBJECT DOUBLE_COLON )? id_ (DOT ID)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-search-property-list-transact-sql create_search_property_list : CREATE SEARCH PROPERTY LIST new_list_name=id_ (FROM (database_name=id_ DOT)? source_list_name=id_ )? (AUTHORIZATION owner_name=id_)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-security-policy-transact-sql create_security_policy : CREATE SECURITY POLICY (schema_name=id_ DOT)? security_policy_name=id_ (COMMA? ADD (FILTER|BLOCK)? PREDICATE tvf_schema_name=id_ DOT security_predicate_function_name=id_ LR_BRACKET (COMMA? column_name_or_arguments=id_)+ RR_BRACKET ON table_schema_name=id_ DOT name=id_ (COMMA? AFTER (INSERT|UPDATE) | COMMA? BEFORE (UPDATE|DELETE) )* )+ (WITH LR_BRACKET STATE EQUAL (ON|OFF) (SCHEMABINDING (ON|OFF) )? RR_BRACKET )? (NOT FOR REPLICATION)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-sequence-transact-sql alter_sequence : ALTER SEQUENCE (schema_name=id_ DOT)? sequence_name=id_ ( RESTART (WITH DECIMAL)? )? (INCREMENT BY sequnce_increment=DECIMAL )? ( MINVALUE DECIMAL| NO MINVALUE)? (MAXVALUE DECIMAL| NO MAXVALUE)? (CYCLE|NO CYCLE)? (CACHE DECIMAL | NO CACHE)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql create_sequence : CREATE SEQUENCE (schema_name=id_ DOT)? sequence_name=id_ (AS data_type )? (START WITH DECIMAL)? (INCREMENT BY MINUS? DECIMAL)? (MINVALUE (MINUS? DECIMAL)? | NO MINVALUE)? (MAXVALUE (MINUS? DECIMAL)? | NO MAXVALUE)? (CYCLE|NO CYCLE)? (CACHE DECIMAL? | NO CACHE)? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-server-audit-transact-sql alter_server_audit : ALTER SERVER AUDIT audit_name=id_ ( ( TO (FILE ( LR_BRACKET ( COMMA? FILEPATH EQUAL filepath=STRING | COMMA? MAXSIZE EQUAL ( DECIMAL (MB|GB|TB) | UNLIMITED ) | COMMA? MAX_ROLLOVER_FILES EQUAL max_rollover_files=(DECIMAL|UNLIMITED) | COMMA? MAX_FILES EQUAL max_files=DECIMAL | COMMA? RESERVE_DISK_SPACE EQUAL (ON|OFF) )* RR_BRACKET ) | APPLICATION_LOG | SECURITY_LOG ) )? ( WITH LR_BRACKET (COMMA? QUEUE_DELAY EQUAL queue_delay=DECIMAL | COMMA? ON_FAILURE EQUAL (CONTINUE | SHUTDOWN|FAIL_OPERATION) |COMMA? STATE EQUAL (ON|OFF) )* RR_BRACKET )? ( WHERE ( COMMA? (NOT?) event_field_name=id_ (EQUAL |(LESS GREATER) | (EXCLAMATION EQUAL) | GREATER | (GREATER EQUAL) | LESS | LESS EQUAL ) (DECIMAL | STRING) | COMMA? (AND|OR) NOT? (EQUAL |(LESS GREATER) | (EXCLAMATION EQUAL) | GREATER | (GREATER EQUAL) | LESS | LESS EQUAL) (DECIMAL | STRING) ) )? |REMOVE WHERE | MODIFY NAME EQUAL new_audit_name=id_ ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-server-audit-transact-sql create_server_audit : CREATE SERVER AUDIT audit_name=id_ ( ( TO (FILE ( LR_BRACKET ( COMMA? FILEPATH EQUAL filepath=STRING | COMMA? MAXSIZE EQUAL ( DECIMAL (MB|GB|TB) | UNLIMITED ) | COMMA? MAX_ROLLOVER_FILES EQUAL max_rollover_files=(DECIMAL|UNLIMITED) | COMMA? MAX_FILES EQUAL max_files=DECIMAL | COMMA? RESERVE_DISK_SPACE EQUAL (ON|OFF) )* RR_BRACKET ) | APPLICATION_LOG | SECURITY_LOG ) )? ( WITH LR_BRACKET (COMMA? QUEUE_DELAY EQUAL queue_delay=DECIMAL | COMMA? ON_FAILURE EQUAL (CONTINUE | SHUTDOWN|FAIL_OPERATION) |COMMA? STATE EQUAL (ON|OFF) |COMMA? AUDIT_GUID EQUAL audit_guid=id_ )* RR_BRACKET )? ( WHERE ( COMMA? (NOT?) event_field_name=id_ (EQUAL |(LESS GREATER) | (EXCLAMATION EQUAL) | GREATER | (GREATER EQUAL) | LESS | LESS EQUAL ) (DECIMAL | STRING) | COMMA? (AND|OR) NOT? (EQUAL |(LESS GREATER) | (EXCLAMATION EQUAL) | GREATER | (GREATER EQUAL) | LESS | LESS EQUAL) (DECIMAL | STRING) ) )? |REMOVE WHERE | MODIFY NAME EQUAL new_audit_name=id_ ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-server-audit-specification-transact-sql alter_server_audit_specification : ALTER SERVER AUDIT SPECIFICATION audit_specification_name=id_ (FOR SERVER AUDIT audit_name=id_)? ( (ADD|DROP) LR_BRACKET audit_action_group_name=id_ RR_BRACKET )* (WITH LR_BRACKET STATE EQUAL (ON|OFF) RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-server-audit-specification-transact-sql create_server_audit_specification : CREATE SERVER AUDIT SPECIFICATION audit_specification_name=id_ (FOR SERVER AUDIT audit_name=id_)? ( ADD LR_BRACKET audit_action_group_name=id_ RR_BRACKET )* (WITH LR_BRACKET STATE EQUAL (ON|OFF) RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-server-configuration-transact-sql alter_server_configuration : ALTER SERVER CONFIGURATION SET ( (PROCESS AFFINITY (CPU EQUAL (AUTO | (COMMA? DECIMAL | COMMA? DECIMAL TO DECIMAL)+ ) | NUMANODE EQUAL ( COMMA? DECIMAL |COMMA? DECIMAL TO DECIMAL)+ ) | DIAGNOSTICS LOG (ON|OFF|PATH EQUAL (STRING | DEFAULT) |MAX_SIZE EQUAL (DECIMAL MB |DEFAULT)|MAX_FILES EQUAL (DECIMAL|DEFAULT) ) | FAILOVER CLUSTER PROPERTY (VERBOSELOGGING EQUAL (STRING|DEFAULT) |SQLDUMPERFLAGS EQUAL (STRING|DEFAULT) | SQLDUMPERPATH EQUAL (STRING|DEFAULT) | SQLDUMPERTIMEOUT (STRING|DEFAULT) | FAILURECONDITIONLEVEL EQUAL (STRING|DEFAULT) | HEALTHCHECKTIMEOUT EQUAL (DECIMAL|DEFAULT) ) | HADR CLUSTER CONTEXT EQUAL (STRING|LOCAL) | BUFFER POOL EXTENSION (ON LR_BRACKET FILENAME EQUAL STRING COMMA SIZE EQUAL DECIMAL (KB|MB|GB) RR_BRACKET | OFF ) | SET SOFTNUMA (ON|OFF) ) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-server-role-transact-sql alter_server_role : ALTER SERVER ROLE server_role_name=id_ ( (ADD|DROP) MEMBER server_principal=id_ | WITH NAME EQUAL new_server_role_name=id_ ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-server-role-transact-sql create_server_role : CREATE SERVER ROLE server_role=id_ (AUTHORIZATION server_principal=id_)? ; alter_server_role_pdw : ALTER SERVER ROLE server_role_name=id_ (ADD|DROP) MEMBER login=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-service-transact-sql alter_service : ALTER SERVICE modified_service_name=id_ (ON QUEUE (schema_name=id_ DOT)? queue_name=id_)? ('(' opt_arg_clause (COMMA opt_arg_clause)* ')')? ; opt_arg_clause : (ADD|DROP) CONTRACT modified_contract_name=id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-service-transact-sql create_service : CREATE SERVICE create_service_name=id_ (AUTHORIZATION owner_name=id_)? ON QUEUE (schema_name=id_ DOT)? queue_name=id_ ( LR_BRACKET (COMMA? (id_|DEFAULT) )+ RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-service-master-key-transact-sql alter_service_master_key : ALTER SERVICE MASTER KEY ( FORCE? REGENERATE | (WITH (OLD_ACCOUNT EQUAL acold_account_name=STRING COMMA OLD_PASSWORD EQUAL old_password=STRING | NEW_ACCOUNT EQUAL new_account_name=STRING COMMA NEW_PASSWORD EQUAL new_password=STRING)? ) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-symmetric-key-transact-sql alter_symmetric_key : ALTER SYMMETRIC KEY key_name=id_ ( (ADD|DROP) ENCRYPTION BY (CERTIFICATE certificate_name=id_ | PASSWORD EQUAL password=STRING | SYMMETRIC KEY symmetric_key_name=id_ | ASYMMETRIC KEY Asym_key_name=id_ ) ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-synonym-transact-sql create_synonym : CREATE SYNONYM (schema_name_1=id_ DOT )? synonym_name=id_ FOR ( (server_name=id_ DOT )? (database_name=id_ DOT)? (schema_name_2=id_ DOT)? object_name=id_ | (database_or_schema2=id_ DOT)? (schema_id_2_or_object_name=id_ DOT)? ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-user-transact-sql alter_user : ALTER USER username=id_ WITH (COMMA? NAME EQUAL newusername=id_ | COMMA? DEFAULT_SCHEMA EQUAL ( schema_name=id_ |NULL_ ) | COMMA? LOGIN EQUAL loginame=id_ | COMMA? PASSWORD EQUAL STRING (OLD_PASSWORD EQUAL STRING)+ | COMMA? DEFAULT_LANGUAGE EQUAL (NONE| lcid=DECIMAL| language_name_or_alias=id_) | COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )+ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-user-transact-sql create_user : CREATE USER user_name=id_ ( (FOR|FROM) LOGIN login_name=id_ )? ( WITH (COMMA? DEFAULT_SCHEMA EQUAL schema_name=id_ |COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )* )? | CREATE USER ( windows_principal=id_ (WITH (COMMA? DEFAULT_SCHEMA EQUAL schema_name=id_ |COMMA? DEFAULT_LANGUAGE EQUAL (NONE |DECIMAL |language_name_or_alias=id_ ) |COMMA? SID EQUAL BINARY |COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )* )? | user_name=id_ WITH PASSWORD EQUAL password=STRING (COMMA? DEFAULT_SCHEMA EQUAL schema_name=id_ |COMMA? DEFAULT_LANGUAGE EQUAL (NONE |DECIMAL |language_name_or_alias=id_ ) |COMMA? SID EQUAL BINARY |COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )* | Azure_Active_Directory_principal=id_ FROM EXTERNAL PROVIDER ) | CREATE USER user_name=id_ ( WITHOUT LOGIN (COMMA? DEFAULT_SCHEMA EQUAL schema_name=id_ |COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )* | (FOR|FROM) CERTIFICATE cert_name=id_ | (FOR|FROM) ASYMMETRIC KEY asym_key_name=id_ ) | CREATE USER user_name=id_ ; create_user_azure_sql_dw : CREATE USER user_name=id_ ( (FOR|FROM) LOGIN login_name=id_ | WITHOUT LOGIN )? ( WITH DEFAULT_SCHEMA EQUAL schema_name=id_)? | CREATE USER Azure_Active_Directory_principal=id_ FROM EXTERNAL PROVIDER ( WITH DEFAULT_SCHEMA EQUAL schema_name=id_)? ; alter_user_azure_sql : ALTER USER username=id_ WITH (COMMA? NAME EQUAL newusername=id_ | COMMA? DEFAULT_SCHEMA EQUAL schema_name=id_ | COMMA? LOGIN EQUAL loginame=id_ | COMMA? ALLOW_ENCRYPTED_VALUE_MODIFICATIONS EQUAL (ON|OFF) )+ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-workload-group-transact-sql alter_workload_group : ALTER WORKLOAD GROUP (workload_group_group_name=id_ |DEFAULT_DOUBLE_QUOTE ) (WITH LR_BRACKET (IMPORTANCE EQUAL (LOW|MEDIUM|HIGH) | COMMA? REQUEST_MAX_MEMORY_GRANT_PERCENT EQUAL request_max_memory_grant=DECIMAL | COMMA? REQUEST_MAX_CPU_TIME_SEC EQUAL request_max_cpu_time_sec=DECIMAL | REQUEST_MEMORY_GRANT_TIMEOUT_SEC EQUAL request_memory_grant_timeout_sec=DECIMAL | MAX_DOP EQUAL max_dop=DECIMAL | GROUP_MAX_REQUESTS EQUAL group_max_requests=DECIMAL)+ RR_BRACKET )? (USING (workload_group_pool_name=id_ | DEFAULT_DOUBLE_QUOTE) )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-workload-group-transact-sql create_workload_group : CREATE WORKLOAD GROUP workload_group_group_name=id_ (WITH LR_BRACKET (IMPORTANCE EQUAL (LOW|MEDIUM|HIGH) | COMMA? REQUEST_MAX_MEMORY_GRANT_PERCENT EQUAL request_max_memory_grant=DECIMAL | COMMA? REQUEST_MAX_CPU_TIME_SEC EQUAL request_max_cpu_time_sec=DECIMAL | REQUEST_MEMORY_GRANT_TIMEOUT_SEC EQUAL request_memory_grant_timeout_sec=DECIMAL | MAX_DOP EQUAL max_dop=DECIMAL | GROUP_MAX_REQUESTS EQUAL group_max_requests=DECIMAL)+ RR_BRACKET )? (USING (workload_group_pool_name=id_ | DEFAULT_DOUBLE_QUOTE)? (COMMA? EXTERNAL external_pool_name=id_ | DEFAULT_DOUBLE_QUOTE)? )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-xml-schema-collection-transact-sql create_xml_schema_collection : CREATE XML SCHEMA COLLECTION (relational_schema=id_ DOT)? sql_identifier=id_ AS (STRING|id_|LOCAL_ID) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-partition-function-transact-sql?view=sql-server-ver15 create_partition_function : CREATE PARTITION FUNCTION partition_function_name=id_ '(' input_parameter_type=data_type ')' AS RANGE ( LEFT | RIGHT )? FOR VALUES '(' boundary_values=expression_list_ ')' ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-partition-scheme-transact-sql?view=sql-server-ver15 create_partition_scheme : CREATE PARTITION SCHEME partition_scheme_name=id_ AS PARTITION partition_function_name=id_ ALL? TO '(' file_group_names+=id_ (',' file_group_names+=id_)* ')' ; create_queue : CREATE QUEUE (full_table_name | queue_name=id_) queue_settings? (ON filegroup=id_ | DEFAULT)? ; queue_settings : WITH (STATUS EQUAL on_off COMMA?)? (RETENTION EQUAL on_off COMMA?)? (ACTIVATION LR_BRACKET ( ( (STATUS EQUAL on_off COMMA? )? (PROCEDURE_NAME EQUAL func_proc_name_database_schema COMMA?)? (MAX_QUEUE_READERS EQUAL max_readers=DECIMAL COMMA?)? (EXECUTE AS (SELF | user_name=STRING | OWNER) COMMA?)? ) | DROP ) RR_BRACKET COMMA? )? (POISON_MESSAGE_HANDLING LR_BRACKET (STATUS EQUAL on_off) RR_BRACKET )? ; alter_queue : ALTER QUEUE (full_table_name | queue_name=id_) (queue_settings | queue_action) ; queue_action : REBUILD ( WITH LR_BRACKET queue_rebuild_options RR_BRACKET)? | REORGANIZE (WITH LOB_COMPACTION EQUAL on_off)? | MOVE TO (id_ | DEFAULT) ; queue_rebuild_options : MAXDOP EQUAL DECIMAL ; create_contract : CREATE CONTRACT contract_name (AUTHORIZATION owner_name=id_)? LR_BRACKET ((message_type_name=id_ | DEFAULT) SENT BY (INITIATOR | TARGET | ANY ) COMMA?)+ RR_BRACKET ; conversation_statement : begin_conversation_timer | begin_conversation_dialog | end_conversation | get_conversation | send_conversation | waitfor_conversation ; message_statement : CREATE MESSAGE TYPE message_type_name=id_ (AUTHORIZATION owner_name=id_)? (VALIDATION EQUAL (NONE | EMPTY | WELL_FORMED_XML | VALID_XML WITH SCHEMA COLLECTION schema_collection_name=id_)) ; // DML // https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql // note that there's a limit on number of when_matches but it has to be done runtime due to different ordering of statements allowed merge_statement : with_expression? MERGE (TOP '(' expression ')' PERCENT?)? INTO? ddl_object with_table_hints? as_table_alias? USING table_sources ON search_condition when_matches+ output_clause? option_clause? ';' ; when_matches : (WHEN MATCHED (AND search_condition)? THEN merge_matched)+ | (WHEN NOT MATCHED (BY TARGET)? (AND search_condition)? THEN merge_not_matched) | (WHEN NOT MATCHED BY SOURCE (AND search_condition)? THEN merge_matched)+ ; merge_matched : UPDATE SET update_elem_merge (',' update_elem_merge)* | DELETE ; merge_not_matched : INSERT ('(' column_name_list ')')? (table_value_constructor | DEFAULT VALUES) ; // https://msdn.microsoft.com/en-us/library/ms189835.aspx delete_statement : with_expression? DELETE (TOP '(' expression ')' PERCENT? | TOP DECIMAL)? FROM? delete_statement_from with_table_hints? output_clause? (FROM table_sources)? (WHERE (search_condition | CURRENT OF (GLOBAL? cursor_name | cursor_var=LOCAL_ID)))? for_clause? option_clause? ';'? ; delete_statement_from : ddl_object | rowset_function_limited | table_var=LOCAL_ID ; // https://msdn.microsoft.com/en-us/library/ms174335.aspx insert_statement : with_expression? INSERT (TOP '(' expression ')' PERCENT?)? INTO? (ddl_object | rowset_function_limited) with_table_hints? ('(' insert_column_name_list ')')? output_clause? insert_statement_value for_clause? option_clause? ';'? ; insert_statement_value : table_value_constructor | derived_table | execute_statement | DEFAULT VALUES ; receive_statement : '('? RECEIVE (ALL | DISTINCT | top_clause | '*') (LOCAL_ID '=' expression ','?)* FROM full_table_name (INTO table_variable=id_ (WHERE where=search_condition))? ')'? ; // https://msdn.microsoft.com/en-us/library/ms189499.aspx select_statement_standalone : with_expression? select_statement ; select_statement : query_expression select_order_by_clause? for_clause? option_clause? ';'? ; time : (LOCAL_ID | constant) ; // https://msdn.microsoft.com/en-us/library/ms177523.aspx update_statement : with_expression? UPDATE (TOP '(' expression ')' PERCENT?)? (ddl_object | rowset_function_limited) with_table_hints? SET update_elem (',' update_elem)* output_clause? (FROM table_sources)? (WHERE (search_condition | CURRENT OF (GLOBAL? cursor_name | cursor_var=LOCAL_ID)))? for_clause? option_clause? ';'? ; // https://msdn.microsoft.com/en-us/library/ms177564.aspx output_clause : OUTPUT output_dml_list_elem (',' output_dml_list_elem)* (INTO (LOCAL_ID | table_name) ('(' column_name_list ')')? )? ; output_dml_list_elem : (expression | asterisk) as_column_alias? ; // DDL // https://msdn.microsoft.com/en-ie/library/ms176061.aspx create_database : CREATE DATABASE (database=id_) ( CONTAINMENT '=' ( NONE | PARTIAL ) )? ( ON PRIMARY? database_file_spec ( ',' database_file_spec )* )? ( LOG ON database_file_spec ( ',' database_file_spec )* )? ( COLLATE collation_name = id_ )? ( WITH create_database_option ( ',' create_database_option )* )? ; // https://msdn.microsoft.com/en-us/library/ms188783.aspx create_index : CREATE UNIQUE? clustered? INDEX id_ ON table_name '(' column_name_list_with_order ')' (INCLUDE '(' column_name_list ')' )? (WHERE where=search_condition)? (create_index_options)? (ON id_)? ';'? ; create_index_options : 'WITH' '(' relational_index_option (',' relational_index_option)* ')' ; relational_index_option : rebuild_index_option | DROP_EXISTING '=' on_off | OPTIMIZE_FOR_SEQUENTIAL_KEY '=' on_off ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-index-transact-sql alter_index : ALTER INDEX (id_ | ALL) ON table_name (DISABLE | PAUSE | ABORT | RESUME resumable_index_options? | reorganize_partition | set_index_options | rebuild_partition) ; resumable_index_options : WITH '(' (resumable_index_option (',' resumable_index_option)*) ')' ; resumable_index_option : MAXDOP '=' max_degree_of_parallelism=DECIMAL | MAX_DURATION '=' max_duration=DECIMAL MINUTES? | low_priority_lock_wait ; reorganize_partition : REORGANIZE (PARTITION '=' DECIMAL)? reorganize_options? ; reorganize_options : WITH '(' (reorganize_option (',' reorganize_option)*) ')' ; reorganize_option : LOB_COMPACTION '=' on_off | COMPRESS_ALL_ROW_GROUPS '=' on_off ; set_index_options : SET '(' set_index_option (',' set_index_option)* ')' ; set_index_option : ALLOW_ROW_LOCKS '=' on_off | ALLOW_PAGE_LOCKS '=' on_off | OPTIMIZE_FOR_SEQUENTIAL_KEY '=' on_off | IGNORE_DUP_KEY '=' on_off | STATISTICS_NORECOMPUTE '=' on_off | COMPRESSION_DELAY '=' delay=DECIMAL MINUTES? ; rebuild_partition : REBUILD (PARTITION '=' ALL)? rebuild_index_options? | REBUILD PARTITION '=' DECIMAL single_partition_rebuild_index_options? ; rebuild_index_options : WITH '(' rebuild_index_option (',' rebuild_index_option)* ')' ; rebuild_index_option : PAD_INDEX '=' on_off | FILLFACTOR '=' DECIMAL | SORT_IN_TEMPDB '=' on_off | IGNORE_DUP_KEY '=' on_off | STATISTICS_NORECOMPUTE '=' on_off | STATISTICS_INCREMENTAL '=' on_off | ONLINE '=' (ON ('(' low_priority_lock_wait ')')? | OFF) | RESUMABLE '=' on_off | MAX_DURATION '=' times=DECIMAL MINUTES? | ALLOW_ROW_LOCKS '=' on_off | ALLOW_PAGE_LOCKS '=' on_off | MAXDOP '=' max_degree_of_parallelism=DECIMAL | DATA_COMPRESSION '=' (NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE) on_partitions? | XML_COMPRESSION '=' on_off on_partitions? ; single_partition_rebuild_index_options : WITH '(' single_partition_rebuild_index_option (',' single_partition_rebuild_index_option)* ')' ; single_partition_rebuild_index_option : SORT_IN_TEMPDB '=' on_off | MAXDOP '=' max_degree_of_parallelism=DECIMAL | RESUMABLE '=' on_off | DATA_COMPRESSION '=' (NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE) on_partitions? | XML_COMPRESSION '=' on_off on_partitions? | ONLINE '=' (ON ('(' low_priority_lock_wait ')')? | OFF) ; on_partitions : ON PARTITIONS '(' partition_number=DECIMAL ( 'TO' to_partition_number=DECIMAL )? ( ',' partition_number=DECIMAL ( 'TO' to_partition_number=DECIMAL )? )* ')' ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-columnstore-index-transact-sql?view=sql-server-ver15 create_columnstore_index : CREATE CLUSTERED COLUMNSTORE INDEX id_ ON table_name create_columnstore_index_options? (ON id_)? ';'? ; create_columnstore_index_options : 'WITH' '(' columnstore_index_option (',' columnstore_index_option)* ')' ; columnstore_index_option : DROP_EXISTING '=' on_off | MAXDOP '=' max_degree_of_parallelism=DECIMAL | ONLINE '=' on_off | COMPRESSION_DELAY '=' delay=DECIMAL MINUTES? | DATA_COMPRESSION '=' (COLUMNSTORE | COLUMNSTORE_ARCHIVE) on_partitions? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-columnstore-index-transact-sql?view=sql-server-ver15 create_nonclustered_columnstore_index : CREATE NONCLUSTERED? COLUMNSTORE INDEX id_ ON table_name '(' column_name_list_with_order ')' (WHERE search_condition)? create_columnstore_index_options? (ON id_)? ';'? ; create_xml_index : CREATE PRIMARY? XML INDEX id_ ON table_name '(' id_ ')' (USING XML INDEX id_ (FOR (VALUE | PATH | PROPERTY)?)?)? xml_index_options? ';'? ; xml_index_options : 'WITH' '(' xml_index_option (',' xml_index_option)* ')' ; xml_index_option : PAD_INDEX '=' on_off | FILLFACTOR '=' DECIMAL | SORT_IN_TEMPDB '=' on_off | IGNORE_DUP_KEY '=' on_off | DROP_EXISTING '=' on_off | ONLINE '=' (ON ('(' low_priority_lock_wait ')')? | OFF) | ALLOW_ROW_LOCKS '=' on_off | ALLOW_PAGE_LOCKS '=' on_off | MAXDOP '=' max_degree_of_parallelism=DECIMAL | XML_COMPRESSION '=' on_off ; // https://msdn.microsoft.com/en-us/library/ms187926(v=sql.120).aspx create_or_alter_procedure : ((CREATE (OR (ALTER | REPLACE))?) | ALTER) proc=(PROC | PROCEDURE) procName=func_proc_name_schema (';' DECIMAL)? ('('? procedure_param (',' procedure_param)* ')'?)? (WITH procedure_option (',' procedure_option)*)? (FOR REPLICATION)? AS (as_external_name | sql_clauses*) ; as_external_name : EXTERNAL NAME assembly_name = id_ '.' class_name = id_ '.' method_name = id_ ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql create_or_alter_trigger : create_or_alter_dml_trigger | create_or_alter_ddl_trigger ; create_or_alter_dml_trigger : (CREATE (OR (ALTER | REPLACE))? | ALTER) TRIGGER simple_name ON table_name (WITH dml_trigger_option (',' dml_trigger_option)* )? (FOR | AFTER | INSTEAD OF) dml_trigger_operation (',' dml_trigger_operation)* (WITH APPEND)? (NOT FOR REPLICATION)? AS sql_clauses+ ; dml_trigger_option : ENCRYPTION | execute_clause ; dml_trigger_operation : (INSERT | UPDATE | DELETE) ; create_or_alter_ddl_trigger : (CREATE (OR (ALTER | REPLACE))? | ALTER) TRIGGER simple_name ON (ALL SERVER | DATABASE) (WITH dml_trigger_option (',' dml_trigger_option)* )? (FOR | AFTER) ddl_trigger_operation (',' ddl_trigger_operation)* AS sql_clauses+ ; ddl_trigger_operation : simple_id ; // https://msdn.microsoft.com/en-us/library/ms186755.aspx create_or_alter_function : ((CREATE (OR ALTER)?) | ALTER) FUNCTION funcName=func_proc_name_schema (('(' procedure_param (',' procedure_param)* ')') | '(' ')') //must have (), but can be empty (func_body_returns_select | func_body_returns_table | func_body_returns_scalar) ';'? ; func_body_returns_select : RETURNS TABLE (WITH function_option (',' function_option)*)? AS? (as_external_name | RETURN ('(' select_statement_standalone ')' | select_statement_standalone)) ; func_body_returns_table : RETURNS LOCAL_ID table_type_definition (WITH function_option (',' function_option)*)? AS? (as_external_name | BEGIN sql_clauses* RETURN ';'? END ';'?) ; func_body_returns_scalar : RETURNS data_type (WITH function_option (',' function_option)*)? AS? (as_external_name | BEGIN sql_clauses* RETURN ret=expression ';'? END) ; procedure_param_default_value : NULL_ | DEFAULT | constant | LOCAL_ID ; procedure_param : LOCAL_ID AS? (type_schema=id_ '.')? data_type VARYING? ('=' default_val=procedure_param_default_value)? (OUT | OUTPUT | READONLY)? ; procedure_option : ENCRYPTION | RECOMPILE | execute_clause ; function_option : ENCRYPTION | SCHEMABINDING | RETURNS NULL_ ON NULL_ INPUT | CALLED ON NULL_ INPUT | execute_clause ; // https://msdn.microsoft.com/en-us/library/ms188038.aspx create_statistics : CREATE STATISTICS id_ ON table_name '(' column_name_list ')' (WITH (FULLSCAN | SAMPLE DECIMAL (PERCENT | ROWS) | STATS_STREAM) (',' NORECOMPUTE)? (',' INCREMENTAL EQUAL on_off)? )? ';'? ; update_statistics : UPDATE STATISTICS full_table_name ( id_ | '(' id_ ( ',' id_ )* ')' )? update_statistics_options? ; update_statistics_options : WITH update_statistics_option (',' update_statistics_option)* ; update_statistics_option : ( FULLSCAN (','? PERSIST_SAMPLE_PERCENT '=' on_off )? ) | ( SAMPLE number=DECIMAL (PERCENT | ROWS) (','? PERSIST_SAMPLE_PERCENT '=' on_off )? ) | RESAMPLE on_partitions? | STATS_STREAM '=' stats_stream_=expression | ROWCOUNT '=' DECIMAL | PAGECOUNT '=' DECIMAL | ALL | COLUMNS | INDEX | NORECOMPUTE | INCREMENTAL '=' on_off | MAXDOP '=' max_dregree_of_parallelism=DECIMAL | AUTO_DROP '=' on_off ; // https://msdn.microsoft.com/en-us/library/ms174979.aspx create_table : CREATE TABLE table_name '(' column_def_table_constraints (','? table_indices)* ','? ')' (LOCK simple_id)? table_options* (ON id_ | DEFAULT | on_partition_or_filegroup)? (TEXTIMAGE_ON id_ | DEFAULT)?';'? ; table_indices : INDEX id_ UNIQUE? clustered? '(' column_name_list_with_order ')' | INDEX id_ CLUSTERED COLUMNSTORE | INDEX id_ NONCLUSTERED? COLUMNSTORE '(' column_name_list ')' create_table_index_options? (ON id_)? ; table_options : WITH ('(' table_option (',' table_option)* ')' | table_option (',' table_option)*) ; table_option : (simple_id | keyword) '=' (simple_id | keyword | on_off | DECIMAL) | CLUSTERED COLUMNSTORE INDEX | HEAP | FILLFACTOR '=' DECIMAL | DISTRIBUTION '=' HASH '(' id_ ')' | CLUSTERED INDEX '(' id_ (ASC | DESC)? (',' id_ (ASC | DESC)?)* ')' | DATA_COMPRESSION '=' (NONE | ROW | PAGE) on_partitions? | XML_COMPRESSION '=' on_off on_partitions? ; create_table_index_options : WITH '(' create_table_index_option ( ',' create_table_index_option)* ')' ; create_table_index_option : PAD_INDEX '=' on_off | FILLFACTOR '=' DECIMAL | IGNORE_DUP_KEY '=' on_off | STATISTICS_NORECOMPUTE '=' on_off | STATISTICS_INCREMENTAL '=' on_off | ALLOW_ROW_LOCKS '=' on_off | ALLOW_PAGE_LOCKS '=' on_off | OPTIMIZE_FOR_SEQUENTIAL_KEY '=' on_off | DATA_COMPRESSION '=' (NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE) on_partitions? | XML_COMPRESSION '=' on_off on_partitions? ; // https://msdn.microsoft.com/en-us/library/ms187956.aspx create_view : (CREATE (OR (ALTER | REPLACE))? | ALTER) VIEW simple_name ('(' column_name_list ')')? (WITH view_attribute (',' view_attribute)*)? AS select_statement_standalone (WITH CHECK OPTION)? ';'? ; view_attribute : ENCRYPTION | SCHEMABINDING | VIEW_METADATA ; // https://msdn.microsoft.com/en-us/library/ms190273.aspx alter_table : ALTER TABLE table_name (SET '(' LOCK_ESCALATION '=' (AUTO | TABLE | DISABLE) ')' | ADD column_def_table_constraints | ALTER COLUMN (column_definition | column_modifier) | DROP COLUMN id_ (',' id_)* | DROP CONSTRAINT constraint=id_ | WITH (CHECK | NOCHECK) ADD (CONSTRAINT constraint=id_)? ( FOREIGN KEY '(' fk=column_name_list ')' REFERENCES table_name ('(' pk=column_name_list')')? (on_delete | on_update)* | CHECK '(' search_condition ')' ) | (NOCHECK | CHECK) CONSTRAINT constraint=id_ | (ENABLE | DISABLE) TRIGGER id_? | REBUILD table_options | SWITCH switch_partition) ';'? ; switch_partition : (PARTITION? source_partition_number_expression=expression)? TO target_table=table_name (PARTITION target_partition_number_expression=expression)? (WITH low_priority_lock_wait)? ; low_priority_lock_wait : WAIT_AT_LOW_PRIORITY '(' MAX_DURATION '=' max_duration=time MINUTES? ',' ABORT_AFTER_WAIT '=' abort_after_wait=(NONE | SELF | BLOCKERS) ')' ; // https://msdn.microsoft.com/en-us/library/ms174269.aspx alter_database : ALTER DATABASE (database=id_ | CURRENT) (MODIFY NAME '=' new_name=id_ | COLLATE collation=id_ | SET database_optionspec (WITH termination)? | add_or_modify_files | add_or_modify_filegroups ) ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-database-transact-sql-file-and-filegroup-options?view=sql-server-ver15 add_or_modify_files : ADD FILE filespec (',' filespec)* (TO FILEGROUP filegroup_name=id_)? | ADD LOG FILE filespec (',' filespec)* | REMOVE FILE logical_file_name=id_ | MODIFY FILE filespec ; filespec : '(' NAME '=' name=id_or_string (',' NEWNAME '=' new_name=id_or_string )? (',' FILENAME '=' file_name=STRING )? (',' SIZE '=' size=file_size )? (',' MAXSIZE '=' (max_size=file_size) | UNLIMITED )? (',' FILEGROWTH '=' growth_increment=file_size )? (',' OFFLINE )? ')' ; add_or_modify_filegroups : ADD FILEGROUP filegroup_name=id_ (CONTAINS FILESTREAM | CONTAINS MEMORY_OPTIMIZED_DATA)? | REMOVE FILEGROUP filegrou_name=id_ | MODIFY FILEGROUP filegrou_name=id_ ( filegroup_updatability_option | DEFAULT | NAME '=' new_filegroup_name=id_ | AUTOGROW_SINGLE_FILE | AUTOGROW_ALL_FILES ) ; filegroup_updatability_option : READONLY | READWRITE | READ_ONLY | READ_WRITE ; // https://msdn.microsoft.com/en-us/library/bb522682.aspx // Runtime check. database_optionspec : auto_option | change_tracking_option | containment_option | cursor_option | database_mirroring_option | date_correlation_optimization_option | db_encryption_option | db_state_option | db_update_option | db_user_access_option | delayed_durability_option | external_access_option | FILESTREAM database_filestream_option | hadr_options | mixed_page_allocation_option | parameterization_option // | query_store_options | recovery_option // | remote_data_archive_option | service_broker_option | snapshot_option | sql_option | target_recovery_time_option | termination ; auto_option : AUTO_CLOSE on_off | AUTO_CREATE_STATISTICS OFF | ON ( INCREMENTAL EQUAL ON | OFF ) | AUTO_SHRINK on_off | AUTO_UPDATE_STATISTICS on_off | AUTO_UPDATE_STATISTICS_ASYNC (ON | OFF ) ; change_tracking_option : CHANGE_TRACKING EQUAL ( OFF | ON '(' (change_tracking_option_list (',' change_tracking_option_list)*)* ')' ) ; change_tracking_option_list : AUTO_CLEANUP EQUAL on_off | CHANGE_RETENTION EQUAL DECIMAL ( DAYS | HOURS | MINUTES ) ; containment_option : CONTAINMENT EQUAL ( NONE | PARTIAL ) ; cursor_option : CURSOR_CLOSE_ON_COMMIT on_off | CURSOR_DEFAULT ( LOCAL | GLOBAL ) ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-endpoint-transact-sql alter_endpoint : ALTER ENDPOINT endpointname=id_ (AUTHORIZATION login=id_)? (STATE EQUAL state=(STARTED | STOPPED | DISABLED))? AS TCP LR_BRACKET endpoint_listener_clause RR_BRACKET ( FOR TSQL LR_BRACKET RR_BRACKET | FOR SERVICE_BROKER LR_BRACKET endpoint_authentication_clause (COMMA? endpoint_encryption_alogorithm_clause)? (COMMA? MESSAGE_FORWARDING EQUAL (ENABLED | DISABLED))? (COMMA? MESSAGE_FORWARD_SIZE EQUAL DECIMAL)? RR_BRACKET | FOR DATABASE_MIRRORING LR_BRACKET endpoint_authentication_clause (COMMA? endpoint_encryption_alogorithm_clause)? COMMA? ROLE EQUAL (WITNESS | PARTNER | ALL) RR_BRACKET ) ; /* Will visit later */ database_mirroring_option : mirroring_set_option ; mirroring_set_option : mirroring_partner partner_option | mirroring_witness witness_option ; mirroring_partner : PARTNER ; mirroring_witness : WITNESS ; witness_partner_equal : EQUAL ; partner_option : witness_partner_equal partner_server | FAILOVER | FORCE_SERVICE_ALLOW_DATA_LOSS | OFF | RESUME | SAFETY (FULL | OFF ) | SUSPEND | TIMEOUT DECIMAL ; witness_option : witness_partner_equal witness_server | OFF ; witness_server : partner_server ; partner_server : partner_server_tcp_prefix host mirroring_host_port_seperator port_number ; mirroring_host_port_seperator : COLON ; partner_server_tcp_prefix : TCP COLON DOUBLE_FORWARD_SLASH ; port_number : port=DECIMAL ; host : id_ DOT host | (id_ DOT |id_) ; date_correlation_optimization_option : DATE_CORRELATION_OPTIMIZATION on_off ; db_encryption_option : ENCRYPTION on_off ; db_state_option : ( ONLINE | OFFLINE | EMERGENCY ) ; db_update_option : READ_ONLY | READ_WRITE ; db_user_access_option : SINGLE_USER | RESTRICTED_USER | MULTI_USER ; delayed_durability_option : DELAYED_DURABILITY EQUAL ( DISABLED | ALLOWED | FORCED ) ; external_access_option : DB_CHAINING on_off | TRUSTWORTHY on_off | DEFAULT_LANGUAGE EQUAL ( id_ | STRING ) | DEFAULT_FULLTEXT_LANGUAGE EQUAL ( id_ | STRING ) | NESTED_TRIGGERS EQUAL ( OFF | ON ) | TRANSFORM_NOISE_WORDS EQUAL ( OFF | ON ) | TWO_DIGIT_YEAR_CUTOFF EQUAL DECIMAL ; hadr_options : HADR ( ( AVAILABILITY GROUP EQUAL availability_group_name=id_ | OFF ) |(SUSPEND|RESUME) ) ; mixed_page_allocation_option : MIXED_PAGE_ALLOCATION ( OFF | ON ) ; parameterization_option : PARAMETERIZATION ( SIMPLE | FORCED ) ; recovery_option : RECOVERY ( FULL | BULK_LOGGED | SIMPLE ) | TORN_PAGE_DETECTION on_off | ACCELERATED_DATABASE_RECOVERY '=' on_off | PAGE_VERIFY ( CHECKSUM | TORN_PAGE_DETECTION | NONE ) ; service_broker_option: ENABLE_BROKER | DISABLE_BROKER | NEW_BROKER | ERROR_BROKER_CONVERSATIONS | HONOR_BROKER_PRIORITY on_off ; snapshot_option : ALLOW_SNAPSHOT_ISOLATION on_off | READ_COMMITTED_SNAPSHOT (ON | OFF ) | MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = (ON | OFF ) ; sql_option : ANSI_NULL_DEFAULT on_off | ANSI_NULLS on_off | ANSI_PADDING on_off | ANSI_WARNINGS on_off | ARITHABORT on_off | COMPATIBILITY_LEVEL EQUAL DECIMAL | CONCAT_NULL_YIELDS_NULL on_off | NUMERIC_ROUNDABORT on_off | QUOTED_IDENTIFIER on_off | RECURSIVE_TRIGGERS on_off ; target_recovery_time_option : TARGET_RECOVERY_TIME EQUAL DECIMAL ( SECONDS | MINUTES ) ; termination : ROLLBACK AFTER seconds = DECIMAL | ROLLBACK IMMEDIATE | NO_WAIT ; // https://msdn.microsoft.com/en-us/library/ms176118.aspx drop_index : DROP INDEX (IF EXISTS)? ( drop_relational_or_xml_or_spatial_index (',' drop_relational_or_xml_or_spatial_index)* | drop_backward_compatible_index (',' drop_backward_compatible_index)* ) ';'? ; drop_relational_or_xml_or_spatial_index : index_name=id_ ON full_table_name ; drop_backward_compatible_index : (owner_name=id_ '.')? table_or_view_name=id_ '.' index_name=id_ ; // https://msdn.microsoft.com/en-us/library/ms174969.aspx drop_procedure : DROP proc=(PROC | PROCEDURE) (IF EXISTS)? func_proc_name_schema (',' func_proc_name_schema)* ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-trigger-transact-sql drop_trigger : drop_dml_trigger | drop_ddl_trigger ; drop_dml_trigger : DROP TRIGGER (IF EXISTS)? simple_name (',' simple_name)* ';'? ; drop_ddl_trigger : DROP TRIGGER (IF EXISTS)? simple_name (',' simple_name)* ON (DATABASE | ALL SERVER) ';'? ; // https://msdn.microsoft.com/en-us/library/ms190290.aspx drop_function : DROP FUNCTION (IF EXISTS)? func_proc_name_schema (',' func_proc_name_schema)* ';'? ; // https://msdn.microsoft.com/en-us/library/ms175075.aspx drop_statistics : DROP STATISTICS (COMMA? (table_name '.')? name=id_)+ ';' ; // https://msdn.microsoft.com/en-us/library/ms173790.aspx drop_table : DROP TABLE (IF EXISTS)? table_name (',' table_name)* ';'? ; // https://msdn.microsoft.com/en-us/library/ms173492.aspx drop_view : DROP VIEW (IF EXISTS)? simple_name (',' simple_name)* ';'? ; create_type : CREATE TYPE name = simple_name (FROM data_type null_notnull?)? (AS TABLE LR_BRACKET column_def_table_constraints RR_BRACKET)? ; drop_type: DROP TYPE ( IF EXISTS )? name = simple_name ; rowset_function_limited : openquery | opendatasource ; // https://msdn.microsoft.com/en-us/library/ms188427(v=sql.120).aspx openquery : OPENQUERY '(' linked_server=id_ ',' query=STRING ')' ; // https://msdn.microsoft.com/en-us/library/ms179856.aspx opendatasource : OPENDATASOURCE '(' provider=STRING ',' init=STRING ')' '.' (database=id_)? '.' (scheme=id_)? '.' (table=id_) ; // Other statements. // https://msdn.microsoft.com/en-us/library/ms188927.aspx declare_statement : DECLARE LOCAL_ID AS? (data_type | table_type_definition | table_name) | DECLARE loc+=declare_local (',' loc+=declare_local)* | DECLARE LOCAL_ID AS? xml_type_definition | WITH XMLNAMESPACES '(' xml_dec+=xml_declaration (',' xml_dec+=xml_declaration)* ')' ; xml_declaration : xml_namespace_uri=STRING AS id_ | DEFAULT STRING ; // https://msdn.microsoft.com/en-us/library/ms181441(v=sql.120).aspx cursor_statement // https://msdn.microsoft.com/en-us/library/ms175035(v=sql.120).aspx : CLOSE GLOBAL? cursor_name ';'? // https://msdn.microsoft.com/en-us/library/ms188782(v=sql.120).aspx | DEALLOCATE GLOBAL? CURSOR? cursor_name ';'? // https://msdn.microsoft.com/en-us/library/ms180169(v=sql.120).aspx | declare_cursor // https://msdn.microsoft.com/en-us/library/ms180152(v=sql.120).aspx | fetch_cursor // https://msdn.microsoft.com/en-us/library/ms190500(v=sql.120).aspx | OPEN GLOBAL? cursor_name ';'? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/backup-transact-sql backup_database : BACKUP DATABASE ( database_name=id_ ) (READ_WRITE_FILEGROUPS (COMMA? (FILE|FILEGROUP) EQUAL file_or_filegroup=STRING)* )? (COMMA? (FILE|FILEGROUP) EQUAL file_or_filegroup=STRING)* ( TO ( COMMA? logical_device_name=id_)+ | TO ( COMMA? (DISK|TAPE|URL) EQUAL (STRING|id_) )+ ) ( (MIRROR TO ( COMMA? logical_device_name=id_)+ )+ | ( MIRROR TO ( COMMA? (DISK|TAPE|URL) EQUAL (STRING|id_) )+ )+ )? (WITH ( COMMA? DIFFERENTIAL | COMMA? COPY_ONLY | COMMA? (COMPRESSION|NO_COMPRESSION) | COMMA? DESCRIPTION EQUAL (STRING|id_) | COMMA? NAME EQUAL backup_set_name=id_ | COMMA? CREDENTIAL | COMMA? FILE_SNAPSHOT | COMMA? (EXPIREDATE EQUAL (STRING|id_) | RETAINDAYS EQUAL (DECIMAL|id_) ) | COMMA? (NOINIT|INIT) | COMMA? (NOSKIP|SKIP_KEYWORD) | COMMA? (NOFORMAT|FORMAT) | COMMA? MEDIADESCRIPTION EQUAL (STRING|id_) | COMMA? MEDIANAME EQUAL (medianame=STRING) | COMMA? BLOCKSIZE EQUAL (DECIMAL|id_) | COMMA? BUFFERCOUNT EQUAL (DECIMAL|id_) | COMMA? MAXTRANSFER EQUAL (DECIMAL|id_) | COMMA? (NO_CHECKSUM|CHECKSUM) | COMMA? (STOP_ON_ERROR|CONTINUE_AFTER_ERROR) | COMMA? RESTART | COMMA? STATS (EQUAL stats_percent=DECIMAL)? | COMMA? (REWIND|NOREWIND) | COMMA? (LOAD|NOUNLOAD) | COMMA? ENCRYPTION LR_BRACKET ALGORITHM EQUAL (AES_128 | AES_192 | AES_256 | TRIPLE_DES_3KEY ) COMMA SERVER CERTIFICATE EQUAL (encryptor_name=id_ | SERVER ASYMMETRIC KEY EQUAL encryptor_name=id_ ) )* )? ; backup_log : BACKUP LOG ( database_name=id_ ) ( TO ( COMMA? logical_device_name=id_)+ | TO ( COMMA? (DISK|TAPE|URL) EQUAL (STRING|id_) )+ ) ( (MIRROR TO ( COMMA? logical_device_name=id_)+ )+ | ( MIRROR TO ( COMMA? (DISK|TAPE|URL) EQUAL (STRING|id_) )+ )+ )? (WITH ( COMMA? DIFFERENTIAL | COMMA? COPY_ONLY | COMMA? (COMPRESSION|NO_COMPRESSION) | COMMA? DESCRIPTION EQUAL (STRING|id_) | COMMA? NAME EQUAL backup_set_name=id_ | COMMA? CREDENTIAL | COMMA? FILE_SNAPSHOT | COMMA? (EXPIREDATE EQUAL (STRING|id_) | RETAINDAYS EQUAL (DECIMAL|id_) ) | COMMA? (NOINIT|INIT) | COMMA? (NOSKIP|SKIP_KEYWORD) | COMMA? (NOFORMAT|FORMAT) | COMMA? MEDIADESCRIPTION EQUAL (STRING|id_) | COMMA? MEDIANAME EQUAL (medianame=STRING) | COMMA? BLOCKSIZE EQUAL (DECIMAL|id_) | COMMA? BUFFERCOUNT EQUAL (DECIMAL|id_) | COMMA? MAXTRANSFER EQUAL (DECIMAL|id_) | COMMA? (NO_CHECKSUM|CHECKSUM) | COMMA? (STOP_ON_ERROR|CONTINUE_AFTER_ERROR) | COMMA? RESTART | COMMA? STATS (EQUAL stats_percent=DECIMAL)? | COMMA? (REWIND|NOREWIND) | COMMA? (LOAD|NOUNLOAD) | COMMA? (NORECOVERY| STANDBY EQUAL undo_file_name=STRING) | COMMA? NO_TRUNCATE | COMMA? ENCRYPTION LR_BRACKET ALGORITHM EQUAL (AES_128 | AES_192 | AES_256 | TRIPLE_DES_3KEY ) COMMA SERVER CERTIFICATE EQUAL (encryptor_name=id_ | SERVER ASYMMETRIC KEY EQUAL encryptor_name=id_ ) )* )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/backup-certificate-transact-sql backup_certificate : BACKUP CERTIFICATE certname=id_ TO FILE EQUAL cert_file=STRING ( WITH PRIVATE KEY LR_BRACKET (COMMA? FILE EQUAL private_key_file=STRING |COMMA? ENCRYPTION BY PASSWORD EQUAL encryption_password=STRING |COMMA? DECRYPTION BY PASSWORD EQUAL decryption_pasword=STRING )+ RR_BRACKET )? ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/backup-master-key-transact-sql backup_master_key : BACKUP MASTER KEY TO FILE EQUAL master_key_backup_file=STRING ENCRYPTION BY PASSWORD EQUAL encryption_password=STRING ; // https://docs.microsoft.com/en-us/sql/t-sql/statements/backup-service-master-key-transact-sql backup_service_master_key : BACKUP SERVICE MASTER KEY TO FILE EQUAL service_master_key_backup_file=STRING ENCRYPTION BY PASSWORD EQUAL encryption_password=STRING ; kill_statement : KILL (kill_process | kill_query_notification | kill_stats_job) ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/kill-transact-sql kill_process : (session_id=(DECIMAL|STRING) | UOW) (WITH STATUSONLY)? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/kill-query-notification-subscription-transact-sql kill_query_notification : QUERY NOTIFICATION SUBSCRIPTION (ALL | subscription_id=DECIMAL) ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/kill-stats-job-transact-sql kill_stats_job : STATS JOB job_id=DECIMAL ; // https://msdn.microsoft.com/en-us/library/ms188332.aspx execute_statement : EXECUTE execute_body ';'? ; execute_body_batch : func_proc_name_server_database_schema (execute_statement_arg (',' execute_statement_arg)*)? ';'? ; //https://docs.microsoft.com/it-it/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver15 execute_body : (return_status=LOCAL_ID '=')? (func_proc_name_server_database_schema | execute_var_string) execute_statement_arg? | '(' execute_var_string (',' execute_var_string)* ')' (AS (LOGIN | USER) '=' STRING)? (AT_KEYWORD linkedServer=id_)? | AS ( (LOGIN | USER) '=' STRING | CALLER ) ; execute_statement_arg : execute_statement_arg_unnamed (',' execute_statement_arg) * //Unnamed params can continue unnamed | execute_statement_arg_named (',' execute_statement_arg_named)* //Named can only be continued by unnamed ; execute_statement_arg_named : name=LOCAL_ID '=' value=execute_parameter ; execute_statement_arg_unnamed : value=execute_parameter ; execute_parameter : (constant | LOCAL_ID (OUTPUT | OUT)? | id_ | DEFAULT | NULL_) ; execute_var_string : LOCAL_ID (OUTPUT | OUT)? ('+' LOCAL_ID ('+' execute_var_string)?)? | STRING ('+' LOCAL_ID ('+' execute_var_string)?)? ; // https://msdn.microsoft.com/en-us/library/ff848791.aspx security_statement // https://msdn.microsoft.com/en-us/library/ms188354.aspx : execute_clause ';'? // https://msdn.microsoft.com/en-us/library/ms187965.aspx | GRANT (ALL PRIVILEGES? | grant_permission ('(' column_name_list ')')?) (ON (class_type_for_grant '::')? on_id=table_name)? TO to_principal+=principal_id (',' to_principal+=principal_id)* (WITH GRANT OPTION)? (AS as_principal=principal_id)? ';'? // https://msdn.microsoft.com/en-us/library/ms178632.aspx | REVERT (WITH COOKIE '=' LOCAL_ID)? ';'? | open_key | close_key | create_key | create_certificate ; principal_id : id_ | PUBLIC ; create_certificate : CREATE CERTIFICATE certificate_name=id_ (AUTHORIZATION user_name=id_)? (FROM existing_keys | generate_new_keys) (ACTIVE FOR BEGIN DIALOG '=' on_off)? ; existing_keys : ASSEMBLY assembly_name=id_ | EXECUTABLE? FILE EQUAL path_to_file=STRING (WITH PRIVATE KEY '(' private_key_options ')')? ; private_key_options : (FILE | BINARY) '=' path=STRING (',' (DECRYPTION | ENCRYPTION) BY PASSWORD '=' password=STRING)? ; generate_new_keys : (ENCRYPTION BY PASSWORD '=' password=STRING)? WITH SUBJECT EQUAL certificate_subject_name=STRING (',' date_options)* ; date_options : (START_DATE | EXPIRY_DATE) EQUAL STRING ; open_key : OPEN SYMMETRIC KEY key_name=id_ DECRYPTION BY decryption_mechanism | OPEN MASTER KEY DECRYPTION BY PASSWORD '=' password=STRING ; close_key : CLOSE SYMMETRIC KEY key_name=id_ | CLOSE ALL SYMMETRIC KEYS | CLOSE MASTER KEY ; create_key : CREATE MASTER KEY ENCRYPTION BY PASSWORD '=' password=STRING | CREATE SYMMETRIC KEY key_name=id_ (AUTHORIZATION user_name=id_)? (FROM PROVIDER provider_name=id_)? WITH ((key_options | ENCRYPTION BY encryption_mechanism)','?)+ ; key_options : KEY_SOURCE EQUAL pass_phrase=STRING | ALGORITHM EQUAL algorithm | IDENTITY_VALUE EQUAL identity_phrase=STRING | PROVIDER_KEY_NAME EQUAL key_name_in_provider=STRING | CREATION_DISPOSITION EQUAL (CREATE_NEW | OPEN_EXISTING) ; algorithm : DES | TRIPLE_DES | TRIPLE_DES_3KEY | RC2 | RC4 | RC4_128 | DESX | AES_128 | AES_192 | AES_256 ; encryption_mechanism : CERTIFICATE certificate_name=id_ | ASYMMETRIC KEY asym_key_name=id_ | SYMMETRIC KEY decrypting_Key_name=id_ | PASSWORD '=' STRING ; decryption_mechanism : CERTIFICATE certificate_name=id_ (WITH PASSWORD EQUAL STRING)? | ASYMMETRIC KEY asym_key_name=id_ (WITH PASSWORD EQUAL STRING)? | SYMMETRIC KEY decrypting_Key_name=id_ | PASSWORD EQUAL STRING ; // https://docs.microsoft.com/en-us/sql/relational-databases/system-functions/sys-fn-builtin-permissions-transact-sql?view=sql-server-ver15 // SELECT DISTINCT '| ' + permission_name // FROM sys.fn_builtin_permissions (DEFAULT) // ORDER BY 1 grant_permission : ADMINISTER ( BULK OPERATIONS | DATABASE BULK OPERATIONS) | ALTER ( ANY ( APPLICATION ROLE | ASSEMBLY | ASYMMETRIC KEY | AVAILABILITY GROUP | CERTIFICATE | COLUMN ( ENCRYPTION KEY | MASTER KEY ) | CONNECTION | CONTRACT | CREDENTIAL | DATABASE ( AUDIT | DDL TRIGGER | EVENT ( NOTIFICATION | SESSION ) | SCOPED CONFIGURATION )? | DATASPACE | ENDPOINT | EVENT ( NOTIFICATION | SESSION ) | EXTERNAL ( DATA SOURCE | FILE FORMAT | LIBRARY) | FULLTEXT CATALOG | LINKED SERVER | LOGIN | MASK | MESSAGE TYPE | REMOTE SERVICE BINDING | ROLE | ROUTE | SCHEMA | SECURITY POLICY | SERVER ( AUDIT | ROLE ) | SERVICE | SYMMETRIC KEY | USER ) | RESOURCES | SERVER STATE | SETTINGS | TRACE )? | AUTHENTICATE SERVER? | BACKUP ( DATABASE | LOG ) | CHECKPOINT | CONNECT ( ANY DATABASE | REPLICATION | SQL )? | CONTROL SERVER? | CREATE ( AGGREGATE | ANY DATABASE | ASSEMBLY | ASYMMETRIC KEY | AVAILABILITY GROUP | CERTIFICATE | CONTRACT | DATABASE (DDL EVENT NOTIFICATION)? | DDL EVENT NOTIFICATION | DEFAULT | ENDPOINT | EXTERNAL LIBRARY | FULLTEXT CATALOG | FUNCTION | MESSAGE TYPE | PROCEDURE | QUEUE | REMOTE SERVICE BINDING | ROLE | ROUTE | RULE | SCHEMA | SEQUENCE | SERVER ROLE | SERVICE | SYMMETRIC KEY | SYNONYM | TABLE | TRACE EVENT NOTIFICATION | TYPE | VIEW | XML SCHEMA COLLECTION ) | DELETE | EXECUTE ( ANY EXTERNAL SCRIPT )? | EXTERNAL ACCESS ASSEMBLY | IMPERSONATE ( ANY LOGIN )? | INSERT | KILL DATABASE CONNECTION | RECEIVE | REFERENCES | SELECT ( ALL USER SECURABLES )? | SEND | SHOWPLAN | SHUTDOWN | SUBSCRIBE QUERY NOTIFICATIONS | TAKE OWNERSHIP | UNMASK | UNSAFE ASSEMBLY | UPDATE | VIEW ( ANY ( DATABASE | DEFINITION | COLUMN ( ENCRYPTION | MASTER ) KEY DEFINITION ) | CHANGE TRACKING | DATABASE STATE | DEFINITION | SERVER STATE ) ; // https://msdn.microsoft.com/en-us/library/ms190356.aspx // https://msdn.microsoft.com/en-us/library/ms189484.aspx set_statement : SET LOCAL_ID ('.' member_name=id_)? '=' expression | SET LOCAL_ID assignment_operator expression | SET LOCAL_ID '=' CURSOR declare_set_cursor_common (FOR (READ ONLY | UPDATE (OF column_name_list)?))? // https://msdn.microsoft.com/en-us/library/ms189837.aspx | set_special ; // https://msdn.microsoft.com/en-us/library/ms174377.aspx transaction_statement // https://msdn.microsoft.com/en-us/library/ms188386.aspx : BEGIN DISTRIBUTED (TRAN | TRANSACTION) (id_ | LOCAL_ID)? // https://msdn.microsoft.com/en-us/library/ms188929.aspx | BEGIN (TRAN | TRANSACTION) ((id_ | LOCAL_ID) (WITH MARK STRING)?)? // https://msdn.microsoft.com/en-us/library/ms190295.aspx | COMMIT (TRAN | TRANSACTION) ((id_ | LOCAL_ID) (WITH '(' DELAYED_DURABILITY EQUAL (OFF | ON) ')')?)? // https://msdn.microsoft.com/en-us/library/ms178628.aspx | COMMIT WORK? | COMMIT id_ | ROLLBACK id_ // https://msdn.microsoft.com/en-us/library/ms181299.aspx | ROLLBACK (TRAN | TRANSACTION) (id_ | LOCAL_ID)? // https://msdn.microsoft.com/en-us/library/ms174973.aspx | ROLLBACK WORK? // https://msdn.microsoft.com/en-us/library/ms188378.aspx | SAVE (TRAN | TRANSACTION) (id_ | LOCAL_ID)? ; // https://msdn.microsoft.com/en-us/library/ms188037.aspx go_statement : GO (count=DECIMAL)? ; // https://msdn.microsoft.com/en-us/library/ms188366.aspx use_statement : USE database=id_ ; setuser_statement : SETUSER user=STRING? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/reconfigure-transact-sql reconfigure_statement : RECONFIGURE (WITH OVERRIDE)? ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/shutdown-transact-sql shutdown_statement : SHUTDOWN (WITH NOWAIT)? ; checkpoint_statement : CHECKPOINT (checkPointDuration=DECIMAL)? ; dbcc_checkalloc_option : ALL_ERRORMSGS | NO_INFOMSGS | TABLOCK | ESTIMATEONLY ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkalloc-transact-sql?view=sql-server-ver16 dbcc_checkalloc : name=CHECKALLOC ( '(' ( database=id_ | databaseid=STRING | DECIMAL ) ( ',' NOINDEX | ',' ( REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD ) )? ')' ( WITH dbcc_option=dbcc_checkalloc_option ( ',' dbcc_option=dbcc_checkalloc_option )* )? )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkcatalog-transact-sql?view=sql-server-ver16 dbcc_checkcatalog : name=CHECKCATALOG ( '(' ( database=id_ | databasename=STRING | DECIMAL ) ')' )? ( WITH dbcc_option=NO_INFOMSGS )? ; dbcc_checkconstraints_option : ALL_CONSTRAINTS | ALL_ERRORMSGS | NO_INFOMSGS ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkconstraints-transact-sql?view=sql-server-ver16 dbcc_checkconstraints : name=CHECKCONSTRAINTS ( '(' ( table_or_constraint=id_ | table_or_constraint_name=STRING ) ')' )? ( WITH dbcc_option=dbcc_checkconstraints_option (',' dbcc_option=dbcc_checkconstraints_option)* )? ; dbcc_checkdb_table_option : ALL_ERRORMSGS | EXTENDED_LOGICAL_CHECKS | NO_INFOMSGS | TABLOCK | ESTIMATEONLY | PHYSICAL_ONLY | DATA_PURITY | MAXDOP '=' max_dregree_of_parallelism=DECIMAL ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkdb-transact-sql?view=sql-server-ver16 dbcc_checkdb : name=CHECKDB ( '(' ( database=id_ | databasename=STRING | DECIMAL ) ( ',' ( NOINDEX | REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD ) )? ')' )? ( WITH dbcc_option=dbcc_checkdb_table_option (',' dbcc_option=dbcc_checkdb_table_option)* )? ; dbcc_checkfilegroup_option : ALL_ERRORMSGS | NO_INFOMSGS | TABLOCK | ESTIMATEONLY | PHYSICAL_ONLY | MAXDOP '=' max_dregree_of_parallelism=DECIMAL ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checkfilegroup-transact-sql?view=sql-server-ver16 // Additional parameters: https://dbtut.com/index.php/2019/01/01/dbcc-checkfilegroup-command-on-sql-server/ dbcc_checkfilegroup : name=CHECKFILEGROUP ( '(' ( filegroup_id=DECIMAL | filegroup_name=STRING ) ( ',' ( NOINDEX | REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD ) )? ')' )? ( WITH dbcc_option=dbcc_checkfilegroup_option (',' dbcc_option=dbcc_checkfilegroup_option)* )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-checktable-transact-sql?view=sql-server-ver16 dbcc_checktable : name=CHECKTABLE '(' table_or_view_name=STRING ( ',' ( NOINDEX | index_id=expression | REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD ) )? ')' ( WITH dbcc_option=dbcc_checkdb_table_option (',' dbcc_option=dbcc_checkdb_table_option)* )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-cleantable-transact-sql?view=sql-server-ver16 dbcc_cleantable : name=CLEANTABLE '(' ( database=id_ | databasename=STRING | DECIMAL ) ',' ( table_or_view=id_ | table_or_view_name=STRING ) ( ',' batch_size=DECIMAL )? ')' ( WITH dbcc_option=NO_INFOMSGS )? ; dbcc_clonedatabase_option : NO_STATISTICS | NO_QUERYSTORE | SERVICEBROKER | VERIFY_CLONEDB | BACKUP_CLONEDB ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-clonedatabase-transact-sql?view=sql-server-ver16 dbcc_clonedatabase : name=CLONEDATABASE '(' source_database=id_ ',' target_database=id_ ')' ( WITH dbcc_option=dbcc_clonedatabase_option (',' dbcc_option=dbcc_clonedatabase_option)* )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-pdw-showspaceused-transact-sql?view=aps-pdw-2016-au7 dbcc_pdw_showspaceused : name=PDW_SHOWSPACEUSED ( '(' tablename=id_ ')' ) ? ( WITH dbcc_option=IGNORE_REPLICATED_TABLE_CACHE )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-proccache-transact-sql?view=sql-server-ver16 dbcc_proccache : name=PROCCACHE ( WITH dbcc_option=NO_INFOMSGS )? ; dbcc_showcontig_option : ALL_INDEXES | TABLERESULTS | FAST | ALL_LEVELS | NO_INFOMSGS ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-showcontig-transact-sql?view=sql-server-ver16 dbcc_showcontig : name=SHOWCONTIG ( '(' table_or_view=expression ( ',' index=expression )? ')' )? ( WITH dbcc_option=dbcc_showcontig_option (',' dbcc_showcontig_option)* )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-shrinklog-azure-sql-data-warehouse?view=aps-pdw-2016-au7 dbcc_shrinklog : name=SHRINKLOG ('(' SIZE '=' ( (DECIMAL ( MB | GB | TB ) ) | DEFAULT ) ')')? ( WITH dbcc_option=NO_INFOMSGS )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-dbreindex-transact-sql?view=sql-server-ver16 dbcc_dbreindex : name=DBREINDEX '(' table=id_or_string ( ',' index_name=id_or_string ( ',' fillfactor=expression)? )? ')' ( WITH dbcc_option=NO_INFOMSGS )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-dllname-free-transact-sql?view=sql-server-ver16 dbcc_dll_free : dllname=id_ '(' name=FREE ')' ( WITH dbcc_option=NO_INFOMSGS )? ; // https://learn.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-dropcleanbuffers-transact-sql?view=sql-server-ver16 dbcc_dropcleanbuffers : name=DROPCLEANBUFFERS ( '(' COMPUTE | ALL ')' )? ( WITH dbcc_option=NO_INFOMSGS )? ; dbcc_clause : DBCC ( dbcc_checkalloc | dbcc_checkcatalog | dbcc_checkconstraints | dbcc_checkdb | dbcc_checkfilegroup | dbcc_checktable | dbcc_cleantable | dbcc_clonedatabase | dbcc_dbreindex | dbcc_dll_free | dbcc_dropcleanbuffers | dbcc_pdw_showspaceused | dbcc_proccache | dbcc_showcontig | dbcc_shrinklog ) ; execute_clause : EXECUTE AS clause=(CALLER | SELF | OWNER | STRING) ; declare_local : LOCAL_ID AS? data_type ('=' expression)? ; table_type_definition : TABLE '(' column_def_table_constraints (','? table_type_indices)* ')' ; table_type_indices : (((PRIMARY KEY | INDEX id_) (CLUSTERED | NONCLUSTERED)?) | UNIQUE) '(' column_name_list_with_order ')' | CHECK '(' search_condition ')' ; xml_type_definition : XML '(' ( CONTENT | DOCUMENT )? xml_schema_collection ')' ; xml_schema_collection : ID '.' ID ; column_def_table_constraints : column_def_table_constraint (','? column_def_table_constraint)* ; column_def_table_constraint : column_definition | materialized_column_definition | table_constraint ; // https://msdn.microsoft.com/en-us/library/ms187742.aspx // There is a documentation error: column definition elements can be given in // any order column_definition : id_ (data_type | AS expression PERSISTED? ) column_definition_element* column_index? ; column_definition_element : FILESTREAM | COLLATE collation_name=id_ | SPARSE | MASKED WITH '(' FUNCTION '=' mask_function=STRING ')' | (CONSTRAINT constraint=id_)? DEFAULT constant_expr=expression | IDENTITY ('(' seed=DECIMAL ',' increment=DECIMAL ')')? | NOT FOR REPLICATION | GENERATED ALWAYS AS ( ROW | TRANSACTION_ID | SEQUENCE_NUMBER ) ( START | END ) HIDDEN_KEYWORD? // NULL / NOT NULL is a constraint | ROWGUIDCOL | ENCRYPTED WITH '(' COLUMN_ENCRYPTION_KEY '=' key_name=STRING ',' ENCRYPTION_TYPE '=' ( DETERMINISTIC | RANDOMIZED ) ',' ALGORITHM '=' algo=STRING ')' | column_constraint ; column_modifier : id_ (ADD | DROP) ( ROWGUIDCOL | PERSISTED | NOT FOR REPLICATION | SPARSE | HIDDEN_KEYWORD | MASKED (WITH (FUNCTION EQUAL STRING | LR_BRACKET FUNCTION EQUAL STRING RR_BRACKET))?) ; materialized_column_definition : id_ (COMPUTE | AS) expression (MATERIALIZED | NOT MATERIALIZED)? ; // https://msdn.microsoft.com/en-us/library/ms186712.aspx // There is a documentation error: NOT NULL is a constraint // and therefore can be given a name. column_constraint : (CONSTRAINT constraint=id_)? ( null_notnull | ( (PRIMARY KEY | UNIQUE) clustered? primary_key_options ) | ( (FOREIGN KEY)? foreign_key_options ) | check_constraint ) ; column_index : INDEX index_name=id_ clustered? create_table_index_options? on_partition_or_filegroup? ( FILESTREAM_ON ( filestream_filegroup_or_partition_schema_name=id_ | NULL_DOUBLE_QUOTE ) )? ; on_partition_or_filegroup : ON ( (partition_scheme_name=id_ '(' partition_column_name=id_ ')') | filegroup=id_ | DEFAULT_DOUBLE_QUOTE ) ; // https://msdn.microsoft.com/en-us/library/ms188066.aspx table_constraint : (CONSTRAINT constraint=id_)? ( ( (PRIMARY KEY | UNIQUE) clustered? '(' column_name_list_with_order ')' primary_key_options ) | ( FOREIGN KEY '(' fk = column_name_list ')' foreign_key_options ) | ( CONNECTION '(' connection_node ( ',' connection_node )* ')' ) | ( DEFAULT constant_expr=expression FOR column=id_ (WITH VALUES)? ) | check_constraint ) ; connection_node : from_node_table=id_ TO to_node_table=id_ ; primary_key_options : (WITH FILLFACTOR '=' DECIMAL)? alter_table_index_options? on_partition_or_filegroup? ; foreign_key_options : REFERENCES table_name '(' pk = column_name_list')' (on_delete | on_update)* (NOT FOR REPLICATION)? ; check_constraint : CHECK (NOT FOR REPLICATION)? '(' search_condition ')' ; on_delete : ON DELETE (NO ACTION | CASCADE | SET NULL_ | SET DEFAULT) ; on_update : ON UPDATE (NO ACTION | CASCADE | SET NULL_ | SET DEFAULT) ; alter_table_index_options : WITH '(' alter_table_index_option (',' alter_table_index_option)* ')' ; // https://msdn.microsoft.com/en-us/library/ms186869.aspx alter_table_index_option : PAD_INDEX '=' on_off | FILLFACTOR '=' DECIMAL | IGNORE_DUP_KEY '=' on_off | STATISTICS_NORECOMPUTE '=' on_off | ALLOW_ROW_LOCKS '=' on_off | ALLOW_PAGE_LOCKS '=' on_off | OPTIMIZE_FOR_SEQUENTIAL_KEY '=' on_off | SORT_IN_TEMPDB '=' on_off | MAXDOP '=' max_degree_of_parallelism=DECIMAL | DATA_COMPRESSION '=' (NONE | ROW | PAGE | COLUMNSTORE | COLUMNSTORE_ARCHIVE) on_partitions? | XML_COMPRESSION '=' on_off on_partitions? | DISTRIBUTION '=' HASH '(' id_ ')' | CLUSTERED INDEX '(' id_ (ASC | DESC)? (',' id_ (ASC | DESC)?)* ')' | ONLINE '=' (ON ('(' low_priority_lock_wait ')')? | OFF) | RESUMABLE '=' on_off | MAX_DURATION '=' times=DECIMAL MINUTES? ; // https://msdn.microsoft.com/en-us/library/ms180169.aspx declare_cursor : DECLARE cursor_name (CURSOR (declare_set_cursor_common (FOR UPDATE (OF column_name_list)?)?)? | (SEMI_SENSITIVE | INSENSITIVE)? SCROLL? CURSOR FOR select_statement_standalone (FOR (READ ONLY | UPDATE | (OF column_name_list)))? ) ';'? ; declare_set_cursor_common : declare_set_cursor_common_partial* FOR select_statement_standalone ; declare_set_cursor_common_partial : (LOCAL | GLOBAL) | (FORWARD_ONLY | SCROLL) | (STATIC | KEYSET | DYNAMIC | FAST_FORWARD) | (READ_ONLY | SCROLL_LOCKS | OPTIMISTIC) | TYPE_WARNING ; fetch_cursor : FETCH ((NEXT | PRIOR | FIRST | LAST | (ABSOLUTE | RELATIVE) expression)? FROM)? GLOBAL? cursor_name (INTO LOCAL_ID (',' LOCAL_ID)*)? ';'? ; // https://msdn.microsoft.com/en-us/library/ms190356.aspx // Runtime check. set_special : SET id_ (id_ | constant_LOCAL_ID | on_off) ';'? | SET STATISTICS (IO | TIME | XML | PROFILE) on_off ';'? | SET ROWCOUNT (LOCAL_ID | DECIMAL) ';'? | SET TEXTSIZE DECIMAL ';'? // https://msdn.microsoft.com/en-us/library/ms173763.aspx | SET TRANSACTION ISOLATION LEVEL (READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE | DECIMAL) ';'? // https://msdn.microsoft.com/en-us/library/ms188059.aspx | SET IDENTITY_INSERT table_name on_off ';'? | SET special_list (',' special_list)* on_off | SET modify_method ; special_list : ANSI_NULLS | QUOTED_IDENTIFIER | ANSI_PADDING | ANSI_WARNINGS | ANSI_DEFAULTS | ANSI_NULL_DFLT_OFF | ANSI_NULL_DFLT_ON | ARITHABORT | ARITHIGNORE | CONCAT_NULL_YIELDS_NULL | CURSOR_CLOSE_ON_COMMIT | FMTONLY | FORCEPLAN | IMPLICIT_TRANSACTIONS | NOCOUNT | NOEXEC | NUMERIC_ROUNDABORT | PARSEONLY | REMOTE_PROC_TRANSACTIONS | SHOWPLAN_ALL | SHOWPLAN_TEXT | SHOWPLAN_XML | XACT_ABORT ; constant_LOCAL_ID : constant | LOCAL_ID ; // Expression. // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/expressions-transact-sql // Operator precendence: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/operator-precedence-transact-sql expression : primitive_expression | function_call | expression '.' (value_call | query_call | exist_call | modify_call) | expression '.' hierarchyid_call | expression COLLATE id_ | case_expression | full_column_name | bracket_expression | unary_operator_expression | expression op=('*' | '/' | '%') expression | expression op=('+' | '-' | '&' | '^' | '|' | '||') expression | expression time_zone | over_clause | DOLLAR_ACTION ; parameter : PLACEHOLDER; time_zone : AT_KEYWORD TIME ZONE expression ; primitive_expression : DEFAULT | NULL_ | LOCAL_ID | primitive_constant ; // https://docs.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql case_expression : CASE caseExpr=expression switch_section+ (ELSE elseExpr=expression)? END | CASE switch_search_condition_section+ (ELSE elseExpr=expression)? END ; unary_operator_expression : '~' expression | op=('+' | '-') expression ; bracket_expression : '(' expression ')' | '(' subquery ')' ; subquery : select_statement ; // https://msdn.microsoft.com/en-us/library/ms175972.aspx with_expression : WITH ctes+=common_table_expression (',' ctes+=common_table_expression)* ; common_table_expression : expression_name=id_ ('(' columns=column_name_list ')')? AS '(' cte_query=select_statement ')' ; update_elem : LOCAL_ID '=' full_column_name ('=' | assignment_operator) expression //Combined variable and column update | (full_column_name | LOCAL_ID) ('=' | assignment_operator) expression | udt_column_name=id_ '.' method_name=id_ '(' expression_list_ ')' //| full_column_name '.' WRITE (expression, ) ; update_elem_merge : (full_column_name | LOCAL_ID) ('=' | assignment_operator) expression | udt_column_name=id_ '.' method_name=id_ '(' expression_list_ ')' //| full_column_name '.' WRITE (expression, ) ; // https://docs.microsoft.com/en-us/sql/t-sql/queries/search-condition-transact-sql search_condition : NOT* (predicate | '(' search_condition ')') | search_condition AND search_condition // AND takes precedence over OR | search_condition OR search_condition ; predicate : EXISTS '(' subquery ')' | freetext_predicate | expression comparison_operator expression | expression MULT_ASSIGN expression ////SQL-82 syntax for left outer joins; '*='. See https://stackoverflow.com/questions/40665/in-sybase-sql | expression comparison_operator (ALL | SOME | ANY) '(' subquery ')' | expression NOT* BETWEEN expression AND expression | expression NOT* IN '(' (subquery | expression_list_) ')' | expression NOT* LIKE expression (ESCAPE expression)? | expression IS null_notnull ; // Changed union rule to sql_union to avoid union construct with C++ target. Issue reported by person who generates into C++. This individual reports change causes generated code to work query_expression : query_specification select_order_by_clause? unions+=sql_union* //if using top, order by can be on the "top" side of union :/ | '(' query_expression ')' (UNION ALL? query_expression)? ; sql_union : (UNION ALL? | EXCEPT | INTERSECT) (spec=query_specification | ('(' op=query_expression ')')) ; // https://msdn.microsoft.com/en-us/library/ms176104.aspx query_specification : SELECT allOrDistinct=(ALL | DISTINCT)? top=top_clause? columns=select_list // https://msdn.microsoft.com/en-us/library/ms188029.aspx (INTO into=table_name)? (FROM from=table_sources)? (WHERE where=search_condition)? // https://msdn.microsoft.com/en-us/library/ms177673.aspx (GROUP BY ((groupByAll=ALL? groupBys+=group_by_item (',' groupBys+=group_by_item)*) | GROUPING SETS '(' groupSets+=grouping_sets_item (',' groupSets+=grouping_sets_item)* ')'))? (HAVING having=search_condition)? ; // https://msdn.microsoft.com/en-us/library/ms189463.aspx top_clause : TOP (top_percent | top_count) (WITH TIES)? ; top_percent : percent_constant=(REAL | FLOAT | DECIMAL) PERCENT | '(' topper_expression=expression ')' PERCENT ; top_count : count_constant=DECIMAL | '(' topcount_expression=expression ')' ; // https://docs.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql?view=sql-server-ver16 order_by_clause : ORDER BY order_bys+=order_by_expression (',' order_bys+=order_by_expression)* ; // https://msdn.microsoft.com/en-us/library/ms188385.aspx select_order_by_clause : order_by_clause (OFFSET offset_exp=expression offset_rows=(ROW | ROWS) (FETCH fetch_offset=(FIRST | NEXT) fetch_exp=expression fetch_rows=(ROW | ROWS) ONLY)?)? ; // https://docs.microsoft.com/en-us/sql/t-sql/queries/select-for-clause-transact-sql for_clause : FOR BROWSE | FOR XML (RAW ('(' STRING ')')? | AUTO) xml_common_directives* (COMMA (XMLDATA | XMLSCHEMA ('(' STRING ')')?))? (COMMA ELEMENTS (XSINIL | ABSENT)?)? | FOR XML EXPLICIT xml_common_directives* (COMMA XMLDATA)? | FOR XML PATH ('(' STRING ')')? xml_common_directives* (COMMA ELEMENTS (XSINIL | ABSENT)?)? | FOR JSON (AUTO | PATH) ( COMMA ( ROOT ('(' STRING ')') | INCLUDE_NULL_VALUES | WITHOUT_ARRAY_WRAPPER ) )* ; xml_common_directives : ',' (BINARY_KEYWORD BASE64 | TYPE | ROOT ('(' STRING ')')?) ; order_by_expression : order_by=expression (ascending=ASC | descending=DESC)? ; // https://docs.microsoft.com/en-us/sql/t-sql/queries/select-group-by-transact-sql?view=sql-server-ver15 grouping_sets_item : '('? groupSetItems+=group_by_item (',' groupSetItems+=group_by_item)* ')'? | '(' ')' ; group_by_item : expression /*| rollup_spec | cube_spec | grouping_sets_spec | grand_total*/ ; option_clause // https://msdn.microsoft.com/en-us/library/ms181714.aspx : OPTION '(' options_ += option (',' options_ += option)* ')' ; option : FAST number_rows=DECIMAL | (HASH | ORDER) GROUP | (MERGE | HASH | CONCAT) UNION | (LOOP | MERGE | HASH) JOIN | EXPAND VIEWS | FORCE ORDER | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX | KEEP PLAN | KEEPFIXED PLAN | MAXDOP number_of_processors=DECIMAL | MAXRECURSION number_recursion=DECIMAL | OPTIMIZE FOR '(' optimize_for_arg (',' optimize_for_arg)* ')' | OPTIMIZE FOR UNKNOWN | PARAMETERIZATION (SIMPLE | FORCED) | RECOMPILE | ROBUST PLAN | USE PLAN STRING ; optimize_for_arg : LOCAL_ID (UNKNOWN | '=' (constant | NULL_)) ; // https://msdn.microsoft.com/en-us/library/ms176104.aspx select_list : selectElement+=select_list_elem (',' selectElement+=select_list_elem)* ; udt_method_arguments : '(' argument+=execute_var_string (',' argument+=execute_var_string)* ')' ; // https://docs.microsoft.com/ru-ru/sql/t-sql/queries/select-clause-transact-sql asterisk : (table_name '.')? '*' | (INSERTED | DELETED) '.' '*' ; udt_elem : udt_column_name=id_ '.' non_static_attr=id_ udt_method_arguments as_column_alias? | udt_column_name=id_ DOUBLE_COLON static_attr=id_ udt_method_arguments? as_column_alias? ; expression_elem : leftAlias=column_alias eq='=' leftAssignment=expression | expressionAs=expression as_column_alias? ; select_list_elem : asterisk | udt_elem | LOCAL_ID (assignment_operator | '=') expression | expression_elem ; table_sources : non_ansi_join | source+=table_source (',' source+=table_source)* ; // https://sqlenlight.com/support/help/sa0006/ non_ansi_join : source+=table_source (',' source+=table_source)+ ; // https://docs.microsoft.com/en-us/sql/t-sql/queries/from-transact-sql table_source : table_source_item joins+=join_part* ; table_source_item : full_table_name deprecated_table_hint as_table_alias // this is currently allowed | full_table_name as_table_alias? (with_table_hints | deprecated_table_hint | sybase_legacy_hints)? | rowset_function as_table_alias? | '(' derived_table ')' (as_table_alias column_alias_list?)? | change_table as_table_alias? | nodes_method (as_table_alias column_alias_list?)? | function_call (as_table_alias column_alias_list?)? | loc_id=LOCAL_ID as_table_alias? | loc_id_call=LOCAL_ID '.' loc_fcall=function_call (as_table_alias column_alias_list?)? | open_xml | open_json | DOUBLE_COLON oldstyle_fcall=function_call as_table_alias? // Build-in function (old syntax) | '(' table_source ')' ; // https://docs.microsoft.com/en-us/sql/t-sql/functions/openxml-transact-sql open_xml : OPENXML '(' expression ',' expression (',' expression)? ')' (WITH '(' schema_declaration ')' )? as_table_alias? ; open_json : OPENJSON '(' expression (',' expression)? ')' (WITH '(' json_declaration ')' )? as_table_alias? ; json_declaration : json_col+=json_column_declaration (',' json_col+=json_column_declaration)* ; json_column_declaration : column_declaration (AS JSON)? ; schema_declaration : xml_col+=column_declaration (',' xml_col+=column_declaration)* ; column_declaration : id_ data_type STRING? ; change_table : change_table_changes | change_table_version ; change_table_changes : CHANGETABLE '(' CHANGES changetable=table_name ',' changesid=(NULL_ | DECIMAL | LOCAL_ID) ')' ; change_table_version : CHANGETABLE '(' VERSION versiontable=table_name ',' pk_columns=full_column_name_list ',' pk_values=select_list ')' ; // https://msdn.microsoft.com/en-us/library/ms191472.aspx join_part // https://msdn.microsoft.com/en-us/library/ms173815(v=sql.120).aspx : join_on | cross_join | apply_ | pivot | unpivot ; join_on : (inner=INNER? | join_type=(LEFT | RIGHT | FULL) outer=OUTER?) (join_hint=(LOOP | HASH | MERGE | REMOTE))? JOIN source=table_source ON cond=search_condition ; cross_join : CROSS JOIN table_source_item ; apply_ : apply_style=(CROSS | OUTER) APPLY source=table_source_item ; pivot : PIVOT pivot_clause as_table_alias ; unpivot : UNPIVOT unpivot_clause as_table_alias ; pivot_clause : '(' aggregate_windowed_function FOR full_column_name IN column_alias_list ')' ; unpivot_clause : '(' unpivot_exp=expression FOR full_column_name IN '(' full_column_name_list ')' ')' ; full_column_name_list : column+=full_column_name (',' column+=full_column_name)* ; // https://msdn.microsoft.com/en-us/library/ms190312.aspx rowset_function : ( OPENROWSET LR_BRACKET provider_name = STRING COMMA connectionString = STRING COMMA sql = STRING RR_BRACKET ) | ( OPENROWSET '(' BULK data_file=STRING ',' (bulk_option (',' bulk_option)* | id_)')' ) ; // runtime check. bulk_option : id_ '=' bulk_option_value=(DECIMAL | STRING) ; derived_table : subquery | '(' subquery (UNION ALL subquery)* ')' | table_value_constructor | '(' table_value_constructor ')' ; function_call : ranking_windowed_function #RANKING_WINDOWED_FUNC | aggregate_windowed_function #AGGREGATE_WINDOWED_FUNC | analytic_windowed_function #ANALYTIC_WINDOWED_FUNC | built_in_functions #BUILT_IN_FUNC | scalar_function_name '(' expression_list_? ')' #SCALAR_FUNCTION | freetext_function #FREE_TEXT | partition_function #PARTITION_FUNC | hierarchyid_static_method #HIERARCHYID_METHOD ; partition_function : (database=id_ '.')? DOLLAR_PARTITION '.' func_name=id_ '(' expression ')' ; freetext_function : (CONTAINSTABLE | FREETEXTTABLE) '(' table_name ',' (full_column_name | '(' full_column_name (',' full_column_name)* ')' | '*' ) ',' expression (',' LANGUAGE expression)? (',' expression)? ')' | (SEMANTICSIMILARITYTABLE | SEMANTICKEYPHRASETABLE) '(' table_name ',' (full_column_name | '(' full_column_name (',' full_column_name)* ')' | '*' ) ',' expression ')' | SEMANTICSIMILARITYDETAILSTABLE '(' table_name ',' full_column_name ',' expression ',' full_column_name ',' expression ')' ; freetext_predicate : CONTAINS '(' (full_column_name | '(' full_column_name (',' full_column_name)* ')' | '*' | PROPERTY '(' full_column_name ',' expression ')') ',' expression ')' | FREETEXT '(' table_name ',' (full_column_name | '(' full_column_name (',' full_column_name)* ')' | '*' ) ',' expression (',' LANGUAGE expression)? ')' ; json_key_value : json_key_name=expression ':' value_expression=expression ; json_null_clause : (ABSENT | NULL_) ON NULL_ ; built_in_functions // Metadata functions // https://docs.microsoft.com/en-us/sql/t-sql/functions/app-name-transact-sql?view=sql-server-ver16 : APP_NAME '(' ')' #APP_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/applock-mode-transact-sql?view=sql-server-ver16 | APPLOCK_MODE '(' database_principal=expression ',' resource_name=expression ',' lock_owner=expression ')' #APPLOCK_MODE // https://docs.microsoft.com/en-us/sql/t-sql/functions/applock-test-transact-sql?view=sql-server-ver16 | APPLOCK_TEST '(' database_principal=expression ',' resource_name=expression ',' lock_mode=expression ',' lock_owner=expression ')' #APPLOCK_TEST // https://docs.microsoft.com/en-us/sql/t-sql/functions/assemblyproperty-transact-sql?view=sql-server-ver16 | ASSEMBLYPROPERTY '(' assembly_name=expression ',' property_name=expression ')' #ASSEMBLYPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/col-length-transact-sql?view=sql-server-ver16 | COL_LENGTH '(' table=expression ',' column=expression ')' #COL_LENGTH // https://docs.microsoft.com/en-us/sql/t-sql/functions/col-name-transact-sql?view=sql-server-ver16 | COL_NAME '(' table_id=expression ',' column_id=expression ')' #COL_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/columnproperty-transact-sql?view=sql-server-ver16 | COLUMNPROPERTY '(' id=expression ',' column=expression ',' property=expression ')' #COLUMNPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/databasepropertyex-transact-sql?view=sql-server-ver16 | DATABASEPROPERTYEX '(' database=expression ',' property=expression ')' #DATABASEPROPERTYEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/db-id-transact-sql?view=sql-server-ver16 | DB_ID '(' database_name=expression? ')' #DB_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/db-name-transact-sql?view=sql-server-ver16 | DB_NAME '(' database_id=expression? ')' #DB_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/file-id-transact-sql?view=sql-server-ver16 | FILE_ID '(' file_name=expression ')' #FILE_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/file-idex-transact-sql?view=sql-server-ver16 | FILE_IDEX '(' file_name=expression ')' #FILE_IDEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/file-name-transact-sql?view=sql-server-ver16 | FILE_NAME '(' file_id=expression ')' #FILE_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/filegroup-id-transact-sql?view=sql-server-ver16 | FILEGROUP_ID '(' filegroup_name=expression ')' #FILEGROUP_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/filegroup-name-transact-sql?view=sql-server-ver16 | FILEGROUP_NAME '(' filegroup_id=expression ')' #FILEGROUP_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/filegroupproperty-transact-sql?view=sql-server-ver16 | FILEGROUPPROPERTY '(' filegroup_name=expression ',' property=expression ')' #FILEGROUPPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/fileproperty-transact-sql?view=sql-server-ver16 | FILEPROPERTY '(' file_name=expression ',' property=expression ')' #FILEPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/filepropertyex-transact-sql?view=sql-server-ver16 | FILEPROPERTYEX '(' name=expression ',' property=expression ')' #FILEPROPERTYEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/fulltextcatalogproperty-transact-sql?view=sql-server-ver16 | FULLTEXTCATALOGPROPERTY '(' catalog_name=expression ',' property=expression ')' #FULLTEXTCATALOGPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/fulltextserviceproperty-transact-sql?view=sql-server-ver16 | FULLTEXTSERVICEPROPERTY '(' property=expression ')' #FULLTEXTSERVICEPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/index-col-transact-sql?view=sql-server-ver16 | INDEX_COL '(' table_or_view_name=expression ',' index_id=expression ',' key_id=expression ')' #INDEX_COL // https://docs.microsoft.com/en-us/sql/t-sql/functions/indexkey-property-transact-sql?view=sql-server-ver16 | INDEXKEY_PROPERTY '(' object_id=expression ',' index_id=expression ',' key_id=expression ',' property=expression ')' #INDEXKEY_PROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/indexproperty-transact-sql?view=sql-server-ver16 | INDEXPROPERTY '(' object_id=expression ',' index_or_statistics_name=expression ',' property=expression ')' #INDEXPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/next-value-for-transact-sql?view=sql-server-ver16 | NEXT VALUE FOR sequence_name=table_name ( OVER '(' order_by_clause ')' )? #NEXT_VALUE_FOR // https://docs.microsoft.com/en-us/sql/t-sql/functions/object-definition-transact-sql?view=sql-server-ver16 | OBJECT_DEFINITION '(' object_id=expression ')' #OBJECT_DEFINITION // https://docs.microsoft.com/en-us/sql/t-sql/functions/object-id-transact-sql?view=sql-server-ver16 | OBJECT_ID '(' object_name=expression ( ',' object_type=expression )? ')' #OBJECT_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/object-name-transact-sql?view=sql-server-ver16 | OBJECT_NAME '(' object_id=expression ( ',' database_id=expression )? ')' #OBJECT_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/object-schema-name-transact-sql?view=sql-server-ver16 | OBJECT_SCHEMA_NAME '(' object_id=expression ( ',' database_id=expression )? ')' #OBJECT_SCHEMA_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/objectproperty-transact-sql?view=sql-server-ver16 | OBJECTPROPERTY '(' id=expression ',' property=expression ')' #OBJECTPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/objectpropertyex-transact-sql?view=sql-server-ver16 | OBJECTPROPERTYEX '(' id=expression ',' property=expression ')' #OBJECTPROPERTYEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/original-db-name-transact-sql?view=sql-server-ver16 | ORIGINAL_DB_NAME '(' ')' #ORIGINAL_DB_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/parsename-transact-sql?view=sql-server-ver16 | PARSENAME '(' object_name=expression ',' object_piece=expression ')' #PARSENAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/schema-id-transact-sql?view=sql-server-ver16 | SCHEMA_ID '(' schema_name=expression? ')' #SCHEMA_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/schema-name-transact-sql?view=sql-server-ver16 | SCHEMA_NAME '(' schema_id=expression? ')' #SCHEMA_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/scope-identity-transact-sql?view=sql-server-ver16 | SCOPE_IDENTITY '(' ')' #SCOPE_IDENTITY // https://docs.microsoft.com/en-us/sql/t-sql/functions/serverproperty-transact-sql?view=sql-server-ver16 | SERVERPROPERTY '(' property=expression ')' #SERVERPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/stats-date-transact-sql?view=sql-server-ver16 | STATS_DATE '(' object_id=expression ',' stats_id=expression ')' #STATS_DATE // https://docs.microsoft.com/en-us/sql/t-sql/functions/type-id-transact-sql?view=sql-server-ver16 | TYPE_ID '(' type_name=expression ')' #TYPE_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/type-name-transact-sql?view=sql-server-ver16 | TYPE_NAME '(' type_id=expression ')' #TYPE_NAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/typeproperty-transact-sql?view=sql-server-ver16 | TYPEPROPERTY '(' type=expression ',' property=expression ')' #TYPEPROPERTY // String functions // https://docs.microsoft.com/en-us/sql/t-sql/functions/ascii-transact-sql?view=sql-server-ver16 | ASCII '(' character_expression=expression ')' #ASCII // https://docs.microsoft.com/en-us/sql/t-sql/functions/char-transact-sql?view=sql-server-ver16 | CHAR '(' integer_expression=expression ')' #CHAR // https://docs.microsoft.com/en-us/sql/t-sql/functions/charindex-transact-sql?view=sql-server-ver16 | CHARINDEX '(' expressionToFind=expression ',' expressionToSearch=expression ( ',' start_location=expression )? ')' #CHARINDEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/concat-transact-sql?view=sql-server-ver16 | CONCAT '(' string_value_1=expression ',' string_value_2=expression ( ',' string_value_n+=expression )* ')' #CONCAT // https://docs.microsoft.com/en-us/sql/t-sql/functions/concat-ws-transact-sql?view=sql-server-ver16 | CONCAT_WS '(' separator=expression ',' argument_1=expression ',' argument_2=expression ( ',' argument_n+=expression )* ')' #CONCAT_WS // https://docs.microsoft.com/en-us/sql/t-sql/functions/difference-transact-sql?view=sql-server-ver16 | DIFFERENCE '(' character_expression_1=expression ',' character_expression_2=expression ')' #DIFFERENCE // https://docs.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql?view=sql-server-ver16 | FORMAT '(' value=expression ',' format=expression ( ',' culture=expression )? ')' #FORMAT // https://docs.microsoft.com/en-us/sql/t-sql/functions/left-transact-sql?view=sql-server-ver16 | LEFT '(' character_expression=expression ',' integer_expression=expression ')' #LEFT // https://docs.microsoft.com/en-us/sql/t-sql/functions/len-transact-sql?view=sql-server-ver16 | LEN '(' string_expression=expression ')' #LEN // https://docs.microsoft.com/en-us/sql/t-sql/functions/lower-transact-sql?view=sql-server-ver16 | LOWER '(' character_expression=expression ')' #LOWER // https://docs.microsoft.com/en-us/sql/t-sql/functions/ltrim-transact-sql?view=sql-server-ver16 | LTRIM '(' character_expression=expression ')' #LTRIM // https://docs.microsoft.com/en-us/sql/t-sql/functions/nchar-transact-sql?view=sql-server-ver16 | NCHAR '(' integer_expression=expression ')' #NCHAR // https://docs.microsoft.com/en-us/sql/t-sql/functions/patindex-transact-sql?view=sql-server-ver16 | PATINDEX '(' pattern=expression ',' string_expression=expression ')' #PATINDEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/quotename-transact-sql?view=sql-server-ver16 | QUOTENAME '(' character_string=expression ( ',' quote_character=expression )? ')' #QUOTENAME // https://docs.microsoft.com/en-us/sql/t-sql/functions/replace-transact-sql?view=sql-server-ver16 | REPLACE '(' input=expression ',' replacing=expression ',' with=expression ')' #REPLACE // https://docs.microsoft.com/en-us/sql/t-sql/functions/replicate-transact-sql?view=sql-server-ver16 | REPLICATE '(' string_expression=expression ',' integer_expression=expression ')' #REPLICATE // https://docs.microsoft.com/en-us/sql/t-sql/functions/reverse-transact-sql?view=sql-server-ver16 | REVERSE '(' string_expression=expression ')' #REVERSE // https://docs.microsoft.com/en-us/sql/t-sql/functions/right-transact-sql?view=sql-server-ver16 | RIGHT '(' character_expression=expression ',' integer_expression=expression ')' #RIGHT // https://docs.microsoft.com/en-us/sql/t-sql/functions/rtrim-transact-sql?view=sql-server-ver16 | RTRIM '(' character_expression=expression ')' #RTRIM // https://docs.microsoft.com/en-us/sql/t-sql/functions/soundex-transact-sql?view=sql-server-ver16 | SOUNDEX '(' character_expression=expression ')' #SOUNDEX // https://docs.microsoft.com/en-us/sql/t-sql/functions/space-transact-sql?view=sql-server-ver16 | SPACE_KEYWORD '(' integer_expression=expression ')' #SPACE // https://docs.microsoft.com/en-us/sql/t-sql/functions/str-transact-sql?view=sql-server-ver16 | STR '(' float_expression=expression ( ',' length_expression=expression ( ',' decimal=expression )? )? ')' #STR // https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver16 | STRING_AGG '(' expr=expression ',' separator=expression ')' (WITHIN GROUP '(' order_by_clause ')')? #STRINGAGG // https://docs.microsoft.com/en-us/sql/t-sql/functions/string-escape-transact-sql?view=sql-server-ver16 | STRING_ESCAPE '(' text_=expression ',' type_=expression ')' #STRING_ESCAPE // https://msdn.microsoft.com/fr-fr/library/ms188043.aspx | STUFF '(' str=expression ',' from=expression ',' to=expression ',' str_with=expression ')' #STUFF // https://docs.microsoft.com/en-us/sql/t-sql/functions/substring-transact-sql?view=sql-server-ver16 | SUBSTRING '(' string_expression=expression ',' start_=expression ',' length=expression ')' #SUBSTRING // https://docs.microsoft.com/en-us/sql/t-sql/functions/translate-transact-sql?view=sql-server-ver16 | TRANSLATE '(' inputString=expression ',' characters=expression ',' translations=expression ')' #TRANSLATE // https://docs.microsoft.com/en-us/sql/t-sql/functions/trim-transact-sql?view=sql-server-ver16 | TRIM '(' ( characters=expression FROM )? string_=expression ')' #TRIM // https://docs.microsoft.com/en-us/sql/t-sql/functions/unicode-transact-sql?view=sql-server-ver16 | UNICODE '(' ncharacter_expression=expression ')' #UNICODE // https://docs.microsoft.com/en-us/sql/t-sql/functions/upper-transact-sql?view=sql-server-ver16 | UPPER '(' character_expression=expression ')' #UPPER // System functions // https://msdn.microsoft.com/en-us/library/ms173784.aspx | BINARY_CHECKSUM '(' ( star='*' | expression (',' expression)* ) ')' #BINARY_CHECKSUM // https://msdn.microsoft.com/en-us/library/ms189788.aspx | CHECKSUM '(' ( star='*' | expression (',' expression)* ) ')' #CHECKSUM // https://docs.microsoft.com/en-us/sql/t-sql/functions/compress-transact-sql?view=sql-server-ver16 | COMPRESS '(' expr=expression ')' #COMPRESS // https://docs.microsoft.com/en-us/sql/t-sql/functions/connectionproperty-transact-sql?view=sql-server-ver16 | CONNECTIONPROPERTY '(' property=STRING ')' #CONNECTIONPROPERTY // https://docs.microsoft.com/en-us/sql/t-sql/functions/context-info-transact-sql?view=sql-server-ver16 | CONTEXT_INFO '(' ')' #CONTEXT_INFO // https://docs.microsoft.com/en-us/sql/t-sql/functions/current-request-id-transact-sql?view=sql-server-ver16 | CURRENT_REQUEST_ID '(' ')' #CURRENT_REQUEST_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/current-transaction-id-transact-sql?view=sql-server-ver16 | CURRENT_TRANSACTION_ID '(' ')' #CURRENT_TRANSACTION_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/decompress-transact-sql?view=sql-server-ver16 | DECOMPRESS '(' expr=expression ')' #DECOMPRESS // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-line-transact-sql?view=sql-server-ver16 | ERROR_LINE '(' ')' #ERROR_LINE // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-message-transact-sql?view=sql-server-ver16 | ERROR_MESSAGE '(' ')' #ERROR_MESSAGE // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-number-transact-sql?view=sql-server-ver16 | ERROR_NUMBER '(' ')' #ERROR_NUMBER // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-procedure-transact-sql?view=sql-server-ver16 | ERROR_PROCEDURE '(' ')' #ERROR_PROCEDURE // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-severity-transact-sql?view=sql-server-ver16 | ERROR_SEVERITY '(' ')' #ERROR_SEVERITY // https://docs.microsoft.com/en-us/sql/t-sql/functions/error-state-transact-sql?view=sql-server-ver16 | ERROR_STATE '(' ')' #ERROR_STATE // https://docs.microsoft.com/en-us/sql/t-sql/functions/formatmessage-transact-sql?view=sql-server-ver16 | FORMATMESSAGE '(' (msg_number=DECIMAL | msg_string=STRING | msg_variable=LOCAL_ID) ',' expression (',' expression)* ')' #FORMATMESSAGE // https://docs.microsoft.com/en-us/sql/t-sql/functions/get-filestream-transaction-context-transact-sql?view=sql-server-ver16 | GET_FILESTREAM_TRANSACTION_CONTEXT '(' ')' #GET_FILESTREAM_TRANSACTION_CONTEXT // https://docs.microsoft.com/en-us/sql/t-sql/functions/getansinull-transact-sql?view=sql-server-ver16 | GETANSINULL '(' (database=STRING)? ')' #GETANSINULL // https://docs.microsoft.com/en-us/sql/t-sql/functions/host-id-transact-sql?view=sql-server-ver16 | HOST_ID '(' ')' #HOST_ID // https://docs.microsoft.com/en-us/sql/t-sql/functions/host-name-transact-sql?view=sql-server-ver16 | HOST_NAME '(' ')' #HOST_NAME // https://msdn.microsoft.com/en-us/library/ms184325.aspx | ISNULL '(' left=expression ',' right=expression ')' #ISNULL // https://docs.microsoft.com/en-us/sql/t-sql/functions/isnumeric-transact-sql?view=sql-server-ver16 | ISNUMERIC '(' expression ')' #ISNUMERIC // https://docs.microsoft.com/en-us/sql/t-sql/functions/min-active-rowversion-transact-sql?view=sql-server-ver16 | MIN_ACTIVE_ROWVERSION '(' ')' #MIN_ACTIVE_ROWVERSION // https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql?view=sql-server-ver16 | NEWID '(' ')' #NEWID // https://docs.microsoft.com/en-us/sql/t-sql/functions/newsequentialid-transact-sql?view=sql-server-ver16 | NEWSEQUENTIALID '(' ')' #NEWSEQUENTIALID // https://docs.microsoft.com/en-us/sql/t-sql/functions/rowcount-big-transact-sql?view=sql-server-ver16 | ROWCOUNT_BIG '(' ')' #ROWCOUNT_BIG // https://docs.microsoft.com/en-us/sql/t-sql/functions/session-context-transact-sql?view=sql-server-ver16 | SESSION_CONTEXT '(' key=STRING ')' #SESSION_CONTEXT // https://docs.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sql?view=sql-server-ver16 | XACT_STATE '(' ')' #XACT_STATE // https://msdn.microsoft.com/en-us/library/hh231076.aspx // https://msdn.microsoft.com/en-us/library/ms187928.aspx | CAST '(' expression AS data_type ')' #CAST | TRY_CAST '(' expression AS data_type ')' #TRY_CAST | CONVERT '(' convert_data_type=data_type ','convert_expression=expression (',' style=expression)? ')' #CONVERT // https://msdn.microsoft.com/en-us/library/ms190349.aspx | COALESCE '(' expression_list_ ')' #COALESCE // Cursor functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/cursor-rows-transact-sql?view=sql-server-ver16 | CURSOR_ROWS #CURSOR_ROWS // https://learn.microsoft.com/en-us/sql/t-sql/functions/cursor-rows-transact-sql?view=sql-server-ver16 | FETCH_STATUS #FETCH_STATUS // https://learn.microsoft.com/en-us/sql/t-sql/functions/cursor-status-transact-sql?view=sql-server-ver16 | CURSOR_STATUS '(' scope=STRING ',' cursor=expression ')' #CURSOR_STATUS // Cryptographic functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/cert-id-transact-sql?view=sql-server-ver16 | CERT_ID '(' cert_name=expression ')' #CERT_ID // Data type functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql?view=sql-server-ver16 | DATALENGTH '(' expression ')' #DATALENGTH // https://learn.microsoft.com/en-us/sql/t-sql/functions/ident-current-transact-sql?view=sql-server-ver16 | IDENT_CURRENT '(' table_or_view=expression ')' # IDENT_CURRENT // https://learn.microsoft.com/en-us/sql/t-sql/functions/ident-incr-transact-sql?view=sql-server-ver16 | IDENT_INCR '(' table_or_view=expression ')' # IDENT_INCR // https://learn.microsoft.com/en-us/sql/t-sql/functions/ident-seed-transact-sql?view=sql-server-ver16 | IDENT_SEED '(' table_or_view=expression ')' # IDENT_SEED // https://learn.microsoft.com/en-us/sql/t-sql/functions/ident-seed-transact-sql?view=sql-server-ver16 | IDENTITY '(' datatype=data_type (',' seed=DECIMAL ',' increment=DECIMAL)? ')' #IDENTITY // https://learn.microsoft.com/en-us/sql/t-sql/functions/ident-seed-transact-sql?view=sql-server-ver16 | SQL_VARIANT_PROPERTY '(' expr=expression ',' property=STRING ')' #SQL_VARIANT_PROPERTY // Date functions //https://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36271.1572/html/blocks/CJADIDHD.htm | CURRENT_DATE '(' ')' #CURRENT_DATE // https://msdn.microsoft.com/en-us/library/ms188751.aspx | CURRENT_TIMESTAMP #CURRENT_TIMESTAMP // https://learn.microsoft.com/en-us/sql/t-sql/functions/current-timezone-transact-sql?view=sql-server-ver16 | CURRENT_TIMEZONE '(' ')' #CURRENT_TIMEZONE // https://learn.microsoft.com/en-us/sql/t-sql/functions/current-timezone-id-transact-sql?view=sql-server-ver16 | CURRENT_TIMEZONE_ID '(' ')' #CURRENT_TIMEZONE_ID // https://learn.microsoft.com/en-us/sql/t-sql/functions/date-bucket-transact-sql?view=sql-server-ver16 | DATE_BUCKET '(' datepart=dateparts_9 ',' number=expression ',' date=expression (',' origin=expression)? ')' #DATE_BUCKET // https://msdn.microsoft.com/en-us/library/ms186819.aspx | DATEADD '(' datepart=dateparts_12 ',' number=expression ',' date=expression ')' #DATEADD // https://msdn.microsoft.com/en-us/library/ms189794.aspx | DATEDIFF '(' datepart=dateparts_12 ',' date_first=expression ',' date_second=expression ')' #DATEDIFF // https://learn.microsoft.com/en-us/sql/t-sql/functions/datediff-big-transact-sql?view=sql-server-ver16 | DATEDIFF_BIG '(' datepart=dateparts_12 ',' startdate=expression ',' enddate=expression ')' #DATEDIFF_BIG // https://learn.microsoft.com/en-us/sql/t-sql/functions/datefromparts-transact-sql?view=sql-server-ver16 | DATEFROMPARTS '(' year=expression ',' month=expression ',' day=expression ')'#DATEFROMPARTS // https://msdn.microsoft.com/en-us/library/ms174395.aspx | DATENAME '(' datepart=dateparts_15 ',' date=expression ')' #DATENAME // https://msdn.microsoft.com/en-us/library/ms174420.aspx | DATEPART '(' datepart=dateparts_15 ',' date=expression ')' #DATEPART // https://learn.microsoft.com/en-us/sql/t-sql/functions/datetime2fromparts-transact-sql?view=sql-server-ver16 | DATETIME2FROMPARTS '(' year=expression ',' month=expression ',' day=expression ',' hour=expression ',' minute=expression ',' seconds=expression ',' fractions=expression ',' precision=expression ')' #DATETIME2FROMPARTS // https://learn.microsoft.com/en-us/sql/t-sql/functions/datetimefromparts-transact-sql?view=sql-server-ver16 | DATETIMEFROMPARTS '(' year=expression ',' month=expression ',' day=expression ',' hour=expression ',' minute=expression ',' seconds=expression ',' milliseconds=expression ')' #DATETIMEFROMPARTS // https://learn.microsoft.com/en-us/sql/t-sql/functions/datetimeoffsetfromparts-transact-sql?view=sql-server-ver16 | DATETIMEOFFSETFROMPARTS '(' year=expression ',' month=expression ',' day=expression ',' hour=expression ',' minute=expression ',' seconds=expression ',' fractions=expression ',' hour_offset=expression ',' minute_offset=expression ',' precision=DECIMAL ')' #DATETIMEOFFSETFROMPARTS // https://learn.microsoft.com/en-us/sql/t-sql/functions/datetrunc-transact-sql?view=sql-server-ver16 | DATETRUNC '(' datepart=dateparts_datetrunc ',' date=expression ')' #DATETRUNC // https://learn.microsoft.com/en-us/sql/t-sql/functions/day-transact-sql?view=sql-server-ver16 | DAY '(' date=expression ')' #DAY // https://learn.microsoft.com/en-us/sql/t-sql/functions/eomonth-transact-sql?view=sql-server-ver16 | EOMONTH '(' start_date=expression (',' month_to_add=expression)? ')'#EOMONTH // https://docs.microsoft.com/en-us/sql/t-sql/functions/getdate-transact-sql | GETDATE '(' ')' #GETDATE // https://docs.microsoft.com/en-us/sql/t-sql/functions/getdate-transact-sql | GETUTCDATE '(' ')' #GETUTCDATE // https://learn.microsoft.com/en-us/sql/t-sql/functions/isdate-transact-sql?view=sql-server-ver16 | ISDATE '(' expression ')' #ISDATE // https://learn.microsoft.com/en-us/sql/t-sql/functions/month-transact-sql?view=sql-server-ver16 | MONTH '(' date=expression ')' #MONTH // https://learn.microsoft.com/en-us/sql/t-sql/functions/smalldatetimefromparts-transact-sql?view=sql-server-ver16 | SMALLDATETIMEFROMPARTS '(' year=expression ',' month=expression ',' day=expression ',' hour=expression ',' minute=expression ')' #SMALLDATETIMEFROMPARTS // https://learn.microsoft.com/en-us/sql/t-sql/functions/switchoffset-transact-sql?view=sql-server-ver16 | SWITCHOFFSET '(' datetimeoffset_expression=expression ',' timezoneoffset_expression=expression ')' #SWITCHOFFSET // https://learn.microsoft.com/en-us/sql/t-sql/functions/sysdatetime-transact-sql?view=sql-server-ver16 | SYSDATETIME '(' ')' #SYSDATETIME // https://learn.microsoft.com/en-us/sql/t-sql/functions/sysdatetimeoffset-transact-sql?view=sql-server-ver16 | SYSDATETIMEOFFSET '(' ')' #SYSDATETIMEOFFSET // https://learn.microsoft.com/en-us/sql/t-sql/functions/sysutcdatetime-transact-sql?view=sql-server-ver16 | SYSUTCDATETIME '(' ')' #SYSUTCDATETIME //https://learn.microsoft.com/en-us/sql/t-sql/functions/timefromparts-transact-sql?view=sql-server-ver16 | TIMEFROMPARTS '(' hour=expression ',' minute=expression ',' seconds=expression ',' fractions=expression ',' precision=DECIMAL ')' #TIMEFROMPARTS // https://learn.microsoft.com/en-us/sql/t-sql/functions/todatetimeoffset-transact-sql?view=sql-server-ver16 | TODATETIMEOFFSET '(' datetime_expression=expression ',' timezoneoffset_expression=expression ')' #TODATETIMEOFFSET // https://learn.microsoft.com/en-us/sql/t-sql/functions/year-transact-sql?view=sql-server-ver16 | YEAR '(' date=expression ')' #YEAR // https://msdn.microsoft.com/en-us/library/ms189838.aspx | IDENTITY '(' data_type (',' seed=DECIMAL)? (',' increment=DECIMAL)? ')' #IDENTITY // https://msdn.microsoft.com/en-us/library/bb839514.aspx | MIN_ACTIVE_ROWVERSION '(' ')' #MIN_ACTIVE_ROWVERSION // https://msdn.microsoft.com/en-us/library/ms177562.aspx | NULLIF '(' left=expression ',' right=expression ')' #NULLIF // https://docs.microsoft.com/en-us/sql/t-sql/functions/parse-transact-sql // https://docs.microsoft.com/en-us/sql/t-sql/functions/try-parse-transact-sql | PARSE '(' str=expression AS data_type ( USING culture=expression )? ')' #PARSE // https://docs.microsoft.com/en-us/sql/t-sql/xml/xml-data-type-methods | xml_data_type_methods #XML_DATA_TYPE_FUNC // https://docs.microsoft.com/en-us/sql/t-sql/functions/logical-functions-iif-transact-sql | IIF '(' cond=search_condition ',' left=expression ',' right=expression ')' #IIF // JSON functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/isjson-transact-sql?view=azure-sqldw-latest | ISJSON '(' json_expr=expression (',' json_type_constraint=expression)? ')' #ISJSON // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-object-transact-sql?view=azure-sqldw-latest | JSON_OBJECT '(' (key_value=json_key_value (',' key_value=json_key_value)*)? json_null_clause? ')' #JSON_OBJECT // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-array-transact-sql?view=azure-sqldw-latest | JSON_ARRAY '(' expression_list_? json_null_clause? ')' #JSON_ARRAY // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-value-transact-sql?view=azure-sqldw-latest | JSON_VALUE '(' expr=expression ',' path=expression ')' #JSON_VALUE // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-query-transact-sql?view=azure-sqldw-latest | JSON_QUERY '(' expr=expression (',' path=expression)? ')' #JSON_QUERY // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-modify-transact-sql?view=azure-sqldw-latest | JSON_MODIFY '(' expr=expression ',' path=expression ',' new_value=expression ')' #JSON_MODIFY // https://learn.microsoft.com/en-us/sql/t-sql/functions/json-path-exists-transact-sql?view=azure-sqldw-latest | JSON_PATH_EXISTS '(' value_expression=expression ',' sql_json_path=expression ')' #JSON_PATH_EXISTS // Math functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql?view=sql-server-ver16 | ABS '(' numeric_expression=expression ')' #ABS // https://learn.microsoft.com/en-us/sql/t-sql/functions/acos-transact-sql?view=sql-server-ver16 | ACOS '(' float_expression=expression ')' #ACOS // https://learn.microsoft.com/en-us/sql/t-sql/functions/asin-transact-sql?view=sql-server-ver16 | ASIN '(' float_expression=expression ')' #ASIN // https://learn.microsoft.com/en-us/sql/t-sql/functions/atan-transact-sql?view=sql-server-ver16 | ATAN '(' float_expression=expression ')' #ATAN // https://learn.microsoft.com/en-us/sql/t-sql/functions/atn2-transact-sql?view=sql-server-ver16 | ATN2 '(' float_expression=expression ',' float_expression=expression ')' #ATN2 // https://learn.microsoft.com/en-us/sql/t-sql/functions/ceiling-transact-sql?view=sql-server-ver16 | CEILING '(' numeric_expression=expression ')' #CEILING // https://learn.microsoft.com/en-us/sql/t-sql/functions/cos-transact-sql?view=sql-server-ver16 | COS '(' float_expression=expression ')' #COS // https://learn.microsoft.com/en-us/sql/t-sql/functions/cot-transact-sql?view=sql-server-ver16 | COT '(' float_expression=expression ')' #COT // https://learn.microsoft.com/en-us/sql/t-sql/functions/degrees-transact-sql?view=sql-server-ver16 | DEGREES '(' numeric_expression=expression ')' #DEGREES // https://learn.microsoft.com/en-us/sql/t-sql/functions/exp-transact-sql?view=sql-server-ver16 | EXP '(' float_expression=expression ')' #EXP // https://learn.microsoft.com/en-us/sql/t-sql/functions/floor-transact-sql?view=sql-server-ver16 | FLOOR '(' numeric_expression=expression ')' #FLOOR // https://learn.microsoft.com/en-us/sql/t-sql/functions/log-transact-sql?view=sql-server-ver16 | LOG '(' float_expression=expression (',' base=expression)? ')' #LOG // https://learn.microsoft.com/en-us/sql/t-sql/functions/log10-transact-sql?view=sql-server-ver16 | LOG10 '(' float_expression=expression ')' #LOG10 // https://learn.microsoft.com/en-us/sql/t-sql/functions/pi-transact-sql?view=sql-server-ver16 | PI '(' ')' #PI // https://learn.microsoft.com/en-us/sql/t-sql/functions/power-transact-sql?view=sql-server-ver16 | POWER '(' float_expression=expression ',' y=expression ')' #POWER // https://learn.microsoft.com/en-us/sql/t-sql/functions/radians-transact-sql?view=sql-server-ver16 | RADIANS '(' numeric_expression=expression ')' #RADIANS // https://learn.microsoft.com/en-us/sql/t-sql/functions/rand-transact-sql?view=sql-server-ver16 | RAND '(' (seed=expression)? ')' #RAND // https://learn.microsoft.com/en-us/sql/t-sql/functions/round-transact-sql?view=sql-server-ver16 | ROUND '(' numeric_expression=expression ',' length=expression (',' function=expression)? ')' #ROUND // https://learn.microsoft.com/en-us/sql/t-sql/functions/sign-transact-sql?view=sql-server-ver16 | SIGN '(' numeric_expression=expression ')' #MATH_SIGN // https://learn.microsoft.com/en-us/sql/t-sql/functions/sin-transact-sql?view=sql-server-ver16 | SIN '(' float_expression=expression ')' #SIN // https://learn.microsoft.com/en-us/sql/t-sql/functions/sqrt-transact-sql?view=sql-server-ver16 | SQRT '(' float_expression=expression ')' #SQRT // https://learn.microsoft.com/en-us/sql/t-sql/functions/square-transact-sql?view=sql-server-ver16 | SQUARE '(' float_expression=expression ')' #SQUARE // https://learn.microsoft.com/en-us/sql/t-sql/functions/tan-transact-sql?view=sql-server-ver16 | TAN '(' float_expression=expression ')' #TAN // Logical functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-greatest-transact-sql?view=azure-sqldw-latest | GREATEST '(' expression_list_ ')' #GREATEST // https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-least-transact-sql?view=azure-sqldw-latest | LEAST '(' expression_list_ ')' #LEAST // Security functions // https://learn.microsoft.com/en-us/sql/t-sql/functions/certencoded-transact-sql?view=sql-server-ver16 | CERTENCODED '(' certid=expression ')' #CERTENCODED // https://learn.microsoft.com/en-us/sql/t-sql/functions/certprivatekey-transact-sql?view=sql-server-ver16 | CERTPRIVATEKEY '(' certid=expression ',' encryption_password=expression (',' decryption_pasword=expression)? ')' #CERTPRIVATEKEY // https://msdn.microsoft.com/en-us/library/ms176050.aspx | CURRENT_USER #CURRENT_USER // https://learn.microsoft.com/en-us/sql/t-sql/functions/database-principal-id-transact-sql?view=sql-server-ver16 | DATABASE_PRINCIPAL_ID '(' (principal_name=expression)? ')' #DATABASE_PRINCIPAL_ID // https://learn.microsoft.com/en-us/sql/t-sql/functions/has-dbaccess-transact-sql?view=sql-server-ver16 | HAS_DBACCESS '(' database_name=expression ')' #HAS_DBACCESS // https://learn.microsoft.com/en-us/sql/t-sql/functions/has-perms-by-name-transact-sql?view=sql-server-ver16 | HAS_PERMS_BY_NAME '(' securable=expression ',' securable_class=expression ',' permission=expression ( ',' sub_securable=expression (',' sub_securable_class=expression )? )? ')' #HAS_PERMS_BY_NAME // https://learn.microsoft.com/en-us/sql/t-sql/functions/is-member-transact-sql?view=sql-server-ver16 | IS_MEMBER '(' group_or_role=expression ')' #IS_MEMBER // https://learn.microsoft.com/en-us/sql/t-sql/functions/is-rolemember-transact-sql?view=sql-server-ver16 | IS_ROLEMEMBER '(' role=expression ( ',' database_principal=expression )? ')' #IS_ROLEMEMBER // https://learn.microsoft.com/en-us/sql/t-sql/functions/is-srvrolemember-transact-sql?view=sql-server-ver16 | IS_SRVROLEMEMBER '(' role=expression ( ',' login=expression )? ')' #IS_SRVROLEMEMBER // https://learn.microsoft.com/en-us/sql/t-sql/functions/loginproperty-transact-sql?view=sql-server-ver16 | LOGINPROPERTY '(' login_name=expression ',' property_name=expression ')' #LOGINPROPERTY // https://learn.microsoft.com/en-us/sql/t-sql/functions/original-login-transact-sql?view=sql-server-ver16 | ORIGINAL_LOGIN '(' ')' #ORIGINAL_LOGIN // https://learn.microsoft.com/en-us/sql/t-sql/functions/permissions-transact-sql?view=sql-server-ver16 | PERMISSIONS '(' ( object_id=expression (',' column=expression)? )? ')' #PERMISSIONS // https://learn.microsoft.com/en-us/sql/t-sql/functions/pwdencrypt-transact-sql?view=sql-server-ver16 | PWDENCRYPT '(' password=expression ')' #PWDENCRYPT // https://learn.microsoft.com/en-us/sql/t-sql/functions/pwdcompare-transact-sql?view=sql-server-ver16 | PWDCOMPARE '(' clear_text_password=expression ',' password_hash=expression (',' version=expression )?')' #PWDCOMPARE // https://msdn.microsoft.com/en-us/library/ms177587.aspx | SESSION_USER #SESSION_USER // https://learn.microsoft.com/en-us/sql/t-sql/functions/sessionproperty-transact-sql?view=sql-server-ver16 | SESSIONPROPERTY '(' option_name=expression ')' #SESSIONPROPERTY // https://learn.microsoft.com/en-us/sql/t-sql/functions/suser-id-transact-sql?view=sql-server-ver16 | SUSER_ID '(' (login=expression)? ')' #SUSER_ID // https://learn.microsoft.com/en-us/sql/t-sql/functions/suser-name-transact-sql?view=sql-server-ver16 | SUSER_NAME '(' (server_user_sid=expression)? ')' #SUSER_SNAME // https://learn.microsoft.com/en-us/sql/t-sql/functions/suser-sid-transact-sql?view=sql-server-ver16 | SUSER_SID '(' (login=expression (',' param2=expression)?)? ')' #SUSER_SID // https://learn.microsoft.com/en-us/sql/t-sql/functions/suser-sname-transact-sql?view=sql-server-ver16 | SUSER_SNAME '(' (server_user_sid=expression)? ')' #SUSER_SNAME // https://msdn.microsoft.com/en-us/library/ms179930.aspx | SYSTEM_USER #SYSTEM_USER // https://learn.microsoft.com/en-us/sql/t-sql/functions/user-transact-sql?view=sql-server-ver16 | USER #USER // https://learn.microsoft.com/en-us/sql/t-sql/functions/user-id-transact-sql?view=sql-server-ver16 | USER_ID '(' (user=expression)? ')' #USER_ID // https://learn.microsoft.com/en-us/sql/t-sql/functions/user-name-transact-sql?view=sql-server-ver16 | USER_NAME '(' (id=expression)? ')' #USER_NAME ; xml_data_type_methods : value_method | query_method | exist_method | modify_method ; // https://learn.microsoft.com/en-us/sql/t-sql/functions/date-bucket-transact-sql?view=sql-server-ver16 dateparts_9 : YEAR | YEAR_ABBR | QUARTER | QUARTER_ABBR | MONTH | MONTH_ABBR | DAY | DAY_ABBR | WEEK | WEEK_ABBR | HOUR | HOUR_ABBR | MINUTE | MINUTE_ABBR | SECOND | SECOND_ABBR | MILLISECOND | MILLISECOND_ABBR ; // https://learn.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql?view=sql-server-ver16 dateparts_12 : dateparts_9 | DAYOFYEAR | DAYOFYEAR_ABBR | MICROSECOND | MICROSECOND_ABBR | NANOSECOND | NANOSECOND_ABBR ; // https://learn.microsoft.com/en-us/sql/t-sql/functions/datename-transact-sql?view=sql-server-ver16 dateparts_15 : dateparts_12 | WEEKDAY | WEEKDAY_ABBR | TZOFFSET | TZOFFSET_ABBR | ISO_WEEK | ISO_WEEK_ABBR ; // https://learn.microsoft.com/en-us/sql/t-sql/functions/datetrunc-transact-sql?view=sql-server-ver16 dateparts_datetrunc : dateparts_9 | DAYOFYEAR | DAYOFYEAR_ABBR | MICROSECOND | MICROSECOND_ABBR | ISO_WEEK | ISO_WEEK_ABBR ; value_method : (loc_id=LOCAL_ID | value_id=full_column_name | eventdata=EVENTDATA '(' ')' | query=query_method | '(' subquery ')') '.' call=value_call ; value_call : (VALUE | VALUE_SQUARE_BRACKET) '(' xquery=STRING ',' sqltype=STRING ')' ; query_method : (loc_id=LOCAL_ID | value_id=full_column_name | '(' subquery ')' ) '.' call=query_call ; query_call : (QUERY | QUERY_SQUARE_BRACKET) '(' xquery=STRING ')' ; exist_method : (loc_id=LOCAL_ID | value_id=full_column_name | '(' subquery ')') '.' call=exist_call ; exist_call : (EXIST | EXIST_SQUARE_BRACKET) '(' xquery=STRING ')' ; modify_method : (loc_id=LOCAL_ID | value_id=full_column_name | '(' subquery ')') '.' call=modify_call ; modify_call : (MODIFY | MODIFY_SQUARE_BRACKET) '(' xml_dml=STRING ')' ; hierarchyid_call : GETANCESTOR '(' n=expression ')' | GETDESCENDANT '(' child1=expression ',' child2=expression ')' | GETLEVEL '(' ')' | ISDESCENDANTOF '(' parent_=expression ')' | GETREPARENTEDVALUE '(' oldroot=expression ',' newroot=expression ')' | TOSTRING '(' ')' ; hierarchyid_static_method : HIERARCHYID DOUBLE_COLON (GETROOT '(' ')' | PARSE '(' input=expression ')') ; nodes_method : (loc_id=LOCAL_ID | value_id=full_column_name | '(' subquery ')') '.' NODES '(' xquery=STRING ')' ; switch_section : WHEN expression THEN expression ; switch_search_condition_section : WHEN search_condition THEN expression ; as_column_alias : AS? column_alias ; as_table_alias : AS? table_alias ; table_alias : id_ ; // https://msdn.microsoft.com/en-us/library/ms187373.aspx with_table_hints : WITH '(' hint+=table_hint (','? hint+=table_hint)* ')' ; deprecated_table_hint : '(' table_hint ')' ; // https://infocenter-archive.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00938.1502/html/locking/locking103.htm // https://infocenter-archive.sybase.com/help/index.jsp?topic=/com.sybase.dc32300_1250/html/sqlug/sqlug792.htm // https://infocenter-archive.sybase.com/help/index.jsp?topic=/com.sybase.dc36271_36272_36273_36274_1250/html/refman/X35229.htm // Legacy hint with no parenthesis and no WITH keyword. Actually conflicts with table alias name except for holdlock which is // a reserved keyword in this grammar. We might want a separate sybase grammar variant. sybase_legacy_hints : sybase_legacy_hint+ ; sybase_legacy_hint : HOLDLOCK | NOHOLDLOCK | READPAST | SHARED ; // For simplicity, we don't build subsets for INSERT/UPDATE/DELETE/SELECT/MERGE // which means the grammar accept slightly more than the what the specification (documentation) says. table_hint : NOEXPAND | INDEX ( '(' index_value (',' index_value)* ')' | '=' '(' index_value ')' | '=' index_value // examples in the doc include this syntax ) | FORCESEEK ( '(' index_value '(' column_name_list ')' ')' )? | FORCESCAN | HOLDLOCK | NOLOCK | NOWAIT | PAGLOCK | READCOMMITTED | READCOMMITTEDLOCK | READPAST | READUNCOMMITTED | REPEATABLEREAD | ROWLOCK | SERIALIZABLE | SNAPSHOT | SPATIAL_WINDOW_MAX_CELLS '=' DECIMAL | TABLOCK | TABLOCKX | UPDLOCK | XLOCK | KEEPIDENTITY | KEEPDEFAULTS | IGNORE_CONSTRAINTS | IGNORE_TRIGGERS ; index_value : id_ | DECIMAL ; column_alias_list : '(' alias+=column_alias (',' alias+=column_alias)* ')' ; column_alias : id_ | STRING ; table_value_constructor : VALUES '(' exps+=expression_list_ ')' (',' '(' exps+=expression_list_ ')')* ; expression_list_ : exp+=expression (',' exp+=expression)* ; // https://msdn.microsoft.com/en-us/library/ms189798.aspx ranking_windowed_function : (RANK | DENSE_RANK | ROW_NUMBER) '(' ')' over_clause | NTILE '(' expression ')' over_clause ; // https://msdn.microsoft.com/en-us/library/ms173454.aspx aggregate_windowed_function : agg_func=(AVG | MAX | MIN | SUM | STDEV | STDEVP | VAR | VARP) '(' all_distinct_expression ')' over_clause? | cnt=(COUNT | COUNT_BIG) '(' ('*' | all_distinct_expression) ')' over_clause? | CHECKSUM_AGG '(' all_distinct_expression ')' | GROUPING '(' expression ')' | GROUPING_ID '(' expression_list_ ')' ; // https://docs.microsoft.com/en-us/sql/t-sql/functions/analytic-functions-transact-sql analytic_windowed_function : (FIRST_VALUE | LAST_VALUE) '(' expression ')' over_clause | (LAG | LEAD) '(' expression (',' expression (',' expression)? )? ')' over_clause | (CUME_DIST | PERCENT_RANK) '(' ')' OVER '(' (PARTITION BY expression_list_)? order_by_clause ')' | (PERCENTILE_CONT | PERCENTILE_DISC) '(' expression ')' WITHIN GROUP '(' order_by_clause ')' OVER '(' (PARTITION BY expression_list_)? ')' ; all_distinct_expression : (ALL | DISTINCT)? expression ; // https://msdn.microsoft.com/en-us/library/ms189461.aspx over_clause : OVER '(' (PARTITION BY expression_list_)? order_by_clause? row_or_range_clause? ')' ; row_or_range_clause : (ROWS | RANGE) window_frame_extent ; window_frame_extent : window_frame_preceding | BETWEEN window_frame_bound AND window_frame_bound ; window_frame_bound : window_frame_preceding | window_frame_following ; window_frame_preceding : UNBOUNDED PRECEDING | DECIMAL PRECEDING | CURRENT ROW ; window_frame_following : UNBOUNDED FOLLOWING | DECIMAL FOLLOWING ; create_database_option : FILESTREAM ( database_filestream_option (',' database_filestream_option)* ) | DEFAULT_LANGUAGE EQUAL ( id_ | STRING ) | DEFAULT_FULLTEXT_LANGUAGE EQUAL ( id_ | STRING ) | NESTED_TRIGGERS EQUAL ( OFF | ON ) | TRANSFORM_NOISE_WORDS EQUAL ( OFF | ON ) | TWO_DIGIT_YEAR_CUTOFF EQUAL DECIMAL | DB_CHAINING ( OFF | ON ) | TRUSTWORTHY ( OFF | ON ) ; database_filestream_option : LR_BRACKET ( ( NON_TRANSACTED_ACCESS EQUAL ( OFF | READ_ONLY | FULL ) ) | ( DIRECTORY_NAME EQUAL STRING ) ) RR_BRACKET ; database_file_spec : file_group | file_spec ; file_group : FILEGROUP id_ ( CONTAINS FILESTREAM )? ( DEFAULT )? ( CONTAINS MEMORY_OPTIMIZED_DATA )? file_spec ( ',' file_spec )* ; file_spec : LR_BRACKET NAME EQUAL ( id_ | STRING ) ','? FILENAME EQUAL file = STRING ','? ( SIZE EQUAL file_size ','? )? ( MAXSIZE EQUAL (file_size | UNLIMITED )','? )? ( FILEGROWTH EQUAL file_size ','? )? RR_BRACKET ; // Primitive. entity_name : (server=id_ '.' database=id_ '.' schema=id_ '.' | database=id_ '.' (schema=id_)? '.' | schema=id_ '.')? table=id_ ; entity_name_for_azure_dw : schema=id_ | schema=id_ '.' object_name=id_ ; entity_name_for_parallel_dw : schema_database=id_ | schema=id_ '.' object_name=id_ ; full_table_name : (linkedServer=id_ '.' '.' schema=id_ '.' | server=id_ '.' database=id_ '.' schema=id_ '.' | database=id_ '.' schema=id_? '.' | schema=id_ '.')? table=id_ ; table_name : (database=id_ '.' schema=id_? '.' | schema=id_ '.')? (table=id_ | blocking_hierarchy=BLOCKING_HIERARCHY) ; simple_name : (schema=id_ '.')? name=id_ ; func_proc_name_schema : ((schema=id_) '.')? procedure=id_ ; func_proc_name_database_schema : database=id_? '.' schema=id_? '.' procedure=id_ | func_proc_name_schema ; func_proc_name_server_database_schema : server=id_? '.' database=id_? '.' schema=id_? '.' procedure=id_ | func_proc_name_database_schema ; ddl_object : full_table_name | LOCAL_ID ; full_column_name : ((DELETED | INSERTED | full_table_name) '.')? (column_name=id_ | ('$' (IDENTITY | ROWGUID))) ; column_name_list_with_order : id_ (ASC | DESC)? (',' id_ (ASC | DESC)?)* ; //For some reason, sql server allows any number of prefixes: Here, h is the column: a.b.c.d.e.f.g.h insert_column_name_list : col+=insert_column_id (',' col+=insert_column_id)* ; insert_column_id : (ignore+=id_? '.' )* id_ ; column_name_list : col+=id_ (',' col+=id_)* ; cursor_name : id_ | LOCAL_ID ; on_off : ON | OFF ; clustered : CLUSTERED | NONCLUSTERED ; null_notnull : NOT? NULL_ ; scalar_function_name : func_proc_name_server_database_schema | RIGHT | LEFT | BINARY_CHECKSUM | CHECKSUM ; begin_conversation_timer : BEGIN CONVERSATION TIMER '(' LOCAL_ID ')' TIMEOUT '=' time ';'? ; begin_conversation_dialog : BEGIN DIALOG (CONVERSATION)? dialog_handle=LOCAL_ID FROM SERVICE initiator_service_name=service_name TO SERVICE target_service_name=service_name (',' service_broker_guid=STRING)? ON CONTRACT contract_name (WITH ((RELATED_CONVERSATION | RELATED_CONVERSATION_GROUP) '=' LOCAL_ID ','?)? (LIFETIME '=' (DECIMAL | LOCAL_ID) ','?)? (ENCRYPTION '=' on_off)? )? ';'? ; contract_name : (id_ | expression) ; service_name : (id_ | expression) ; end_conversation : END CONVERSATION conversation_handle=LOCAL_ID ';'? (WITH (ERROR '=' faliure_code=(LOCAL_ID | STRING) DESCRIPTION '=' failure_text=(LOCAL_ID | STRING))? CLEANUP? )? ; waitfor_conversation : WAITFOR? '(' get_conversation ')' (','? TIMEOUT timeout=time)? ';'? ; get_conversation :GET CONVERSATION GROUP conversation_group_id=(STRING | LOCAL_ID) FROM queue=queue_id ';'? ; queue_id : (database_name=id_ '.' schema_name=id_ '.' name=id_) | id_ ; send_conversation : SEND ON CONVERSATION conversation_handle=(STRING | LOCAL_ID) MESSAGE TYPE message_type_name=expression ('(' message_body_expression=(STRING | LOCAL_ID) ')' )? ';'? ; // https://msdn.microsoft.com/en-us/library/ms187752.aspx // TODO: implement runtime check or add new tokens. data_type : scaled=(VARCHAR | NVARCHAR | BINARY_KEYWORD | VARBINARY_KEYWORD | SQUARE_BRACKET_ID) '(' MAX ')' | ext_type=id_ '(' scale=DECIMAL ',' prec=DECIMAL ')' | ext_type=id_ '(' scale=DECIMAL ')' | ext_type=id_ IDENTITY ('(' seed=DECIMAL ',' inc=DECIMAL ')')? | double_prec=DOUBLE PRECISION? | unscaled_type=id_ ; // https://msdn.microsoft.com/en-us/library/ms179899.aspx constant : STRING // string, datetime or uniqueidentifier | BINARY | '-'? (DECIMAL | REAL | FLOAT) // float or decimal | '-'? dollar='$' ('-'|'+')? (DECIMAL | FLOAT) // money | parameter ; // To reduce ambiguity, -X is considered as an application of unary operator primitive_constant : STRING // string, datetime or uniqueidentifier | BINARY | (DECIMAL | REAL | FLOAT) // float or decimal | dollar='$' ('-'|'+')? (DECIMAL | FLOAT) // money | parameter ; keyword : ABORT | ABSOLUTE | ACCENT_SENSITIVITY | ACCESS | ACTION | ACTIVATION | ACTIVE | ADD // ? | ADDRESS | AES_128 | AES_192 | AES_256 | AFFINITY | AFTER | AGGREGATE | ALGORITHM | ALL_CONSTRAINTS | ALL_ERRORMSGS | ALL_INDEXES | ALL_LEVELS | ALLOW_ENCRYPTED_VALUE_MODIFICATIONS | ALLOW_PAGE_LOCKS | ALLOW_ROW_LOCKS | ALLOW_SNAPSHOT_ISOLATION | ALLOWED | ALWAYS | ANSI_DEFAULTS | ANSI_NULL_DEFAULT | ANSI_NULL_DFLT_OFF | ANSI_NULL_DFLT_ON | ANSI_NULLS | ANSI_PADDING | ANSI_WARNINGS | APP_NAME | APPLICATION_LOG | APPLOCK_MODE | APPLOCK_TEST | APPLY | ARITHABORT | ARITHIGNORE | ASCII | ASSEMBLY | ASSEMBLYPROPERTY | AT_KEYWORD | AUDIT | AUDIT_GUID | AUTO | AUTO_CLEANUP | AUTO_CLOSE | AUTO_CREATE_STATISTICS | AUTO_DROP | AUTO_SHRINK | AUTO_UPDATE_STATISTICS | AUTO_UPDATE_STATISTICS_ASYNC | AUTOGROW_ALL_FILES | AUTOGROW_SINGLE_FILE | AVAILABILITY | AVG | BACKUP_CLONEDB | BACKUP_PRIORITY | BASE64 | BEGIN_DIALOG | BIGINT | BINARY_KEYWORD | BINARY_CHECKSUM | BINDING | BLOB_STORAGE | BROKER | BROKER_INSTANCE | BULK_LOGGED | CALLER | CAP_CPU_PERCENT | CAST | TRY_CAST | CATALOG | CATCH | CERT_ID | CERTENCODED | CERTPRIVATEKEY | CHANGE | CHANGE_RETENTION | CHANGE_TRACKING | CHAR | CHARINDEX | CHECKALLOC | CHECKCATALOG | CHECKCONSTRAINTS | CHECKDB | CHECKFILEGROUP | CHECKSUM | CHECKSUM_AGG | CHECKTABLE | CLEANTABLE | CLEANUP | CLONEDATABASE | COL_LENGTH | COL_NAME | COLLECTION | COLUMN_ENCRYPTION_KEY | COLUMN_MASTER_KEY | COLUMNPROPERTY | COLUMNS | COLUMNSTORE | COLUMNSTORE_ARCHIVE | COMMITTED | COMPATIBILITY_LEVEL | COMPRESS_ALL_ROW_GROUPS | COMPRESSION_DELAY | CONCAT | CONCAT_WS | CONCAT_NULL_YIELDS_NULL | CONTENT | CONTROL | COOKIE | COUNT | COUNT_BIG | COUNTER | CPU | CREATE_NEW | CREATION_DISPOSITION | CREDENTIAL | CRYPTOGRAPHIC | CUME_DIST | CURSOR_CLOSE_ON_COMMIT | CURSOR_DEFAULT | CURSOR_STATUS | DATA | DATA_PURITY | DATABASE_PRINCIPAL_ID | DATABASEPROPERTYEX | DATALENGTH | DATE_CORRELATION_OPTIMIZATION | DATEADD | DATEDIFF | DATENAME | DATEPART | DAYS | DB_CHAINING | DB_FAILOVER | DB_ID | DB_NAME | DBCC | DBREINDEX | DECRYPTION | DEFAULT_DOUBLE_QUOTE | DEFAULT_FULLTEXT_LANGUAGE | DEFAULT_LANGUAGE | DEFINITION | DELAY | DELAYED_DURABILITY | DELETED | DENSE_RANK | DEPENDENTS | DES | DESCRIPTION | DESX | DETERMINISTIC | DHCP | DIALOG | DIFFERENCE | DIRECTORY_NAME | DISABLE | DISABLE_BROKER | DISABLED | DOCUMENT | DROP_EXISTING | DROPCLEANBUFFERS | DYNAMIC | ELEMENTS | EMERGENCY | EMPTY | ENABLE | ENABLE_BROKER | ENCRYPTED | ENCRYPTED_VALUE | ENCRYPTION | ENCRYPTION_TYPE | ENDPOINT_URL | ERROR_BROKER_CONVERSATIONS | ESTIMATEONLY | EXCLUSIVE | EXECUTABLE | EXIST | EXIST_SQUARE_BRACKET | EXPAND | EXPIRY_DATE | EXPLICIT | EXTENDED_LOGICAL_CHECKS | FAIL_OPERATION | FAILOVER_MODE | FAILURE | FAILURE_CONDITION_LEVEL | FAST | FAST_FORWARD | FILE_ID | FILE_IDEX | FILE_NAME | FILEGROUP | FILEGROUP_ID | FILEGROUP_NAME | FILEGROUPPROPERTY | FILEGROWTH | FILENAME | FILEPATH | FILEPROPERTY | FILEPROPERTYEX | FILESTREAM | FILTER | FIRST | FIRST_VALUE | FMTONLY | FOLLOWING | FORCE | FORCE_FAILOVER_ALLOW_DATA_LOSS | FORCED | FORCEPLAN | FORCESCAN | FORMAT | FORWARD_ONLY | FREE | FULLSCAN | FULLTEXT | FULLTEXTCATALOGPROPERTY | FULLTEXTSERVICEPROPERTY | GB | GENERATED | GETDATE | GETUTCDATE | GLOBAL | GO | GREATEST | GROUP_MAX_REQUESTS | GROUPING | GROUPING_ID | HADR | HAS_DBACCESS | HAS_PERMS_BY_NAME | HASH | HEALTH_CHECK_TIMEOUT | HIDDEN_KEYWORD | HIGH | HONOR_BROKER_PRIORITY | HOURS | IDENT_CURRENT | IDENT_INCR | IDENT_SEED | IDENTITY_VALUE | IGNORE_CONSTRAINTS | IGNORE_DUP_KEY | IGNORE_NONCLUSTERED_COLUMNSTORE_INDEX | IGNORE_REPLICATED_TABLE_CACHE | IGNORE_TRIGGERS | IMMEDIATE | IMPERSONATE | IMPLICIT_TRANSACTIONS | IMPORTANCE | INCLUDE_NULL_VALUES | INCREMENTAL | INDEX_COL | INDEXKEY_PROPERTY | INDEXPROPERTY | INITIATOR | INPUT | INSENSITIVE | INSERTED | INT | IP | IS_MEMBER | IS_ROLEMEMBER | IS_SRVROLEMEMBER | ISJSON | ISOLATION | JOB | JSON | JSON_OBJECT | JSON_ARRAY | JSON_VALUE | JSON_QUERY | JSON_MODIFY | JSON_PATH_EXISTS | KB | KEEP | KEEPDEFAULTS | KEEPFIXED | KEEPIDENTITY | KEY_SOURCE | KEYS | KEYSET | LAG | LAST | LAST_VALUE | LEAD | LEAST | LEN | LEVEL | LIST | LISTENER | LISTENER_URL | LOB_COMPACTION | LOCAL | LOCATION | LOCK | LOCK_ESCALATION | LOGIN | LOGINPROPERTY | LOOP | LOW | LOWER | LTRIM | MANUAL | MARK | MASKED | MATERIALIZED | MAX | MAX_CPU_PERCENT | MAX_DOP | MAX_FILES | MAX_IOPS_PER_VOLUME | MAX_MEMORY_PERCENT | MAX_PROCESSES | MAX_QUEUE_READERS | MAX_ROLLOVER_FILES | MAXDOP | MAXRECURSION | MAXSIZE | MB | MEDIUM | MEMORY_OPTIMIZED_DATA | MESSAGE | MIN | MIN_ACTIVE_ROWVERSION | MIN_CPU_PERCENT | MIN_IOPS_PER_VOLUME | MIN_MEMORY_PERCENT | MINUTES | MIRROR_ADDRESS | MIXED_PAGE_ALLOCATION | MODE | MODIFY | MODIFY_SQUARE_BRACKET | MOVE | MULTI_USER | NAME | NCHAR | NESTED_TRIGGERS | NEW_ACCOUNT | NEW_BROKER | NEW_PASSWORD | NEWNAME | NEXT | NO | NO_INFOMSGS | NO_QUERYSTORE | NO_STATISTICS | NO_TRUNCATE | NO_WAIT | NOCOUNT | NODES | NOEXEC | NOEXPAND | NOINDEX | NOLOCK | NON_TRANSACTED_ACCESS | NORECOMPUTE | NORECOVERY | NOTIFICATIONS | NOWAIT | NTILE | NULL_DOUBLE_QUOTE | NUMANODE | NUMBER | NUMERIC_ROUNDABORT | OBJECT | OBJECT_DEFINITION | OBJECT_ID | OBJECT_NAME | OBJECT_SCHEMA_NAME | OBJECTPROPERTY | OBJECTPROPERTYEX | OFFLINE | OFFSET | OLD_ACCOUNT | ONLINE | ONLY | OPEN_EXISTING | OPENJSON | OPTIMISTIC | OPTIMIZE | OPTIMIZE_FOR_SEQUENTIAL_KEY | ORIGINAL_DB_NAME | ORIGINAL_LOGIN | OUT | OUTPUT | OVERRIDE | OWNER | OWNERSHIP | PAD_INDEX | PAGE_VERIFY | PAGECOUNT | PAGLOCK | PARAMETERIZATION | PARSENAME | PARSEONLY | PARTITION | PARTITIONS | PARTNER | PATH | PATINDEX | PAUSE | PDW_SHOWSPACEUSED | PERCENT_RANK | PERCENTILE_CONT | PERCENTILE_DISC | PERMISSIONS | PERSIST_SAMPLE_PERCENT | PHYSICAL_ONLY | POISON_MESSAGE_HANDLING | POOL | PORT | PRECEDING | PRIMARY_ROLE | PRIOR | PRIORITY | PRIORITY_LEVEL | PRIVATE | PRIVATE_KEY | PRIVILEGES | PROCCACHE | PROCEDURE_NAME | PROPERTY | PROVIDER | PROVIDER_KEY_NAME | PWDCOMPARE | PWDENCRYPT | QUERY | QUERY_SQUARE_BRACKET | QUEUE | QUEUE_DELAY | QUOTED_IDENTIFIER | QUOTENAME | RANDOMIZED | RANGE | RANK | RC2 | RC4 | RC4_128 | READ_COMMITTED_SNAPSHOT | READ_ONLY | READ_ONLY_ROUTING_LIST | READ_WRITE | READCOMMITTED | READCOMMITTEDLOCK | READONLY | READPAST | READUNCOMMITTED | READWRITE | REBUILD | RECEIVE | RECOMPILE | RECOVERY | RECURSIVE_TRIGGERS | RELATIVE | REMOTE | REMOTE_PROC_TRANSACTIONS | REMOTE_SERVICE_NAME | REMOVE | REORGANIZE | REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD | REPEATABLE | REPEATABLEREAD | REPLACE | REPLICA | REPLICATE | REQUEST_MAX_CPU_TIME_SEC | REQUEST_MAX_MEMORY_GRANT_PERCENT | REQUEST_MEMORY_GRANT_TIMEOUT_SEC | REQUIRED_SYNCHRONIZED_SECONDARIES_TO_COMMIT | RESAMPLE | RESERVE_DISK_SPACE | RESOURCE | RESOURCE_MANAGER_LOCATION | RESTRICTED_USER | RESUMABLE | RETENTION | REVERSE | ROBUST | ROOT | ROUTE | ROW | ROW_NUMBER | ROWGUID | ROWLOCK | ROWS | RTRIM | SAMPLE | SCHEMA_ID | SCHEMA_NAME | SCHEMABINDING | SCOPE_IDENTITY | SCOPED | SCROLL | SCROLL_LOCKS | SEARCH | SECONDARY | SECONDARY_ONLY | SECONDARY_ROLE | SECONDS | SECRET | SECURABLES | SECURITY | SECURITY_LOG | SEEDING_MODE | SELF | SEMI_SENSITIVE | SEND | SENT | SEQUENCE | SEQUENCE_NUMBER | SERIALIZABLE | SERVERPROPERTY | SERVICEBROKER | SESSIONPROPERTY | SESSION_TIMEOUT | SETERROR | SHARE | SHARED | SHOWCONTIG | SHOWPLAN | SHOWPLAN_ALL | SHOWPLAN_TEXT | SHOWPLAN_XML | SIGNATURE | SIMPLE | SINGLE_USER | SIZE | SMALLINT | SNAPSHOT | SORT_IN_TEMPDB | SOUNDEX | SPACE_KEYWORD | SPARSE | SPATIAL_WINDOW_MAX_CELLS | SQL_VARIANT_PROPERTY | STANDBY | START_DATE | STATIC | STATISTICS_INCREMENTAL | STATISTICS_NORECOMPUTE | STATS_DATE | STATS_STREAM | STATUS | STATUSONLY | STDEV | STDEVP | STOPLIST | STR | STRING_AGG | STRING_ESCAPE | STUFF | SUBJECT | SUBSCRIBE | SUBSCRIPTION | SUBSTRING | SUM | SUSER_ID | SUSER_NAME | SUSER_SID | SUSER_SNAME | SUSPEND | SYMMETRIC | SYNCHRONOUS_COMMIT | SYNONYM | SYSTEM | TABLERESULTS | TABLOCK | TABLOCKX | TAKE | TARGET_RECOVERY_TIME | TB | TEXTIMAGE_ON | THROW | TIES | TIME | TIMEOUT | TIMER | TINYINT | TORN_PAGE_DETECTION | TRACKING | TRANSACTION_ID | TRANSFORM_NOISE_WORDS | TRANSLATE | TRIM | TRIPLE_DES | TRIPLE_DES_3KEY | TRUSTWORTHY | TRY | TSQL | TWO_DIGIT_YEAR_CUTOFF | TYPE | TYPE_ID | TYPE_NAME | TYPE_WARNING | TYPEPROPERTY | UNBOUNDED | UNCOMMITTED | UNICODE | UNKNOWN | UNLIMITED | UNMASK | UOW | UPDLOCK | UPPER | USER_ID | USER_NAME | USING | VALID_XML | VALIDATION | VALUE | VALUE_SQUARE_BRACKET | VAR | VARBINARY_KEYWORD | VARP | VERIFY_CLONEDB | VERSION | VIEW_METADATA | VIEWS | WAIT | WELL_FORMED_XML | WITHOUT_ARRAY_WRAPPER | WORK | WORKLOAD | XLOCK | XML | XML_COMPRESSION | XMLDATA | XMLNAMESPACES | XMLSCHEMA | XSINIL | ZONE //More keywords that can also be used as IDs | ABORT_AFTER_WAIT | ABSENT | ADMINISTER | AES | ALLOW_CONNECTIONS | ALLOW_MULTIPLE_EVENT_LOSS | ALLOW_SINGLE_EVENT_LOSS | ANONYMOUS | APPEND | APPLICATION | ASYMMETRIC | ASYNCHRONOUS_COMMIT | AUTHENTICATE | AUTHENTICATION | AUTOMATED_BACKUP_PREFERENCE | AUTOMATIC | AVAILABILITY_MODE | BEFORE | BLOCK | BLOCKERS | BLOCKSIZE | BLOCKING_HIERARCHY | BUFFER | BUFFERCOUNT | CACHE | CALLED | CERTIFICATE | CHANGETABLE | CHANGES | CHECK_POLICY | CHECK_EXPIRATION | CLASSIFIER_FUNCTION | CLUSTER | COMPRESS | COMPRESSION | CONNECT | CONNECTION | CONFIGURATION | CONNECTIONPROPERTY | CONTAINMENT | CONTEXT | CONTEXT_INFO | CONTINUE_AFTER_ERROR | CONTRACT | CONTRACT_NAME | CONVERSATION | COPY_ONLY | CURRENT_REQUEST_ID | CURRENT_TRANSACTION_ID | CYCLE | DATA_COMPRESSION | DATA_SOURCE | DATABASE_MIRRORING | DATASPACE | DDL | DECOMPRESS | DEFAULT_DATABASE | DEFAULT_SCHEMA | DIAGNOSTICS | DIFFERENTIAL | DISTRIBUTION | DTC_SUPPORT | ENABLED | ENDPOINT | ERROR | ERROR_LINE | ERROR_MESSAGE | ERROR_NUMBER | ERROR_PROCEDURE | ERROR_SEVERITY | ERROR_STATE | EVENT | EVENTDATA | EVENT_RETENTION_MODE | EXECUTABLE_FILE | EXPIREDATE | EXTENSION | EXTERNAL_ACCESS | FAILOVER | FAILURECONDITIONLEVEL | FAN_IN | FILE_SNAPSHOT | FORCESEEK | FORCE_SERVICE_ALLOW_DATA_LOSS | FORMATMESSAGE | GET | GET_FILESTREAM_TRANSACTION_CONTEXT | GETANCESTOR | GETANSINULL | GETDESCENDANT | GETLEVEL | GETREPARENTEDVALUE | GETROOT | GOVERNOR | HASHED | HEALTHCHECKTIMEOUT | HEAP | HIERARCHYID | HOST_ID | HOST_NAME | IIF | IO | INCLUDE | INCREMENT | INFINITE | INIT | INSTEAD | ISDESCENDANTOF | ISNULL | ISNUMERIC | KERBEROS | KEY_PATH | KEY_STORE_PROVIDER_NAME | LANGUAGE | LIBRARY | LIFETIME | LINKED | LINUX | LISTENER_IP | LISTENER_PORT | LOCAL_SERVICE_NAME | LOG | MASK | MATCHED | MASTER | MAX_MEMORY | MAXTRANSFER | MAXVALUE | MAX_DISPATCH_LATENCY | MAX_DURATION | MAX_EVENT_SIZE | MAX_SIZE | MAX_OUTSTANDING_IO_PER_VOLUME | MEDIADESCRIPTION | MEDIANAME | MEMBER | MEMORY_PARTITION_MODE | MESSAGE_FORWARDING | MESSAGE_FORWARD_SIZE | MINVALUE | MIRROR | MUST_CHANGE | NEWID | NEWSEQUENTIALID | NOFORMAT | NOINIT | NONE | NOREWIND | NOSKIP | NOUNLOAD | NO_CHECKSUM | NO_COMPRESSION | NO_EVENT_LOSS | NOTIFICATION | NTLM | OLD_PASSWORD | ON_FAILURE | OPERATIONS | PAGE | PARAM_NODE | PARTIAL | PASSWORD | PERMISSION_SET | PER_CPU | PER_DB | PER_NODE | PERSISTED | PLATFORM | POLICY | PREDICATE | PROCESS | PROFILE | PYTHON | R | READ_WRITE_FILEGROUPS | REGENERATE | RELATED_CONVERSATION | RELATED_CONVERSATION_GROUP | REQUIRED | RESET | RESOURCES | RESTART | RESUME | RETAINDAYS | RETURNS | REWIND | ROLE | ROUND_ROBIN | ROWCOUNT_BIG | RSA_512 | RSA_1024 | RSA_2048 | RSA_3072 | RSA_4096 | SAFETY | SAFE | SCHEDULER | SCHEME | SCRIPT | SERVER | SERVICE | SERVICE_BROKER | SERVICE_NAME | SESSION | SESSION_CONTEXT | SETTINGS | SHRINKLOG | SID | SKIP_KEYWORD | SOFTNUMA | SOURCE | SPECIFICATION | SPLIT | SQL | SQLDUMPERFLAGS | SQLDUMPERPATH | SQLDUMPERTIMEOUT | STATE | STATS | START | STARTED | STARTUP_STATE | STOP | STOPPED | STOP_ON_ERROR | SUPPORTED | SWITCH | TAPE | TARGET | TCP | TOSTRING | TRACE | TRACK_CAUSALITY | TRANSFER | UNCHECKED | UNLOCK | UNSAFE | URL | USED | VERBOSELOGGING | VISIBILITY | WAIT_AT_LOW_PRIORITY | WINDOWS | WITHOUT | WITNESS | XACT_ABORT | XACT_STATE // | ABS | ACOS | ASIN | ATAN | ATN2 | CEILING | COS | COT | DEGREES | EXP | FLOOR | LOG10 | PI | POWER | RADIANS | RAND | ROUND | SIGN | SIN | SQRT | SQUARE | TAN // | CURRENT_TIMEZONE | CURRENT_TIMEZONE_ID | DATE_BUCKET | DATEDIFF_BIG | DATEFROMPARTS | DATETIME2FROMPARTS | DATETIMEFROMPARTS | DATETIMEOFFSETFROMPARTS | DATETRUNC | DAY | EOMONTH | ISDATE | MONTH | SMALLDATETIMEFROMPARTS | SWITCHOFFSET | SYSDATETIME | SYSDATETIMEOFFSET | SYSUTCDATETIME | TIMEFROMPARTS | TODATETIMEOFFSET | YEAR // | QUARTER | DAYOFYEAR | WEEK | HOUR | MINUTE | SECOND | MILLISECOND | MICROSECOND | NANOSECOND | TZOFFSET | ISO_WEEK | WEEKDAY // | YEAR_ABBR | QUARTER_ABBR | MONTH_ABBR | DAYOFYEAR_ABBR | DAY_ABBR | WEEK_ABBR | HOUR_ABBR | MINUTE_ABBR | SECOND_ABBR | MILLISECOND_ABBR | MICROSECOND_ABBR | NANOSECOND_ABBR | TZOFFSET_ABBR | ISO_WEEK_ABBR | WEEKDAY_ABBR // | SP_EXECUTESQL //Build-ins: | VARCHAR | NVARCHAR | PRECISION //For some reason this is possible to use as ID | FILESTREAM_ON ; // https://msdn.microsoft.com/en-us/library/ms175874.aspx id_ : ID | TEMP_ID | DOUBLE_QUOTE_ID | DOUBLE_QUOTE_BLANK | SQUARE_BRACKET_ID | keyword | RAW ; simple_id : ID ; id_or_string : id_ | STRING ; // https://msdn.microsoft.com/en-us/library/ms188074.aspx // Spaces are allowed for comparison operators. comparison_operator : '=' | '>' | '<' | '<' '=' | '>' '=' | '<' '>' | '!' '=' | '!' '>' | '!' '<' ; assignment_operator : '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '^=' | '|=' ; file_size : DECIMAL( KB | MB | GB | TB | '%' )? ; ================================================ FILE: superior-sqlserver-parser/src/main/kotlin/io/github/melin/superior/parser/sqlserver/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.sqlserver import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(SqlServerParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: SqlServerParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(SqlServerParser._ATN)) } } ================================================ FILE: superior-sqlserver-parser/src/main/kotlin/io/github/melin/superior/parser/sqlserver/SqlServerAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.sqlserver import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.common.UseDatabase import io.github.melin.superior.common.relational.create.CreateDatabase import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropDatabase import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerParser import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerParserBaseVisitor import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:59 上午 */ class SqlServerAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : SqlServerParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitTsql_file(ctx: SqlServerParser.Tsql_fileContext): Statement? { ctx.batch().forEach { this.visitBatch(it) } return null } override fun visitBatch(ctx: SqlServerParser.BatchContext): Statement? { ctx.sql_clauses().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSql_clauses(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() } override fun visitCreate_database(ctx: SqlServerParser.Create_databaseContext): Statement { val databaseName = CommonUtils.cleanQuote(ctx.database.text) return CreateDatabase(databaseName) } override fun visitDrop_database(ctx: SqlServerParser.Drop_databaseContext): Statement { val ifExists = ctx.IF() != null val databases = ctx.id_().map { it.text } val dropDatabase = DropDatabase(databases.first(), ifExists) dropDatabase.databaseNames.addAll(databases) return dropDatabase } override fun visitSelect_statement_standalone(ctx: SqlServerParser.Select_statement_standaloneContext): Statement { currentOptType = StatementType.SELECT if (ctx.with_expression() != null) { this.visitWith_expression(ctx.with_expression()) } super.visitSelect_statement(ctx.select_statement()) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.inputTables = inputTables return queryStmt } override fun visitDelete_statement(ctx: SqlServerParser.Delete_statementContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.delete_statement_from().ddl_object().full_table_name()) if (ctx.with_expression() != null) { this.visitWith_expression(ctx.with_expression()) } if (ctx.search_condition() != null) { super.visitSearch_condition(ctx.search_condition()) } return DeleteTable(tableId, inputTables) } override fun visitInsert_statement(ctx: SqlServerParser.Insert_statementContext): Statement { currentOptType = StatementType.INSERT val tableId = parseTableName(ctx.ddl_object().full_table_name()) if (ctx.with_expression() != null) { this.visitWith_expression(ctx.with_expression()) } this.visitInsert_statement_value(ctx.insert_statement_value()) val queryStmt = QueryStmt(inputTables) val insertTable = if (ctx.INTO() != null) InsertTable(InsertMode.INTO, queryStmt, tableId) else InsertTable(InsertMode.OVERWRITE, queryStmt, tableId) return insertTable } override fun visitUpdate_statement(ctx: SqlServerParser.Update_statementContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableName(ctx.ddl_object().full_table_name()) if (ctx.with_expression() != null) { this.visitWith_expression(ctx.with_expression()) } if (ctx.table_sources() != null) { super.visitTable_sources(ctx.table_sources()) } if (ctx.search_condition() != null) { super.visitSearch_condition(ctx.search_condition()) } return UpdateTable(tableId, inputTables) } override fun visitMerge_statement(ctx: SqlServerParser.Merge_statementContext): Statement { currentOptType = StatementType.MERGE val tableId = parseTableName(ctx.ddl_object().full_table_name()) val mergeTable = MergeTable(tableId) if (ctx.with_expression() != null) { this.visitWith_expression(ctx.with_expression()) } if (ctx.table_sources() != null) { super.visitTable_sources(ctx.table_sources()) } mergeTable.inputTables = inputTables return mergeTable } override fun visitWith_expression(ctx: SqlServerParser.With_expressionContext): Statement? { ctx.common_table_expression().forEach { cteTempTables.add(TableId(it.id_().text)) } return super.visitWith_expression(ctx) } override fun visitSelect_order_by_clause(ctx: SqlServerParser.Select_order_by_clauseContext): Statement? { if (ctx.OFFSET() != null) { offset = ctx.offset_exp.text.toInt() } if (ctx.OFFSET() != null) { limit = ctx.fetch_exp.text.toInt() } return super.visitSelect_order_by_clause(ctx) } override fun visitTable_source_item(ctx: SqlServerParser.Table_source_itemContext): Statement? { if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.CREATE_MATERIALIZED_VIEW || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.MERGE || currentOptType == StatementType.INSERT || currentOptType == StatementType.CREATE_FUNCTION ) { if (ctx.full_table_name() != null) { val tableId = parseTableName(ctx.full_table_name()) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } else { super.visitTable_source_item(ctx) } } return null } override fun visitUse_statement(ctx: SqlServerParser.Use_statementContext): Statement { return UseDatabase(ctx.database.text) } fun parseTableName(ctx: SqlServerParser.Full_table_nameContext): TableId { if (ctx.database != null) { return TableId(ctx.database.text, ctx.schema.text, ctx.table.text) } else if (ctx.schema != null) { return TableId(null, ctx.schema.text, ctx.table.text) } else { return TableId(null, null, ctx.table.text) } } } ================================================ FILE: superior-sqlserver-parser/src/main/kotlin/io/github/melin/superior/parser/sqlserver/SqlServerHelper.kt ================================================ package io.github.melin.superior.parser.sqlserver import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerLexer import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerParser import io.github.melin.superior.parser.sqlserver.antlr4.SqlServerParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 10:01 上午 */ object SqlServerHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until SqlServerLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = SqlServerLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = SqlServerAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = SqlServerAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = SqlServerParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: SqlServerParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = SqlServerLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = SqlServerParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.tsql_file()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.tsql_file()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-sqlserver-parser/src/test/kotlin/io/github/melin/superior/parser/sqlserver/SqlServerParserDdlTest.kt ================================================ package io.github.melin.superior.parser.sqlserver import io.github.melin.superior.common.relational.create.CreateDatabase import io.github.melin.superior.common.relational.drop.DropDatabase import org.junit.Assert import org.junit.Test /** Created by libinsong on 2020/6/30 11:05 上午 */ class SqlServerParserDdlTest { @Test fun createDatabaseTest() { val sql = """ USE master; GO CREATE DATABASE Sales ON ( NAME = Sales_dat, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\saledat.mdf', SIZE = 10, MAXSIZE = 50, FILEGROWTH = 5 ) LOG ON ( NAME = Sales_log, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\salelog.ldf', SIZE = 5MB, MAXSIZE = 25MB, FILEGROWTH = 5MB ) ; GO DROP DATABASE Sales, demos; GO """ .trimIndent() val statements = SqlServerHelper.parseMultiStatement(sql) val createDatabse = statements.get(1) val dropDatabase = statements.get(2) if (createDatabse is CreateDatabase) { Assert.assertEquals("Sales", createDatabse.databaseName) } else { Assert.fail() } if (dropDatabase is DropDatabase) { Assert.assertEquals("Sales", dropDatabase.databaseNames.get(0)) Assert.assertEquals(2, dropDatabase.databaseNames.size) } else { Assert.fail() } } } ================================================ FILE: superior-sqlserver-parser/src/test/kotlin/io/github/melin/superior/parser/sqlserver/SqlServerParserDmlTest.kt ================================================ package io.github.melin.superior.parser.sqlserver import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.dml.* import org.junit.Assert import org.junit.Test /** Created by libinsong on 2020/6/30 11:05 上午 */ class SqlServerParserDmlTest { @Test fun queryTest0() { val sql = """ SELECT product_name, list_price FROM production.products ORDER BY list_price, product_name OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(20, statement.offset) Assert.assertEquals(10, statement.limit) } else { Assert.fail() } } @Test fun queryTest1() { val sql = """ WITH Sales_CTE (SalesPersonID, TotalSales, SalesYear) AS ( SELECT SalesPersonID, SUM(TotalDue) AS TotalSales, YEAR(OrderDate) AS SalesYear FROM Sales.SalesOrderHeader WHERE SalesPersonID IS NOT NULL GROUP BY SalesPersonID, YEAR(OrderDate) ), Sales_Quota_CTE (BusinessEntityID, SalesQuota, SalesQuotaYear) AS ( SELECT BusinessEntityID, SUM(SalesQuota)AS SalesQuota, YEAR(QuotaDate) AS SalesQuotaYear FROM Sales.SalesPersonQuotaHistory GROUP BY BusinessEntityID, YEAR(QuotaDate) ) SELECT SalesPersonID , SalesYear , FORMAT(TotalSales,'C','en-us') AS TotalSales , SalesQuotaYear , FORMAT (SalesQuota,'C','en-us') AS SalesQuota , FORMAT (TotalSales -SalesQuota, 'C','en-us') AS Amt_Above_or_Below_Quota FROM Sales_CTE JOIN Sales_Quota_CTE ON Sales_Quota_CTE.BusinessEntityID = Sales_CTE.SalesPersonID AND Sales_CTE.SalesYear = Sales_Quota_CTE.SalesQuotaYear ORDER BY SalesPersonID, SalesYear """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } // @Test fun queryTest2() { val sql = """ DECLARE @NAME VARCHAR(20) SET @NAME='kkk' SELECT * FROM demos.dbo.tab1 WHERsE name=@NAME SELECT name FROM demos.dbo.tab1 WHERE name=@NAME """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest0() { val sql = """ DELETE Production.ProductCostHistory WHERE StandardCost BETWEEN 12.00 AND 14.00 AND EndDate IS NULL; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals(TableId("Production", "ProductCostHistory"), statement.tableId) } else { Assert.fail() } } @Test fun deleteTest1() { val sql = """ DELETE TOP (20) FROM Purchasing.PurchaseOrderDetail WHERE DueDate < '20020701'; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals(TableId("Purchasing", "PurchaseOrderDetail"), statement.tableId) } else { Assert.fail() } } @Test fun deleteTest2() { val sql = """ DELETE FROM dbo.FactInternetSales WHERE ProductKey IN ( SELECT T1.ProductKey FROM dbo.DimProduct T1 JOIN dbo.DimProductSubcategory T2 ON T1.ProductSubcategoryKey = T2.ProductSubcategoryKey WHERE T2.EnglishProductSubcategoryName = 'Road Bikes') """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals(TableId("dbo", "FactInternetSales"), statement.tableId) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun insertTest0() { val sql = """ INSERT INTO Production.UnitMeasure VALUES (N'FT2', N'Square Feet ', '20080923'), (N'Y', N'Yards', '20080923') , (N'Y3', N'Cubic Yards', '20080923'); """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(TableId("Production", "UnitMeasure"), statement.tableId) } else { Assert.fail() } } @Test fun updateTest0() { val sql = """ UPDATE Cities SET Location = CONVERT(Point, '12.3:46.2') WHERE Name = 'Anchorage'; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals(TableId("Cities"), statement.tableId) } else { Assert.fail() } } @Test fun updateTest1() { val sql = """ UPDATE HumanResources.Employee SET VacationHours = VacationHours + 8 FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee1 ORDER BY HireDate ASC) AS th WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals(TableId("HumanResources", "Employee"), statement.tableId) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("HumanResources", "Employee1"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun mergeTest0() { val sql = """ MERGE TargetProducts AS Target USING SourceProducts AS Source ON Source.ProductID = Target.ProductID WHEN NOT MATCHED BY Target THEN INSERT (ProductID,ProductName, Price) VALUES (Source.ProductID,Source.ProductName, Source.Price) WHEN MATCHED THEN UPDATE SET Target.ProductName = Source.ProductName, Target.Price = Source.Price WHEN NOT MATCHED BY Source THEN DELETE; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is MergeTable) { Assert.assertEquals(StatementType.MERGE, statement.statementType) Assert.assertEquals("TargetProducts", statement.targetTable.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("SourceProducts"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun insertTest() { val sql = """ insert into dbo.spt_fallback_dev select * from dbo.spt_fallback_usg; """ .trimIndent() val statement = SqlServerHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("spt_fallback_dev", statement.outputTables.get(0).tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) Assert.assertEquals(TableId("dbo", "spt_fallback_usg"), statement.queryStmt.inputTables.get(0)) } else { Assert.fail() } } } ================================================ FILE: superior-sqlserver-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-starrocks-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-starrocks-parser superior-starrocks-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-starrocks-parser/src/main/antlr4/io/github/melin/superior/parser/starrocks/antlr4/StarRocksLexer.g4 ================================================ // Copyright 2021-present StarRocks, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. lexer grammar StarRocksLexer; @members { private long sqlMode = io.github.melin.superior.parser.starrocks.SqlModeHelper.MODE_DEFAULT; public void setSqlMode(long newSqlMode) { sqlMode = newSqlMode; } } tokens { CONCAT } ACCESS: 'ACCESS'; ACTIVE: 'ACTIVE'; ADD: 'ADD'; ADMIN: 'ADMIN'; ADVISOR: 'ADVISOR'; AFTER: 'AFTER'; AGGREGATE: 'AGGREGATE'; ALL: 'ALL'; ALTER: 'ALTER'; ANALYZE: 'ANALYZE'; AND: 'AND'; ANTI: 'ANTI'; APPLY: 'APPLY'; ARRAY: 'ARRAY'; ARRAY_AGG: 'ARRAY_AGG'; ARRAY_AGG_DISTINCT: 'ARRAY_AGG_DISTINCT'; AS: 'AS'; ASC: 'ASC'; ASYNC: 'ASYNC'; ASSERT_ROWS: 'ASSERT_ROWS'; AUTHORS: 'AUTHORS'; AUTHENTICATION: 'AUTHENTICATION'; AUTOMATED: 'AUTOMATED'; AUTO_INCREMENT: 'AUTO_INCREMENT'; AVG: 'AVG'; AWARE: 'AWARE'; BACKEND: 'BACKEND'; BACKENDS: 'BACKENDS'; BACKUP: 'BACKUP'; BASE: 'BASE'; BASELINE: 'BASELINE'; BEGIN: 'BEGIN'; BETWEEN: 'BETWEEN'; BIGINT: 'BIGINT'; BINARY: 'BINARY'; BITMAP: 'BITMAP'; BITMAP_UNION: 'BITMAP_UNION'; BLACKHOLE: 'BLACKHOLE'; BLACKLIST: 'BLACKLIST'; BODY: 'BODY'; BOOLEAN: 'BOOLEAN'; BOTH: 'BOTH'; BRANCH: 'BRANCH'; BROKER: 'BROKER'; BUCKETS: 'BUCKETS'; BUILTIN: 'BUILTIN'; BY: 'BY'; CACHE: 'CACHE'; CANCEL: 'CANCEL'; CASE: 'CASE'; CAST: 'CAST'; CATALOG: 'CATALOG'; CATALOGS: 'CATALOGS'; CEIL: 'CEIL'; CHAIN: 'CHAIN'; CHAR: 'CHAR'; CHARACTER: 'CHARACTER'; CHARSET: 'CHARSET'; CHECK: 'CHECK'; CLEAN: 'CLEAN'; CLEAR: 'CLEAR'; CLUSTER : 'CLUSTER'; CLUSTERS : 'CLUSTERS'; CNGROUP : 'CNGROUP'; CNGROUPS : 'CNGROUPS'; COLLATE: 'COLLATE'; COLLATION: 'COLLATION'; COLUMN: 'COLUMN'; COLUMNS: 'COLUMNS'; COMMENT: 'COMMENT'; COMMIT: 'COMMIT'; COMMITTED: 'COMMITTED'; COMPACT: 'COMPACT'; COMPACTION: 'COMPACTION'; COMPUTE: 'COMPUTE'; CONFIG: 'CONFIG'; CONNECTION: 'CONNECTION'; CONSISTENT: 'CONSISTENT'; CONVERT: 'CONVERT'; COSTS: 'COSTS'; COUNT: 'COUNT'; CREATE: 'CREATE'; CROSS: 'CROSS'; CUBE: 'CUBE'; CUME_DIST: 'CUME_DIST'; CUMULATIVE: 'CUMULATIVE'; CURRENT: 'CURRENT'; CURRENT_DATE: 'CURRENT_DATE'; CURRENT_GROUP: 'CURRENT_GROUP'; CURRENT_ROLE: 'CURRENT_ROLE'; CURRENT_TIME: 'CURRENT_TIME'; CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'; CURRENT_USER: 'CURRENT_USER'; DATA: 'DATA'; DATACACHE: 'DATACACHE'; DATABASE: 'DATABASE'; DATABASES: 'DATABASES'; DATE: 'DATE'; DATETIME: 'DATETIME'; DAY: 'DAY'; DAYS: 'DAYS'; DEALLOCATE : 'DEALLOCATE'; DECIMAL: 'DECIMAL'; DECIMALV2: 'DECIMALV2'; DECIMAL32: 'DECIMAL32'; DECIMAL64: 'DECIMAL64'; DECIMAL128: 'DECIMAL128'; DECOMMISSION: 'DECOMMISSION'; DEFAULT: 'DEFAULT'; DELETE: 'DELETE'; DENSE_RANK: 'DENSE_RANK'; DEFERRED: 'DEFERRED'; DIALECT: 'DIALECT'; DICTIONARY: 'DICTIONARY'; DICTIONARY_GET: 'DICTIONARY_GET'; NTILE: 'NTILE'; DESC: 'DESC'; DESCRIBE: 'DESCRIBE'; DISABLE: 'DISABLE'; DISTINCT: 'DISTINCT'; DISTRIBUTED: 'DISTRIBUTED'; DISTRIBUTION: 'DISTRIBUTION'; DOUBLE: 'DOUBLE'; DROP: 'DROP'; DUAL: 'DUAL'; DUPLICATE: 'DUPLICATE'; DYNAMIC: 'DYNAMIC'; ELSE: 'ELSE'; ENABLE: 'ENABLE'; ENCLOSE: 'ENCLOSE'; END: 'END'; ENGINE: 'ENGINE'; ENGINES: 'ENGINES'; ERRORS: 'ERRORS'; ESCAPE: 'ESCAPE'; EVENTS: 'EVENTS'; EXCEPT: 'EXCEPT'; EXCLUDE: 'EXCLUDE'; EXECUTE: 'EXECUTE'; EXISTS: 'EXISTS'; EXPLAIN: 'EXPLAIN'; EXPORT: 'EXPORT'; EXTERNAL: 'EXTERNAL'; EXTRACT: 'EXTRACT'; EVERY: 'EVERY'; FAILPOINT: 'FAILPOINT'; FAILPOINTS: 'FAILPOINTS'; FALSE: 'FALSE'; FIELDS: 'FIELDS'; FILE: 'FILE'; FILES: 'FILES'; FILTER: 'FILTER'; FIRST: 'FIRST'; FIRST_VALUE: 'FIRST_VALUE'; FLOAT: 'FLOAT'; FLOOR: 'FLOOR'; FN: 'FN'; FOLLOWING: 'FOLLOWING'; FOLLOWER: 'FOLLOWER'; FOR: 'FOR'; FORCE: 'FORCE'; FORMAT: 'FORMAT'; FREE: 'FREE'; FROM: 'FROM'; FRONTEND: 'FRONTEND'; FRONTENDS: 'FRONTENDS'; FULL: 'FULL'; FUNCTION: 'FUNCTION'; FUNCTIONS: 'FUNCTIONS'; GLOBAL: 'GLOBAL'; GRANT: 'GRANT'; GRANTS: 'GRANTS'; GROUP: 'GROUP'; GROUPS: 'GROUPS'; GROUPING: 'GROUPING'; GROUPING_ID: 'GROUPING_ID'; GROUP_CONCAT: 'GROUP_CONCAT'; HASH: 'HASH'; HAVING: 'HAVING'; HELP: 'HELP'; HISTOGRAM: 'HISTOGRAM'; HLL: 'HLL'; HLL_UNION: 'HLL_UNION'; HOST: 'HOST'; HOUR: 'HOUR'; HOURS: 'HOURS'; HUB: 'HUB'; IDENTIFIED: 'IDENTIFIED'; IF: 'IF'; IMPERSONATE: 'IMPERSONATE'; IMMEDIATE: 'IMMEDIATE'; IGNORE: 'IGNORE'; IMAGE: 'IMAGE'; IN: 'IN'; INACTIVE: 'INACTIVE'; INCREMENTAL: 'INCREMENTAL'; INDEX: 'INDEX'; INDEXES: 'INDEXES'; INFILE: 'INFILE'; INNER: 'INNER'; INSTALL: 'INSTALL'; INSERT: 'INSERT'; INT: 'INT'; INTEGER: 'INTEGER'; INTEGRATION: 'INTEGRATION'; INTEGRATIONS: 'INTEGRATIONS'; INTERMEDIATE: 'INTERMEDIATE'; INTERSECT: 'INTERSECT'; INTERVAL: 'INTERVAL'; INTO: 'INTO'; INVOKER: 'INVOKER'; GIN: 'GIN'; OVERWRITE: 'OVERWRITE'; IS: 'IS'; ISOLATION: 'ISOLATION'; JOB: 'JOB'; JOIN: 'JOIN'; JSON: 'JSON'; KEY: 'KEY'; KEYS: 'KEYS'; KILL: 'KILL'; LABEL: 'LABEL'; LAG: 'LAG'; LARGEINT: 'LARGEINT'; LAST: 'LAST'; LAST_VALUE: 'LAST_VALUE'; LATERAL: 'LATERAL'; LEAD: 'LEAD'; LEFT: 'LEFT'; LESS: 'LESS'; LEVEL: 'LEVEL'; LIKE: 'LIKE'; LIMIT: 'LIMIT'; LIST: 'LIST'; LOAD: 'LOAD'; LOCAL: 'LOCAL'; LOCALTIME: 'LOCALTIME'; LOCALTIMESTAMP: 'LOCALTIMESTAMP'; LOCATION: 'LOCATION'; LOCATIONS: 'LOCATIONS'; LOGS: 'LOGS'; LOGICAL: 'LOGICAL'; MANUAL: 'MANUAL'; MAP: 'MAP'; MAPPING: 'MAPPING'; MAPPINGS: 'MAPPINGS'; MASKING: 'MASKING'; MATCH: 'MATCH'; MATERIALIZED: 'MATERIALIZED'; MAX: 'MAX'; MAXVALUE: 'MAXVALUE'; MERGE: 'MERGE'; MICROSECOND: 'MICROSECOND'; MILLISECOND: 'MILLISECOND'; MIN: 'MIN'; MINUTE: 'MINUTE'; MINUTES: 'MINUTES'; MINUS: 'MINUS'; META: 'META'; MOD: 'MOD'; MODE: 'MODE'; MODIFY: 'MODIFY'; MONTH: 'MONTH'; MULTIPLE: 'MULTIPLE'; NAME: 'NAME'; NAMES: 'NAMES'; NEGATIVE: 'NEGATIVE'; NGRAMBF: 'NGRAMBF'; NO: 'NO'; NODE: 'NODE'; NODES: 'NODES'; NONE: 'NONE'; NOT: 'NOT'; NULL: 'NULL'; NULLS: 'NULLS'; NUMBER: 'NUMBER'; NUMERIC: 'NUMERIC'; OBSERVER: 'OBSERVER'; OF: 'OF'; OFF: 'OFF'; OFFSET: 'OFFSET'; ON: 'ON'; ONLY: 'ONLY'; OPEN: 'OPEN'; OPERATE: 'OPERATE'; OPTIMIZE: 'OPTIMIZE'; OPTIMIZER: 'OPTIMIZER'; OPTION: 'OPTION'; OR: 'OR'; ORDER: 'ORDER'; OUTER: 'OUTER'; OUTFILE: 'OUTFILE'; OVER: 'OVER'; PARAMETER: '?'; PARTITION: 'PARTITION'; PARTITIONS: 'PARTITIONS'; PASSWORD: 'PASSWORD'; PATH: 'PATH'; PAUSE: 'PAUSE'; PENDING: 'PENDING'; PERCENT_RANK: 'PERCENT_RANK'; PERCENTILE: 'PERCENTILE'; PERCENTILE_UNION: 'PERCENTILE_UNION'; PLAN: 'PLAN'; PLUGIN: 'PLUGIN'; PLUGINS: 'PLUGINS'; PIPE: 'PIPE'; PIPES: 'PIPES'; PIVOT: 'PIVOT'; POLICY: 'POLICY'; POLICIES: 'POLICIES'; PRECEDING: 'PRECEDING'; PREDICATE: 'PREDICATE'; PREPARE: 'PREPARE'; PRIMARY: 'PRIMARY'; PRIORITY: 'PRIORITY'; PRIVILEGES: 'PRIVILEGES'; PROBABILITY: 'PROBABILITY'; PROC: 'PROC'; PROCEDURE: 'PROCEDURE'; PROCESSLIST: 'PROCESSLIST'; PROFILE: 'PROFILE'; PROFILELIST: 'PROFILELIST'; PROPERTIES: 'PROPERTIES'; PROPERTY: 'PROPERTY'; PROVIDER: 'PROVIDER'; PROVIDERS: 'PROVIDERS'; QUALIFY: 'QUALIFY'; QUARTER: 'QUARTER'; QUERY: 'QUERY'; QUERIES: 'QUERIES'; QUEUE: 'QUEUE'; QUOTA: 'QUOTA'; RANDOM: 'RANDOM'; RANGE: 'RANGE'; RANK: 'RANK'; READ: 'READ'; REASON: 'REASON'; RECOVER: 'RECOVER'; REFRESH: 'REFRESH'; REWRITE: 'REWRITE'; REGEXP: 'REGEXP'; RELEASE: 'RELEASE'; REMOVE: 'REMOVE'; RENAME: 'RENAME'; REPAIR: 'REPAIR'; REPEATABLE: 'REPEATABLE'; REPLACE: 'REPLACE'; REPLACE_IF_NOT_NULL: 'REPLACE_IF_NOT_NULL'; REPLICA: 'REPLICA'; REPOSITORY: 'REPOSITORY'; REPOSITORIES: 'REPOSITORIES'; RESOURCE: 'RESOURCE'; RESOURCES: 'RESOURCES'; RESTORE: 'RESTORE'; RESUME: 'RESUME'; RETAIN: 'RETAIN'; RETENTION: 'RETENTION'; RETURNS: 'RETURNS'; RETRY: 'RETRY'; REVOKE: 'REVOKE'; REVERT: 'REVERT'; RIGHT: 'RIGHT'; RLIKE: 'RLIKE'; ROLE: 'ROLE'; ROLES: 'ROLES'; ROLLBACK: 'ROLLBACK'; ROLLUP: 'ROLLUP'; ROUTINE: 'ROUTINE'; ROW: 'ROW'; ROWS: 'ROWS'; ROW_NUMBER: 'ROW_NUMBER'; RULE: 'RULE'; RULES: 'RULES'; RUNNING: 'RUNNING'; SAMPLE: 'SAMPLE'; SCHEDULE: 'SCHEDULE'; SCHEDULER: 'SCHEDULER'; SCHEMA: 'SCHEMA'; SCHEMAS: 'SCHEMAS'; SECOND: 'SECOND'; SECURITY: 'SECURITY'; SELECT: 'SELECT'; SEMI: 'SEMI'; SEPARATOR: 'SEPARATOR'; SERIALIZABLE: 'SERIALIZABLE'; SESSION: 'SESSION'; SET: 'SET'; SETS: 'SETS'; SET_VAR: 'SET_VAR'; SIGNED: 'SIGNED'; SKIP_HEADER: 'SKIP_HEADER'; SHOW: 'SHOW'; SMALLINT: 'SMALLINT'; SNAPSHOT: 'SNAPSHOT'; SNAPSHOTS: 'SNAPSHOTS'; SQLBLACKLIST: 'SQLBLACKLIST'; STARROCKS: 'STARROCKS'; START: 'START'; STATS: 'STATS'; STATUS: 'STATUS'; STOP: 'STOP'; STORAGE: 'STORAGE'; STREAM: 'STREAM'; STRING: 'STRING'; TEXT: 'TEXT'; SUBMIT: 'SUBMIT'; SUM: 'SUM'; SUSPEND: 'SUSPEND'; SYNC: 'SYNC'; SYSTEM: 'SYSTEM'; SYSTEM_TIME: 'SYSTEM_TIME'; SWAP: 'SWAP'; STRUCT: 'STRUCT'; TABLE: 'TABLE'; TABLES: 'TABLES'; TABLET: 'TABLET'; TABLETS: 'TABLETS'; TAG: 'TAG'; TASK: 'TASK'; TEMPORARY: 'TEMPORARY'; TERMINATED: 'TERMINATED'; THAN: 'THAN'; THEN: 'THEN'; TIME: 'TIME'; TIMES: 'TIMES'; TIMESTAMP: 'TIMESTAMP'; TIMESTAMPADD: 'TIMESTAMPADD'; TIMESTAMPDIFF: 'TIMESTAMPDIFF'; TINYINT: 'TINYINT'; TRANSACTION: 'TRANSACTION'; TRANSLATE: 'TRANSLATE'; TO: 'TO'; TRACE: 'TRACE'; TRIGGERS: 'TRIGGERS'; TRIM_SPACE: 'TRIM_SPACE'; TRUE: 'TRUE'; TRUNCATE: 'TRUNCATE'; TYPE: 'TYPE'; TYPES: 'TYPES'; UNBOUNDED: 'UNBOUNDED'; UNCOMMITTED: 'UNCOMMITTED'; UNION: 'UNION'; UNIQUE: 'UNIQUE'; UNINSTALL: 'UNINSTALL'; UNSET: 'UNSET'; UNSIGNED: 'UNSIGNED'; UPDATE: 'UPDATE'; USAGE: 'USAGE'; USE: 'USE'; USER: 'USER'; USERS: 'USERS'; USING: 'USING'; VALUE: 'VALUE'; VALUES: 'VALUES'; VARBINARY: 'VARBINARY'; VARCHAR: 'VARCHAR'; VARIABLES: 'VARIABLES'; VECTOR: 'VECTOR'; VERBOSE: 'VERBOSE'; VERSION: 'VERSION'; VIEW: 'VIEW'; VIEWS: 'VIEWS'; VOLUME: 'VOLUME'; VOLUMES: 'VOLUMES'; WAREHOUSE: 'WAREHOUSE'; WAREHOUSES: 'WAREHOUSES'; WARNINGS: 'WARNINGS'; WEEK: 'WEEK'; WHEN: 'WHEN'; WHERE: 'WHERE'; WHITELIST: 'WHITELIST'; WITH: 'WITH'; WORK: 'WORK'; WRITE: 'WRITE'; YEAR: 'YEAR'; LOCK: 'LOCK'; UNLOCK: 'UNLOCK'; LOW_PRIORITY: 'LOW_PRIORITY'; DISK: 'DISK'; BEFORE: 'BEFORE'; DOUBLE_DOLLAR: '$$'; FIELD: 'FIELD'; PERSISTENT: 'PERSISTENT'; EQ : '='; NEQ : '<>' | '!='; LT : '<'; LTE : '<='; GT : '>'; GTE : '>='; EQ_FOR_NULL: '<=>'; ARRAY_ELEMENT: '[*]'; PLUS_SYMBOL: '+'; MINUS_SYMBOL: '-'; ASTERISK_SYMBOL: '*'; SLASH_SYMBOL: '/'; PERCENT_SYMBOL: '%'; LOGICAL_OR: '||' {setType((sqlMode & io.github.melin.superior.parser.starrocks.SqlModeHelper.MODE_PIPES_AS_CONCAT) == 0 ? LOGICAL_OR : StarRocksParser.CONCAT);}; LOGICAL_AND: '&&'; LOGICAL_NOT: '!'; INT_DIV: 'DIV'; BITAND: '&'; BITOR: '|'; BITXOR: '^'; BITNOT: '~'; BIT_SHIFT_LEFT: 'BITSHIFTLEFT'; BIT_SHIFT_RIGHT: 'BITSHIFTRIGHT'; BIT_SHIFT_RIGHT_LOGICAL: 'BITSHIFTRIGHTLOGICAL'; ARROW: '->'; FAT_ARROW : '=>'; AT: '@'; INTEGER_VALUE : DIGIT+ ; DECIMAL_VALUE : DIGIT+ '.' DIGIT* | '.' DIGIT+ ; DOUBLE_VALUE : DIGIT+ ('.' DIGIT*)? EXPONENT | '.' DIGIT+ EXPONENT ; SINGLE_QUOTED_TEXT : '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\'' ; DOUBLE_QUOTED_TEXT : '"' ('\\'. | '""' | ~('"'| '\\'))* '"' ; BINARY_SINGLE_QUOTED_TEXT : 'X\'' (~('\'' | '\\'))* '\'' ; BINARY_DOUBLE_QUOTED_TEXT : 'X"' (~('"'| '\\'))* '"' ; LETTER_IDENTIFIER : (LETTER | '_') (LETTER | DIGIT | '_')* ; DIGIT_IDENTIFIER : DIGIT (LETTER | DIGIT | '_')+ ; BACKQUOTED_IDENTIFIER : '`' ( ~'`' | '``' )* '`' ; // Prevent recognize string: .123somelatin AS ((.123), DECIMAL_LITERAL), ((somelatin), IDENTIFIER) // it must recoginze: .123somelatin AS ((.), DOT), (123somelatin, IDENTIFIER) DOT_IDENTIFIER : '.' DIGIT_IDENTIFIER ; fragment EXPONENT : 'E' [+-]? DIGIT+ ; fragment DIGIT : [0-9] ; fragment LETTER : [a-zA-Z_$\u0080-\uffff] ; SIMPLE_COMMENT : '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) ; BRACKETED_COMMENT : '/*'([ \r\n\t\u3000]* | ~'+' .*?) '*/' -> channel(HIDDEN) ; OPTIMIZER_HINT : '/*+' .*? '*/' -> channel(2) ; SEMICOLON: ';'; COLON: ':'; LEFT_PAREN: '('; RIGHT_PAREN: ')'; COMMA: ','; DOT: '.'; LEFT_BRACKET: '['; RIGHT_BRACKET: ']'; LEFT_BRACE: '{'; RIGHT_BRACE: '}'; DOTDOTDOT: '...'; WS : [ \r\n\t\u3000]+ -> channel(HIDDEN) ; ATTACHMENT : DOUBLE_DOLLAR .*? DOUBLE_DOLLAR ; ================================================ FILE: superior-starrocks-parser/src/main/antlr4/io/github/melin/superior/parser/starrocks/antlr4/StarRocksParser.g4 ================================================ // Copyright 2021-present StarRocks, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. parser grammar StarRocksParser; options { tokenVocab = StarRocksLexer; } sqlStatements : singleStatement* EOF ; singleStatement : statement SEMICOLON? ; statement // Query Statement : queryStatement // Database Statement | useDatabaseStatement | useCatalogStatement | setCatalogStatement | showDatabasesStatement | alterDbQuotaStatement | createDbStatement | dropDbStatement | showCreateDbStatement | alterDatabaseRenameStatement | recoverDbStmt | showDataStmt | showDataDistributionStmt // Table Statement | createTableStatement | createTableAsSelectStatement | createTableLikeStatement | showCreateTableStatement | dropTableStatement | cleanTemporaryTableStatement | recoverTableStatement | truncateTableStatement | showTableStatement | descTableStatement | showTableStatusStatement | showColumnStatement | refreshTableStatement | alterTableStatement | cancelAlterTableStatement | showAlterStatement | showTemporaryTablesStatement // View Statement | createViewStatement | alterViewStatement | dropViewStatement // Partition Statement | showPartitionsStatement | recoverPartitionStatement // Index Statement | createIndexStatement | dropIndexStatement | showIndexStatement // Task Statement | submitTaskStatement | dropTaskStatement // Materialized View Statement | createMaterializedViewStatement | showMaterializedViewsStatement | dropMaterializedViewStatement | alterMaterializedViewStatement | refreshMaterializedViewStatement | cancelRefreshMaterializedViewStatement // Catalog Statement | createExternalCatalogStatement | dropExternalCatalogStatement | showCatalogsStatement | showCreateExternalCatalogStatement | alterCatalogStatement // DML Statement | insertStatement | updateStatement | deleteStatement // Routine Statement | createRoutineLoadStatement | alterRoutineLoadStatement | stopRoutineLoadStatement | resumeRoutineLoadStatement | pauseRoutineLoadStatement | showRoutineLoadStatement | showRoutineLoadTaskStatement | showCreateRoutineLoadStatement // StreamLoad Statement | showStreamLoadStatement // Admin Statement | adminSetConfigStatement | adminSetReplicaStatusStatement | adminShowConfigStatement | adminShowReplicaDistributionStatement | adminShowReplicaStatusStatement | adminRepairTableStatement | adminCancelRepairTableStatement | adminCheckTabletsStatement | adminSetPartitionVersion | killStatement | syncStatement | executeScriptStatement | adminSetAutomatedSnapshotOnStatement | adminSetAutomatedSnapshotOffStatement // Cluster Management Statement | alterSystemStatement | cancelAlterSystemStatement | showComputeNodesStatement // Analyze Statement | analyzeStatement | dropStatsStatement | createAnalyzeStatement | dropAnalyzeJobStatement | analyzeHistogramStatement | dropHistogramStatement | showAnalyzeStatement | showStatsMetaStatement | showHistogramMetaStatement | killAnalyzeStatement // Profile Statement | analyzeProfileStatement // Resource Group Statement | createResourceGroupStatement | dropResourceGroupStatement | alterResourceGroupStatement | showResourceGroupStatement | showResourceGroupUsageStatement // External Resource Statement | createResourceStatement | alterResourceStatement | dropResourceStatement | showResourceStatement // UDF Statement | showFunctionsStatement | dropFunctionStatement | createFunctionStatement // Load Statement | loadStatement | showLoadStatement | showLoadWarningsStatement | cancelLoadStatement | alterLoadStatement // Show Statement | showAuthorStatement | showBackendsStatement | showBrokerStatement | showCharsetStatement | showCollationStatement | showDeleteStatement | showDynamicPartitionStatement | showEventsStatement | showEnginesStatement | showFrontendsStatement | showPluginsStatement | showRepositoriesStatement | showOpenTableStatement | showPrivilegesStatement | showProcedureStatement | showProcStatement | showProcesslistStatement | showProfilelistStatement | showRunningQueriesStatement | showStatusStatement | showTabletStatement | showTransactionStatement | showTriggersStatement | showUserPropertyStatement | showVariablesStatement | showWarningStatement | helpStatement // authz Statement | createUserStatement | dropUserStatement | alterUserStatement | showUserStatement | showAuthenticationStatement | executeAsStatement | createRoleStatement | alterRoleStatement | dropRoleStatement | showRolesStatement | grantRoleStatement | revokeRoleStatement | setRoleStatement | setDefaultRoleStatement | grantPrivilegeStatement | revokePrivilegeStatement | showGrantsStatement // Security Integration Statement | createSecurityIntegrationStatement | alterSecurityIntegrationStatement | dropSecurityIntegrationStatement | showSecurityIntegrationStatement | showCreateSecurityIntegrationStatement // Group Provider Statement | createGroupProviderStatement | dropGroupProviderStatement | showGroupProvidersStatement | showCreateGroupProviderStatement // Backup Restore Statement | backupStatement | cancelBackupStatement | showBackupStatement | restoreStatement | cancelRestoreStatement | showRestoreStatement | showSnapshotStatement | createRepositoryStatement | dropRepositoryStatement // Sql BlackList And WhiteList Statement | addSqlBlackListStatement | delSqlBlackListStatement | showSqlBlackListStatement | showWhiteListStatement // Backend BlackList | addBackendBlackListStatement | delBackendBlackListStatement | showBackendBlackListStatement // Data Cache management statement | createDataCacheRuleStatement | showDataCacheRulesStatement | dropDataCacheRuleStatement | clearDataCacheRulesStatement | dataCacheSelectStatement // Export Statement | exportStatement | cancelExportStatement | showExportStatement // Plugin Statement | installPluginStatement | uninstallPluginStatement // File Statement | createFileStatement | dropFileStatement | showSmallFilesStatement // Set Statement | setStatement | setUserPropertyStatement // Storage Volume Statement | createStorageVolumeStatement | alterStorageVolumeStatement | dropStorageVolumeStatement | showStorageVolumesStatement | descStorageVolumeStatement | setDefaultStorageVolumeStatement // Pipe Statement | createPipeStatement | dropPipeStatement | alterPipeStatement | showPipeStatement | descPipeStatement // Compaction Statement | cancelCompactionStatement // FailPoint Statement | updateFailPointStatusStatement | showFailPointStatement // prepare_stmt | prepareStatement | executeStatement | deallocateStatement // Dictionary Statement | createDictionaryStatement | dropDictionaryStatement | refreshDictionaryStatement | showDictionaryStatement | cancelRefreshDictionaryStatement // Plan advisor statement | alterPlanAdvisorAddStatement | truncatePlanAdvisorStatement | alterPlanAdvisorDropStatement | showPlanAdvisorStatement // Warehouse Statement | createWarehouseStatement | dropWarehouseStatement | suspendWarehouseStatement | resumeWarehouseStatement | setWarehouseStatement | showWarehousesStatement | showClustersStatement | showNodesStatement | alterWarehouseStatement // CNGroup Statement | createCNGroupStatement | dropCNGroupStatement | enableCNGroupStatement | disableCNGroupStatement | alterCNGroupStatement // Transaction Statement | beginStatement | commitStatement | rollbackStatement // Translate Statement | translateStatement // SQL Plan Management Statement | createBaselinePlanStatement | dropBaselinePlanStatement | showBaselinePlanStatement | disableBaselinePlanStatement | enableBaselinePlanStatement // Unsupported Statement | unsupportedStatement ; // ---------------------------------------- DataBase Statement --------------------------------------------------------- useDatabaseStatement : USE qualifiedName ; useCatalogStatement : USE string ; setCatalogStatement : SET CATALOG identifierOrString ; showDatabasesStatement : SHOW DATABASES ((FROM | IN) catalog=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? | SHOW SCHEMAS ((LIKE pattern=string) | (WHERE expression))? ; alterDbQuotaStatement : ALTER DATABASE identifier SET DATA QUOTA identifier | ALTER DATABASE identifier SET REPLICA QUOTA INTEGER_VALUE ; createDbStatement : CREATE (DATABASE | SCHEMA) (IF NOT EXISTS)? (catalog=identifier DOT)? database=qualifiedName charsetDesc? collateDesc? properties? ; dropDbStatement : DROP (DATABASE | SCHEMA) (IF EXISTS)? (catalog=identifier DOT)? database=qualifiedName FORCE? ; showCreateDbStatement : SHOW CREATE (DATABASE | SCHEMA) identifier ; alterDatabaseRenameStatement : ALTER DATABASE identifier RENAME identifier ; recoverDbStmt : RECOVER (DATABASE | SCHEMA) identifier ; showDataStmt : SHOW DATA | SHOW DATA FROM qualifiedName ; showDataDistributionStmt : SHOW DATA DISTRIBUTION FROM qualifiedName partitionNames? ; // ------------------------------------------- Table Statement --------------------------------------------------------- createTableStatement : CREATE (TEMPORARY | EXTERNAL)? TABLE (IF NOT EXISTS)? qualifiedName LEFT_PAREN columnDesc (COMMA columnDesc)* (COMMA indexDesc)* RIGHT_PAREN engineDesc? charsetDesc? keyDesc? comment? partitionDesc? distributionDesc? orderByDesc? rollupDesc? properties? extProperties? ; columnDesc : identifier type? charsetName? KEY? aggDesc? columnNullable? (defaultDesc | AUTO_INCREMENT | generatedColumnDesc)? comment? ; charsetName : CHAR SET identifier | CHARSET identifier | CHARACTER SET identifier ; defaultDesc : DEFAULT (string | NULL | CURRENT_TIMESTAMP (LEFT_PAREN (INTEGER_VALUE)? RIGHT_PAREN)? | LEFT_PAREN qualifiedName LEFT_PAREN RIGHT_PAREN RIGHT_PAREN) ; generatedColumnDesc : AS expression ; indexDesc : INDEX indexName=identifier identifierList (indexType propertyList?)? comment? ; engineDesc : ENGINE EQ identifier ; charsetDesc : DEFAULT? (CHAR SET | CHARSET | CHARACTER SET) EQ? identifierOrString ; collateDesc : DEFAULT? COLLATE EQ? identifierOrString ; keyDesc : (AGGREGATE | UNIQUE | PRIMARY | DUPLICATE) KEY identifierList ; orderByDesc : ORDER BY identifierList ; columnNullable : NULL | NOT NULL ; typeWithNullable : type columnNullable? ; aggStateDesc : identifier LEFT_PAREN typeWithNullable (COMMA typeWithNullable)* RIGHT_PAREN ; aggDesc : SUM | MAX | MIN | REPLACE | HLL_UNION | BITMAP_UNION | PERCENTILE_UNION | REPLACE_IF_NOT_NULL | aggStateDesc ; rollupDesc : ROLLUP LEFT_PAREN rollupItem (COMMA rollupItem)* RIGHT_PAREN ; rollupItem : rollupName=identifier identifierList (dupKeys)? (fromRollup)? properties? ; dupKeys : DUPLICATE KEY identifierList ; fromRollup : FROM identifier ; orReplace: (OR REPLACE)? ; ifNotExists: (IF NOT EXISTS)? ; createTableAsSelectStatement : CREATE TEMPORARY? TABLE (IF NOT EXISTS)? qualifiedName (LEFT_PAREN (identifier (COMMA identifier)* (COMMA indexDesc)* | indexDesc (COMMA indexDesc)*) RIGHT_PAREN)? keyDesc? comment? partitionDesc? distributionDesc? orderByDesc? properties? AS queryStatement ; dropTableStatement : DROP TEMPORARY? TABLE (IF EXISTS)? qualifiedName FORCE? ; cleanTemporaryTableStatement : CLEAN TEMPORARY TABLE ON SESSION string ; alterTableStatement : ALTER TABLE qualifiedName alterClause (COMMA alterClause)* | ALTER TABLE qualifiedName ADD ROLLUP rollupItem (COMMA rollupItem)* | ALTER TABLE qualifiedName DROP ROLLUP identifier (COMMA identifier)* ; createIndexStatement : CREATE INDEX indexName=identifier ON qualifiedName identifierList (indexType propertyList?)? comment? ; dropIndexStatement : DROP INDEX indexName=identifier ON qualifiedName ; indexType : USING (BITMAP | GIN | NGRAMBF | VECTOR) ; showTableStatement : SHOW FULL? TABLES ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showTemporaryTablesStatement : SHOW TEMPORARY TABLES ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showCreateTableStatement : SHOW CREATE (TABLE | VIEW | MATERIALIZED VIEW) table=qualifiedName ; showColumnStatement : SHOW FULL? (COLUMNS | FIELDS) ((FROM | IN) table=qualifiedName) ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showTableStatusStatement : SHOW TABLE STATUS ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; refreshTableStatement : REFRESH EXTERNAL TABLE qualifiedName (PARTITION LEFT_PAREN string (COMMA string)* RIGHT_PAREN)? ; showAlterStatement : SHOW ALTER TABLE (COLUMN | ROLLUP | OPTIMIZE) ((FROM | IN) db=qualifiedName)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? | SHOW ALTER MATERIALIZED VIEW ((FROM | IN) db=qualifiedName)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; descTableStatement : (DESC | DESCRIBE) ((table=qualifiedName ALL?) | (FILES propertyList)) ; createTableLikeStatement : CREATE (TEMPORARY | EXTERNAL)? TABLE (IF NOT EXISTS)? qualifiedName partitionDesc? distributionDesc? properties? LIKE qualifiedName ; showIndexStatement : SHOW (INDEX | INDEXES | KEY | KEYS) ((FROM | IN) table=qualifiedName) ((FROM | IN) db=qualifiedName)? ; recoverTableStatement : RECOVER TABLE qualifiedName ; truncateTableStatement : TRUNCATE TABLE qualifiedName partitionNames? ; cancelAlterTableStatement : CANCEL ALTER TABLE (COLUMN | ROLLUP | OPTIMIZE)? FROM qualifiedName (LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN)? | CANCEL ALTER MATERIALIZED VIEW FROM qualifiedName ; showPartitionsStatement : SHOW TEMPORARY? PARTITIONS FROM table=qualifiedName (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; recoverPartitionStatement : RECOVER PARTITION identifier FROM table=qualifiedName ; // ------------------------------------------- View Statement ---------------------------------------------------------- createViewStatement : CREATE (OR REPLACE)? VIEW (IF NOT EXISTS)? qualifiedName (LEFT_PAREN columnNameWithComment (COMMA columnNameWithComment)* RIGHT_PAREN)? comment? (SECURITY (NONE | INVOKER))? AS queryStatement ; alterViewStatement : ALTER VIEW qualifiedName (LEFT_PAREN columnNameWithComment (COMMA columnNameWithComment)* RIGHT_PAREN)? AS queryStatement | ALTER VIEW qualifiedName SET SECURITY (NONE | INVOKER) | ALTER VIEW qualifiedName SET properties | ALTER VIEW qualifiedName (ADD | MODIFY) DIALECT (STARROCKS)? queryStatement ; dropViewStatement : DROP VIEW (IF EXISTS)? qualifiedName ; columnNameWithComment : columnName=identifier comment? ; // ------------------------------------------- Task Statement ---------------------------------------------------------- submitTaskStatement : SUBMIT TASK qualifiedName? taskClause* AS (createTableAsSelectStatement | insertStatement | dataCacheSelectStatement) ; taskClause : properties | taskScheduleDesc ; dropTaskStatement : DROP TASK qualifiedName FORCE? ; taskScheduleDesc : SCHEDULE (START LEFT_PAREN string RIGHT_PAREN)? EVERY LEFT_PAREN taskInterval RIGHT_PAREN ; // ------------------------------------------- Materialized View Statement --------------------------------------------- createMaterializedViewStatement : CREATE MATERIALIZED VIEW (IF NOT EXISTS)? mvName=qualifiedName (LEFT_PAREN columnNameWithComment (COMMA columnNameWithComment)* (COMMA indexDesc)* RIGHT_PAREN)? comment? materializedViewDesc* AS queryStatement ; mvPartitionExprs: primaryExpression | LEFT_PAREN primaryExpression (COMMA primaryExpression)* RIGHT_PAREN ; materializedViewDesc : (PARTITION BY mvPartitionExprs) | distributionDesc | orderByDesc | refreshSchemeDesc | properties ; showMaterializedViewsStatement : SHOW MATERIALIZED VIEWS ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; dropMaterializedViewStatement : DROP MATERIALIZED VIEW (IF EXISTS)? mvName=qualifiedName ; alterMaterializedViewStatement : ALTER MATERIALIZED VIEW mvName=qualifiedName ( refreshSchemeDesc | tableRenameClause | modifyPropertiesClause | swapTableClause ) | ALTER MATERIALIZED VIEW mvName=qualifiedName statusDesc ; refreshMaterializedViewStatement : REFRESH MATERIALIZED VIEW mvName=qualifiedName (PARTITION (partitionRangeDesc | listPartitionValues))? FORCE? (WITH (SYNC | ASYNC) MODE)? (WITH PRIORITY priority=INTEGER_VALUE)? ; cancelRefreshMaterializedViewStatement : CANCEL REFRESH MATERIALIZED VIEW mvName=qualifiedName FORCE? ; // ------------------------------------------- Admin Statement --------------------------------------------------------- adminSetConfigStatement : ADMIN SET FRONTEND CONFIG LEFT_PAREN property RIGHT_PAREN (WITH PERSISTENT)? ; adminSetReplicaStatusStatement : ADMIN SET REPLICA STATUS properties ; adminShowConfigStatement : ADMIN SHOW FRONTEND CONFIG (LIKE pattern=string)? ; adminShowReplicaDistributionStatement : ADMIN SHOW REPLICA DISTRIBUTION FROM qualifiedName partitionNames? ; adminShowReplicaStatusStatement : ADMIN SHOW REPLICA STATUS FROM qualifiedName partitionNames? (WHERE where=expression)? ; adminRepairTableStatement : ADMIN REPAIR TABLE qualifiedName partitionNames? ; adminCancelRepairTableStatement : ADMIN CANCEL REPAIR TABLE qualifiedName partitionNames? ; adminCheckTabletsStatement : ADMIN CHECK tabletList PROPERTIES LEFT_PARENpropertyRIGHT_PAREN ; adminSetPartitionVersion : ADMIN SET TABLE qualifiedName PARTITION LEFT_PAREN(partitionName=identifierOrString | partitionId=INTEGER_VALUE)RIGHT_PAREN VERSION TO version=INTEGER_VALUE ; killStatement : KILL (CONNECTION? | QUERY) (connId=INTEGER_VALUE | queryId=string) ; syncStatement : SYNC ; adminSetAutomatedSnapshotOnStatement : ADMIN SET AUTOMATED CLUSTER SNAPSHOT ON (STORAGE VOLUME svName=identifier)? ; adminSetAutomatedSnapshotOffStatement : ADMIN SET AUTOMATED CLUSTER SNAPSHOT OFF ; // ------------------------------------------- Cluster Management Statement --------------------------------------------- alterSystemStatement : ALTER SYSTEM alterClause ; cancelAlterSystemStatement : CANCEL DECOMMISSION BACKEND string (COMMA string)* ; showComputeNodesStatement : SHOW COMPUTE NODES ; // ------------------------------------------- Catalog Statement ------------------------------------------------------- createExternalCatalogStatement : CREATE EXTERNAL CATALOG (IF NOT EXISTS)? catalogName=identifierOrString comment? properties ; showCreateExternalCatalogStatement : SHOW CREATE CATALOG catalogName=identifierOrString ; dropExternalCatalogStatement : DROP CATALOG (IF EXISTS)? catalogName=identifierOrString ; showCatalogsStatement : SHOW CATALOGS (LIKE pattern=string)? ; alterCatalogStatement : ALTER CATALOG catalogName=identifierOrString modifyPropertiesClause ; // ---------------------------------------- Storage Volume Statement --------------------------------------------------- createStorageVolumeStatement : CREATE STORAGE VOLUME (IF NOT EXISTS)? storageVolumeName=identifierOrString typeDesc locationsDesc comment? properties? ; typeDesc : TYPE EQ identifier ; locationsDesc : LOCATIONS EQ stringList ; showStorageVolumesStatement : SHOW STORAGE VOLUMES (LIKE pattern=string)? ; dropStorageVolumeStatement : DROP STORAGE VOLUME (IF EXISTS)? storageVolumeName=identifierOrString ; alterStorageVolumeStatement : ALTER STORAGE VOLUME identifierOrString alterStorageVolumeClause (COMMA alterStorageVolumeClause)* ; alterStorageVolumeClause : modifyStorageVolumeCommentClause | modifyStorageVolumePropertiesClause ; modifyStorageVolumePropertiesClause : SET propertyList ; modifyStorageVolumeCommentClause : COMMENT '=' string ; descStorageVolumeStatement : (DESC | DESCRIBE) STORAGE VOLUME identifierOrString ; setDefaultStorageVolumeStatement : SET identifierOrString AS DEFAULT STORAGE VOLUME ; // ------------------------------------------- FailPoint Statement ----------------------------------------------------- updateFailPointStatusStatement : ADMIN (DISABLE | ENABLE) FAILPOINT string (WITH (times=INTEGER_VALUE TIMES | prob=DECIMAL_VALUE PROBABILITY))? (ON (BACKEND string | FRONTEND))? ; showFailPointStatement : SHOW FAILPOINTS ((LIKE pattern=string))? (ON BACKEND string)? ; // ------------------------------------------- Dictionary Statement ----------------------------------------------------- createDictionaryStatement : CREATE DICTIONARY dictionaryName USING qualifiedName LEFT_PAREN dictionaryColumnDesc (COMMA dictionaryColumnDesc)* RIGHT_PAREN properties? ; dropDictionaryStatement : DROP DICTIONARY qualifiedName CACHE? ; refreshDictionaryStatement : REFRESH DICTIONARY qualifiedName ; showDictionaryStatement : SHOW DICTIONARY qualifiedName? ; cancelRefreshDictionaryStatement : CANCEL REFRESH DICTIONARY qualifiedName; dictionaryColumnDesc : qualifiedName KEY | qualifiedName VALUE ; dictionaryName : qualifiedName ; // ------------------------------------------- Alter Clause ------------------------------------------------------------ alterClause //Alter system clause : addFrontendClause | dropFrontendClause | modifyFrontendHostClause | addBackendClause | dropBackendClause | decommissionBackendClause | modifyBackendClause | addComputeNodeClause | dropComputeNodeClause | modifyBrokerClause | alterLoadErrorUrlClause | createImageClause | cleanTabletSchedQClause | decommissionDiskClause | cancelDecommissionDiskClause | disableDiskClause | cancelDisableDiskClause //Alter table clause | createIndexClause | dropIndexClause | tableRenameClause | swapTableClause | modifyPropertiesClause | addColumnClause | addColumnsClause | dropColumnClause | modifyColumnCommentClause | modifyColumnClause | columnRenameClause | reorderColumnsClause | rollupRenameClause | compactionClause | modifyCommentClause | optimizeClause | addFieldClause | dropFieldClause | createOrReplaceBranchClause | createOrReplaceTagClause | dropBranchClause | dropTagClause | tableOperationClause | dropPersistentIndexClause //Alter partition clause | addPartitionClause | dropPartitionClause | distributionClause | truncatePartitionClause | modifyPartitionClause | replacePartitionClause | partitionRenameClause ; // ---------Alter system clause--------- addFrontendClause : ADD (FOLLOWER | OBSERVER) string ; dropFrontendClause : DROP (FOLLOWER | OBSERVER) string ; modifyFrontendHostClause : MODIFY FRONTEND HOST string TO string ; addBackendClause : ADD BACKEND string (COMMA string)* (INTO WAREHOUSE warehouseName=identifierOrString (CNGROUP cngroupName=identifierOrString)?)? ; dropBackendClause : DROP BACKEND string (COMMA string)* (FROM WAREHOUSE warehouseName=identifierOrString (CNGROUP cngroupName=identifierOrString)?)? FORCE? ; decommissionBackendClause : DECOMMISSION BACKEND string (COMMA string)* ; modifyBackendClause : MODIFY BACKEND HOST string TO string | MODIFY BACKEND string SET propertyList ; addComputeNodeClause : ADD COMPUTE NODE string (COMMA string)* (INTO WAREHOUSE warehouseName=identifierOrString (CNGROUP cngroupName=identifierOrString)?)? ; dropComputeNodeClause : DROP COMPUTE NODE string (COMMA string)* (FROM WAREHOUSE warehouseName=identifierOrString (CNGROUP cngroupName=identifierOrString)?)? ; modifyBrokerClause : ADD BROKER identifierOrString string (COMMA string)* | DROP BROKER identifierOrString string (COMMA string)* | DROP ALL BROKER identifierOrString ; alterLoadErrorUrlClause : SET LOAD ERRORS HUB properties? ; createImageClause : CREATE IMAGE ; cleanTabletSchedQClause : CLEAN TABLET SCHEDULER QUEUE ; decommissionDiskClause : DECOMMISSION DISK string (COMMA string)* ON BACKEND string ; cancelDecommissionDiskClause : CANCEL DECOMMISSION DISK string (COMMA string)* ON BACKEND string ; disableDiskClause : DISABLE DISK string (COMMA string)* ON BACKEND string ; cancelDisableDiskClause : CANCEL DISABLE DISK string (COMMA string)* ON BACKEND string ; // ---------Alter table clause--------- createIndexClause : ADD INDEX indexName=identifier identifierList (indexType propertyList?)? comment? ; dropIndexClause : DROP INDEX indexName=identifier ; tableRenameClause : RENAME identifier ; swapTableClause : SWAP WITH identifier ; modifyPropertiesClause : SET propertyList ; modifyCommentClause : COMMENT '=' string ; optimizeRange : BETWEEN start=string AND end=string ; optimizeClause : partitionNames? keyDesc? partitionDesc? orderByDesc? distributionDesc? optimizeRange? ; addColumnClause : ADD COLUMN columnDesc (FIRST | AFTER identifier)? ((TO | IN) rollupName=identifier)? properties? ; addColumnsClause : ADD COLUMN LEFT_PAREN columnDesc (COMMA columnDesc)* RIGHT_PAREN ((TO | IN) rollupName=identifier)? properties? ; dropColumnClause : DROP COLUMN identifier (FROM rollupName=identifier)? properties? ; modifyColumnClause : MODIFY COLUMN columnDesc (FIRST | AFTER identifier)? (FROM rollupName=identifier)? properties? ; modifyColumnCommentClause : MODIFY COLUMN identifier comment ; columnRenameClause : RENAME COLUMN oldColumn=identifier TO newColumn=identifier ; reorderColumnsClause : ORDER BY identifierList (FROM rollupName=identifier)? properties? ; rollupRenameClause : RENAME ROLLUP rollupName=identifier newRollupName=identifier ; compactionClause : (BASE | CUMULATIVE)? COMPACT (identifier | identifierList)? ; subfieldName : identifier | ARRAY_ELEMENT ; nestedFieldName : subfieldName (DOT_IDENTIFIER | DOT subfieldName)* ; addFieldClause : MODIFY COLUMN identifier ADD FIELD subfieldDesc (FIRST | AFTER identifier)? properties? ; dropFieldClause : MODIFY COLUMN identifier DROP FIELD nestedFieldName properties? ; createOrReplaceTagClause : (CREATE OR)? REPLACE TAG identifier tagOptions | CREATE TAG (IF NOT EXISTS)? identifier tagOptions ; createOrReplaceBranchClause : (CREATE OR)? REPLACE BRANCH identifier branchOptions | CREATE BRANCH (IF NOT EXISTS)? identifier branchOptions ; dropBranchClause : DROP BRANCH (IF EXISTS)? identifier ; dropTagClause : DROP TAG (IF EXISTS)? identifier ; tableOperationClause : EXECUTE functionCall ; tagOptions : (AS OF VERSION snapshotId)? (refRetain)? ; branchOptions : (AS OF VERSION snapshotId)? (refRetain)? (snapshotRetention)? ; snapshotRetention : WITH SNAPSHOT RETENTION minSnapshotsToKeep | WITH SNAPSHOT RETENTION maxSnapshotAge | WITH SNAPSHOT RETENTION minSnapshotsToKeep maxSnapshotAge ; refRetain : RETAIN number timeUnit ; maxSnapshotAge : number timeUnit ; minSnapshotsToKeep : number SNAPSHOTS ; snapshotId : number ; timeUnit : DAYS | HOURS | MINUTES ; integer_list : LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN ; dropPersistentIndexClause : DROP PERSISTENT INDEX ON TABLETS integer_list ; // ---------Alter partition clause--------- addPartitionClause : ADD TEMPORARY? (singleRangePartition | PARTITIONS multiRangePartition) distributionDesc? properties? | ADD TEMPORARY? (singleItemListPartitionDesc | multiItemListPartitionDesc) distributionDesc? properties? ; dropPartitionClause : DROP TEMPORARY? (PARTITION (IF EXISTS)? identifier | PARTITIONS (IF EXISTS)? identifierList) FORCE? | DROP TEMPORARY? PARTITIONS (IF EXISTS)? multiRangePartition FORCE? | DROP TEMPORARY? PARTITIONS (IF EXISTS)? WHERE where=expression FORCE? | DROP ALL TEMPORARY PARTITIONS FORCE? ; truncatePartitionClause : TRUNCATE partitionNames ; modifyPartitionClause : MODIFY PARTITION (identifier | identifierList | LEFT_PAREN ASTERISK_SYMBOL RIGHT_PAREN) SET propertyList | MODIFY PARTITION distributionDesc ; replacePartitionClause : REPLACE parName=partitionNames WITH tempParName=partitionNames properties? ; partitionRenameClause : RENAME PARTITION parName=identifier newParName=identifier ; // ------------------------------------------- DML Statement ----------------------------------------------------------- insertStatement : explainDesc? INSERT (INTO | OVERWRITE) (qualifiedName writeBranch? partitionNames? | (FILES propertyList) | (BLACKHOLE LEFT_PAREN RIGHT_PAREN)) insertLabelOrColumnAliases* properties? (queryStatement | (VALUES expressionsWithDefault (COMMA expressionsWithDefault)*)) ; // for compatibility with the case 'LABEL before columnAliases' insertLabelOrColumnAliases : columnAliasesOrByName | WITH LABEL label=identifier ; columnAliasesOrByName : columnAliases | BY NAME ; updateStatement : explainDesc? withClause? UPDATE qualifiedName SET assignmentList fromClause (WHERE where=expression)? ; deleteStatement : explainDesc? withClause? DELETE FROM qualifiedName partitionNames? (USING using=relations)? (WHERE where=expression)? ; // ------------------------------------------- Routine Statement ----------------------------------------------------------- createRoutineLoadStatement : CREATE ROUTINE LOAD (db=qualifiedName DOT)? name=identifier ON table=qualifiedName loadPropertiesExpr jobProperties? FROM source=identifier dataSourceProperties? ; alterRoutineLoadStatement : ALTER ROUTINE LOAD FOR (db=qualifiedName DOT)? name=identifier loadPropertiesExpr jobProperties? dataSource? ; loadPropertiesExpr : (loadProperties (COMMA loadProperties)*)? ; dataSource : FROM source=identifier dataSourceProperties ; loadProperties : colSeparatorProperty | rowDelimiterProperty | importColumns | WHERE expression | partitionNames ; colSeparatorProperty : COLUMNS TERMINATED BY string ; rowDelimiterProperty : ROWS TERMINATED BY string ; importColumns : COLUMNS columnProperties ; columnProperties : LEFT_PAREN (qualifiedName | assignment) (COMMA (qualifiedName | assignment))* RIGHT_PAREN ; jobProperties : properties ; dataSourceProperties : propertyList ; stopRoutineLoadStatement : STOP ROUTINE LOAD FOR (db=qualifiedName DOT)? name=identifier ; resumeRoutineLoadStatement : RESUME ROUTINE LOAD FOR (db=qualifiedName DOT)? name=identifier ; pauseRoutineLoadStatement : PAUSE ROUTINE LOAD FOR (db=qualifiedName DOT)? name=identifier ; showRoutineLoadStatement : SHOW ALL? ROUTINE LOAD (FOR (db=qualifiedName DOT)? name=identifier)? (FROM db=qualifiedName)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; showRoutineLoadTaskStatement : SHOW ROUTINE LOAD TASK (FROM db=qualifiedName)? WHERE expression ; showCreateRoutineLoadStatement : SHOW CREATE ROUTINE LOAD (db=qualifiedName DOT)? name=identifier ; showStreamLoadStatement : SHOW ALL? STREAM LOAD (FOR (db=qualifiedName DOT)? name=identifier)? (FROM db=qualifiedName)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; // ------------------------------------------- Analyze Statement ------------------------------------------------------- analyzeStatement : ANALYZE (FULL | SAMPLE)? TABLE tableName analyzeColumnClause? partitionNames? (WITH (SYNC | ASYNC) MODE)? properties? ; analyzeColumnClause : LEFT_PAREN qualifiedName (COMMA qualifiedName)* RIGHT_PAREN #regularColumns | qualifiedName (COMMA qualifiedName)* #regularColumns | ALL COLUMNS #allColumns | PREDICATE COLUMNS #predicateColumns | MULTIPLE COLUMNS LEFT_PAREN qualifiedName (COMMA qualifiedName)* RIGHT_PAREN #multiColumnSet ; dropStatsStatement : DROP (MULTIPLE COLUMNS)? STATS qualifiedName ; histogramStatement: ANALYZE TABLE tableName UPDATE HISTOGRAM ON analyzeColumnClause (WITH bucket=INTEGER_VALUE BUCKETS)? properties? ; analyzeHistogramStatement : histogramStatement (WITH (SYNC | ASYNC) MODE)? ; dropHistogramStatement : ANALYZE TABLE qualifiedName DROP HISTOGRAM ON qualifiedName (COMMA qualifiedName)* ; createAnalyzeStatement : CREATE ANALYZE (FULL | SAMPLE)? ALL properties? | CREATE ANALYZE (FULL | SAMPLE)? DATABASE db=identifier properties? | CREATE ANALYZE (FULL | SAMPLE)? TABLE qualifiedName (LEFT_PAREN qualifiedName (COMMA qualifiedName)* RIGHT_PAREN)? properties? | CREATE histogramStatement ; dropAnalyzeJobStatement : DROP ANALYZE INTEGER_VALUE | DROP ALL ANALYZE JOB ; showAnalyzeStatement : SHOW ANALYZE (JOB | STATUS)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; showStatsMetaStatement : SHOW (MULTIPLE COLUMNS)? STATS META (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; showHistogramMetaStatement : SHOW HISTOGRAM META (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; killAnalyzeStatement : KILL ANALYZE INTEGER_VALUE ; // ----------------------------------------- Analyze Profile Statement ------------------------------------------------- analyzeProfileStatement : ANALYZE PROFILE FROM string | ANALYZE PROFILE FROM string COMMA INTEGER_VALUE (COMMA INTEGER_VALUE)* ; // ----------------------------------------- SQL Plan Manager Statement ------------------------------------------------- createBaselinePlanStatement : CREATE GLOBAL? BASELINE (ON queryRelation)? USING queryRelation properties? ; dropBaselinePlanStatement : DROP BASELINE INTEGER_VALUE (COMMA INTEGER_VALUE)* ; showBaselinePlanStatement : SHOW BASELINE (WHERE expression)? ; disableBaselinePlanStatement : DISABLE BASELINE INTEGER_VALUE (COMMA INTEGER_VALUE)* ; enableBaselinePlanStatement : ENABLE BASELINE INTEGER_VALUE (COMMA INTEGER_VALUE)* ; // ------------------------------------------- Work Group Statement ---------------------------------------------------- createResourceGroupStatement : CREATE RESOURCE GROUP (IF NOT EXISTS)? (OR REPLACE)? identifier (TO classifier (COMMA classifier)*)? WITH LEFT_PAREN property (COMMA property)* RIGHT_PAREN ; dropResourceGroupStatement : DROP RESOURCE GROUP identifier ; alterResourceGroupStatement : ALTER RESOURCE GROUP identifier ADD classifier (COMMA classifier)* | ALTER RESOURCE GROUP identifier DROP LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN | ALTER RESOURCE GROUP identifier DROP ALL | ALTER RESOURCE GROUP identifier WITH LEFT_PAREN property (COMMA property)* RIGHT_PAREN ; showResourceGroupStatement : SHOW VERBOSE? RESOURCE GROUP identifier | SHOW VERBOSE? RESOURCE GROUPS ALL? ; showResourceGroupUsageStatement : SHOW USAGE RESOURCE GROUP identifier | SHOW USAGE RESOURCE GROUPS ; createResourceStatement : CREATE EXTERNAL? RESOURCE resourceName=identifierOrString properties? ; alterResourceStatement : ALTER RESOURCE resourceName=identifierOrString SET properties ; dropResourceStatement : DROP RESOURCE resourceName=identifierOrString ; showResourceStatement : SHOW RESOURCES ; classifier : LEFT_PAREN expressionList RIGHT_PAREN ; // ------------------------------------------- UDF Statement ---------------------------------------------------- showFunctionsStatement : SHOW FULL? (BUILTIN|GLOBAL)? FUNCTIONS ((FROM | IN) db=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; dropFunctionStatement : DROP GLOBAL? FUNCTION (IF EXISTS)? qualifiedName LEFT_PAREN typeList RIGHT_PAREN ; createFunctionStatement : CREATE orReplace GLOBAL? functionType=(TABLE | AGGREGATE)? FUNCTION ifNotExists qualifiedName LEFT_PAREN typeList RIGHT_PAREN RETURNS returnType=type (properties|inlineProperties)?? inlineFunction? ; inlineFunction : AS ATTACHMENT ; typeList : type? ( COMMA type)* (COMMA DOTDOTDOT) ? ; // ------------------------------------------- Load Statement ---------------------------------------------------------- loadStatement : LOAD LABEL label=labelName data=dataDescList? broker=brokerDesc? (BY system=identifierOrString)? (PROPERTIES props=propertyList)? | LOAD LABEL label=labelName data=dataDescList? resource=resourceDesc (PROPERTIES props=propertyList)? ; labelName : (db=identifier DOT)? label=identifier ; dataDescList : LEFT_PAREN dataDesc (COMMA dataDesc)* RIGHT_PAREN ; dataDesc : DATA INFILE srcFiles=stringList NEGATIVE? INTO TABLE dstTableName=identifier partitions=partitionNames? (COLUMNS TERMINATED BY colSep=string)? (ROWS TERMINATED BY rowSep=string)? format=fileFormat? (formatPropsField=formatProps)? colList=columnAliases? (COLUMNS FROM PATH AS colFromPath=identifierList)? (SET colMappingList=classifier)? (WHERE where=expression)? | DATA FROM TABLE srcTableName=identifier NEGATIVE? INTO TABLE dstTableName=identifier partitions=partitionNames? (SET colMappingList=classifier)? (WHERE where=expression)? ; formatProps : LEFT_PAREN (SKIP_HEADER '=' INTEGER_VALUE)? (TRIM_SPACE '=' booleanValue)? (ENCLOSE '=' encloseCharacter=string)? (ESCAPE '=' escapeCharacter=string)? RIGHT_PAREN ; brokerDesc : WITH BROKER props=propertyList? | WITH BROKER name=identifierOrString props=propertyList? ; resourceDesc : WITH RESOURCE name=identifierOrString props=propertyList? ; showLoadStatement : SHOW LOAD (ALL)? (FROM identifier)? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; showLoadWarningsStatement : SHOW LOAD WARNINGS (FROM identifier)? (WHERE expression)? limitElement? | SHOW LOAD WARNINGS ON string ; cancelLoadStatement : CANCEL LOAD (FROM identifier)? (WHERE expression)? ; alterLoadStatement : ALTER LOAD FOR (db=qualifiedName DOT)? name=identifier jobProperties? ; // ------------------------------------------- Compaction Statement ---------------------------------------------------------- cancelCompactionStatement : CANCEL COMPACTION WHERE expression ; // ------------------------------------------- Show Statement ---------------------------------------------------------- showAuthorStatement : SHOW AUTHORS ; showBackendsStatement : SHOW BACKENDS ; showBrokerStatement : SHOW BROKER ; showCharsetStatement : SHOW (CHAR SET | CHARSET | CHARACTER SET) ((LIKE pattern=string) | (WHERE expression))? ; showCollationStatement : SHOW COLLATION ((LIKE pattern=string) | (WHERE expression))? ; showDeleteStatement : SHOW DELETE ((FROM | IN) db=qualifiedName)? ; showDynamicPartitionStatement : SHOW DYNAMIC PARTITION TABLES ((FROM | IN) db=qualifiedName)? ; showEventsStatement : SHOW EVENTS ((FROM | IN) catalog=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showEnginesStatement : SHOW ENGINES ; showFrontendsStatement : SHOW FRONTENDS ; showPluginsStatement : SHOW PLUGINS ; showRepositoriesStatement : SHOW REPOSITORIES ; showOpenTableStatement : SHOW OPEN TABLES ; showPrivilegesStatement : SHOW PRIVILEGES ; showProcedureStatement : SHOW (PROCEDURE | FUNCTION) STATUS ((LIKE pattern=string) | (WHERE where=expression))? ; showProcStatement : SHOW PROC path=string ; showProcesslistStatement : SHOW FULL? PROCESSLIST (FOR string)? ; showProfilelistStatement : SHOW PROFILELIST (LIMIT limit =INTEGER_VALUE)? ; showRunningQueriesStatement : SHOW RUNNING QUERIES (LIMIT limit =INTEGER_VALUE)? ; showStatusStatement : SHOW varType? STATUS ((LIKE pattern=string) | (WHERE expression))? ; showTabletStatement : SHOW TABLET INTEGER_VALUE | SHOW (TABLET | TABLETS) FROM qualifiedName partitionNames? (WHERE expression)? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; showTransactionStatement : SHOW TRANSACTION ((FROM | IN) db=qualifiedName)? (WHERE expression)? ; showTriggersStatement : SHOW FULL? TRIGGERS ((FROM | IN) catalog=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showUserPropertyStatement : SHOW PROPERTY (FOR string)? (LIKE string)? | SHOW PROPERTIES (FOR string)? (LIKE string)? ; showVariablesStatement : SHOW varType? VARIABLES ((LIKE pattern=string) | (WHERE expression))? ; showWarningStatement : SHOW (WARNINGS | ERRORS) (limitElement)? ; helpStatement : HELP identifierOrString ; // ------------------------------------------- Authz Statement ----------------------------------------------------- createUserStatement : CREATE USER (IF NOT EXISTS)? user authOption? (DEFAULT ROLE roleList)? properties? ; dropUserStatement : DROP USER (IF EXISTS)? user ; alterUserStatement : ALTER USER (IF EXISTS)? user authOption | ALTER USER (IF EXISTS)? user DEFAULT ROLE (NONE| ALL | roleList) | ALTER USER (IF EXISTS)? user SET properties ; showUserStatement : SHOW (USER | USERS) ; showAuthenticationStatement : SHOW ALL AUTHENTICATION #showAllAuthentication | SHOW AUTHENTICATION (FOR user)? #showAuthenticationForUser ; executeAsStatement : EXECUTE AS user (WITH NO REVERT)? ; createRoleStatement : CREATE ROLE (IF NOT EXISTS)? roleList comment? ; alterRoleStatement : ALTER ROLE (IF EXISTS)? roleList SET COMMENT '=' string ; dropRoleStatement : DROP ROLE (IF EXISTS)? roleList ; showRolesStatement : SHOW ROLES ; grantRoleStatement : GRANT identifierOrStringList TO USER? user #grantRoleToUser | GRANT identifierOrStringList TO ROLE identifierOrString #grantRoleToRole ; revokeRoleStatement : REVOKE identifierOrStringList FROM USER? user #revokeRoleFromUser | REVOKE identifierOrStringList FROM ROLE identifierOrString #revokeRoleFromRole ; setRoleStatement : SET ROLE DEFAULT | SET ROLE NONE | SET ROLE ALL (EXCEPT roleList)? | SET ROLE roleList ; setDefaultRoleStatement : SET DEFAULT ROLE (NONE | ALL | roleList) TO user; grantRevokeClause : (USER? user | ROLE identifierOrString) ; grantPrivilegeStatement : GRANT IMPERSONATE ON USER user (COMMA user)* TO grantRevokeClause (WITH GRANT OPTION)? #grantOnUser | GRANT privilegeTypeList ON privObjectNameList TO grantRevokeClause (WITH GRANT OPTION)? #grantOnTableBrief | GRANT privilegeTypeList ON GLOBAL? FUNCTION privFunctionObjectNameList TO grantRevokeClause (WITH GRANT OPTION)? #grantOnFunc | GRANT privilegeTypeList ON SYSTEM TO grantRevokeClause (WITH GRANT OPTION)? #grantOnSystem | GRANT privilegeTypeList ON privObjectType privObjectNameList TO grantRevokeClause (WITH GRANT OPTION)? #grantOnPrimaryObj | GRANT privilegeTypeList ON ALL privObjectTypePlural (IN isAll=ALL DATABASES| IN DATABASE identifierOrString)? TO grantRevokeClause (WITH GRANT OPTION)? #grantOnAll ; revokePrivilegeStatement : REVOKE IMPERSONATE ON USER user (COMMA user)* FROM grantRevokeClause #revokeOnUser | REVOKE privilegeTypeList ON privObjectNameList FROM grantRevokeClause #revokeOnTableBrief | REVOKE privilegeTypeList ON GLOBAL? FUNCTION privFunctionObjectNameList FROM grantRevokeClause #revokeOnFunc | REVOKE privilegeTypeList ON SYSTEM FROM grantRevokeClause #revokeOnSystem | REVOKE privilegeTypeList ON privObjectType privObjectNameList FROM grantRevokeClause #revokeOnPrimaryObj | REVOKE privilegeTypeList ON ALL privObjectTypePlural (IN isAll=ALL DATABASES| IN DATABASE identifierOrString)? FROM grantRevokeClause #revokeOnAll ; showGrantsStatement : SHOW GRANTS | SHOW GRANTS FOR USER? user | SHOW GRANTS FOR ROLE identifierOrString ; authOption : IDENTIFIED BY PASSWORD? string #authWithoutPlugin | IDENTIFIED WITH identifierOrString ((BY | AS) string)? #authWithPlugin ; privObjectName : identifierOrStringOrStar (DOT identifierOrStringOrStar)? ; privObjectNameList : privObjectName (COMMA privObjectName)* ; privFunctionObjectNameList : qualifiedName LEFT_PAREN typeList RIGHT_PAREN (COMMA qualifiedName LEFT_PAREN typeList RIGHT_PAREN)* ; privilegeTypeList : privilegeType (COMMA privilegeType)* ; privilegeType : ALL PRIVILEGES? | ALTER | APPLY | BLACKLIST | CREATE ( DATABASE| TABLE| VIEW| FUNCTION| GLOBAL FUNCTION| MATERIALIZED VIEW| RESOURCE| RESOURCE GROUP| EXTERNAL CATALOG | STORAGE VOLUME | WAREHOUSE | CNGROUP | PIPE ) | DELETE | DROP | EXPORT | FILE | IMPERSONATE | INSERT | GRANT | NODE | OPERATE | PLUGIN | REPOSITORY| REFRESH | SELECT | UPDATE | USAGE ; privObjectType : CATALOG | DATABASE | MATERIALIZED VIEW | RESOURCE | RESOURCE GROUP | STORAGE VOLUME | SYSTEM | TABLE | VIEW | WAREHOUSE | PIPE ; privObjectTypePlural : CATALOGS | DATABASES | FUNCTIONS | GLOBAL FUNCTIONS | MATERIALIZED VIEWS | POLICIES | RESOURCES | RESOURCE GROUPS | STORAGE VOLUMES | TABLES | USERS | VIEWS | WAREHOUSES | PIPES ; // ------------------------------------------- Security Integration Statement ---------------------------------------------------- createSecurityIntegrationStatement : CREATE SECURITY INTEGRATION identifier properties ; alterSecurityIntegrationStatement : ALTER SECURITY INTEGRATION identifier SET propertyList ; dropSecurityIntegrationStatement : DROP SECURITY INTEGRATION identifier ; showSecurityIntegrationStatement : SHOW SECURITY INTEGRATIONS ; showCreateSecurityIntegrationStatement : SHOW CREATE SECURITY INTEGRATION identifier ; // ------------------------------------------- Group Provider Statement ------------------------------------------ createGroupProviderStatement : CREATE GROUP PROVIDER identifier properties ; dropGroupProviderStatement : DROP GROUP PROVIDER identifier ; showGroupProvidersStatement : SHOW GROUP PROVIDERS ; showCreateGroupProviderStatement : SHOW CREATE GROUP PROVIDER identifier ; // ---------------------------------------- Backup Restore Statement --------------------------------------------------- backupStatement : BACKUP (ALL EXTERNAL CATALOGS | EXTERNAL (CATALOG | CATALOGS) identifierList)? (DATABASE dbName=identifier)? SNAPSHOT qualifiedName TO repoName=identifier (ON LEFT_PAREN backupRestoreObjectDesc (COMMA backupRestoreObjectDesc) * RIGHT_PAREN)? (PROPERTIES propertyList)? ; cancelBackupStatement : CANCEL BACKUP ((FROM | IN) identifier | FOR EXTERNAL CATALOG)? ; showBackupStatement : SHOW BACKUP ((FROM | IN) identifier)? ; restoreStatement : RESTORE SNAPSHOT qualifiedName FROM repoName=identifier (ALL EXTERNAL CATALOGS | EXTERNAL (CATALOG | CATALOGS) identifierWithAliasList)? (DATABASE dbName=identifier (AS dbAlias=identifier)?)? (ON LEFT_PAREN backupRestoreObjectDesc (COMMA backupRestoreObjectDesc) * RIGHT_PAREN)? (PROPERTIES propertyList)? ; cancelRestoreStatement : CANCEL RESTORE ((FROM | IN) identifier | FOR EXTERNAL CATALOG)? ; showRestoreStatement : SHOW RESTORE ((FROM | IN) identifier)? (WHERE where=expression)? ; showSnapshotStatement : SHOW SNAPSHOT ON identifier (WHERE expression)? ; createRepositoryStatement : CREATE (READ ONLY)? REPOSITORY repoName=identifier WITH BROKER brokerName=identifierOrString? ON LOCATION location=string (PROPERTIES propertyList)? ; dropRepositoryStatement : DROP REPOSITORY identifier ; // ------------------------------------ Sql BlackList And WhiteList Statement ------------------------------------------ addSqlBlackListStatement : ADD SQLBLACKLIST string ; delSqlBlackListStatement : DELETE SQLBLACKLIST INTEGER_VALUE (COMMA INTEGER_VALUE)* ; showSqlBlackListStatement : SHOW SQLBLACKLIST ; showWhiteListStatement : SHOW WHITELIST ; // ------------------------------------ backend BlackList Statement --------------------------------------------------- addBackendBlackListStatement : ADD BACKEND BLACKLIST INTEGER_VALUE (COMMA INTEGER_VALUE)* ; delBackendBlackListStatement : DELETE BACKEND BLACKLIST INTEGER_VALUE (COMMA INTEGER_VALUE)* ; showBackendBlackListStatement : SHOW BACKEND BLACKLIST ; // -------------------------------------- DataCache Management Statement -------------------------------------------- dataCacheTarget : identifierOrStringOrStar DOT identifierOrStringOrStar DOT identifierOrStringOrStar ; createDataCacheRuleStatement : CREATE DATACACHE RULE dataCacheTarget (WHERE expression)? PRIORITY '=' MINUS_SYMBOL? INTEGER_VALUE properties? ; showDataCacheRulesStatement : SHOW DATACACHE RULES ; dropDataCacheRuleStatement : DROP DATACACHE RULE INTEGER_VALUE ; clearDataCacheRulesStatement : CLEAR DATACACHE RULES ; dataCacheSelectStatement : CACHE SELECT selectItem (COMMA selectItem)* FROM qualifiedName (WHERE where=expression)? properties? ; // ------------------------------------------- Export Statement -------------------------------------------------------- exportStatement : EXPORT TABLE tableDesc columnAliases? TO string (WITH (SYNC | ASYNC) MODE)? properties? brokerDesc? ; cancelExportStatement : CANCEL EXPORT ((FROM | IN) catalog=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? ; showExportStatement : SHOW EXPORT ((FROM | IN) catalog=qualifiedName)? ((LIKE pattern=string) | (WHERE expression))? (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; // ------------------------------------------- Plugin Statement -------------------------------------------------------- installPluginStatement : INSTALL PLUGIN FROM identifierOrString properties? ; uninstallPluginStatement : UNINSTALL PLUGIN identifierOrString ; // ------------------------------------------- File Statement ---------------------------------------------------------- createFileStatement : CREATE FILE string ((FROM | IN) catalog=qualifiedName)? properties ; dropFileStatement : DROP FILE string ((FROM | IN) catalog=qualifiedName)? properties ; showSmallFilesStatement : SHOW FILE ((FROM | IN) catalog=qualifiedName)? ; // -------------------------------------------- Pipe Statement --------------------------------------------------------- createPipeStatement : CREATE orReplace PIPE ifNotExists qualifiedName properties? AS insertStatement ; dropPipeStatement : DROP PIPE (IF EXISTS)? qualifiedName ; alterPipeClause : SUSPEND | RESUME | RETRY ALL | RETRY FILE fileName=string | SET propertyList ; alterPipeStatement : ALTER PIPE qualifiedName alterPipeClause ; descPipeStatement : (DESC | DESCRIBE) PIPE qualifiedName ; showPipeStatement : SHOW PIPES ((LIKE pattern=string) | (WHERE expression) | (FROM qualifiedName))? (ORDER BY sortItem (COMMA sortItem)*)? limitElement? ; // ------------------------------------------- Set Statement ----------------------------------------------------------- setStatement : SET setVar (COMMA setVar)* ; setVar : (CHAR SET | CHARSET | CHARACTER SET) (identifierOrString | DEFAULT) #setNames | NAMES (charset = identifierOrString | DEFAULT) (COLLATE (collate = identifierOrString | DEFAULT))? #setNames | PASSWORD '=' (string | PASSWORD LEFT_PAREN string RIGHT_PAREN) #setPassword | PASSWORD FOR user '=' (string | PASSWORD LEFT_PAREN string RIGHT_PAREN) #setPassword | userVariable '=' expression #setUserVar | varType? identifier '=' setExprOrDefault #setSystemVar | systemVariable '=' setExprOrDefault #setSystemVar | varType? TRANSACTION transaction_characteristics #setTransaction ; transaction_characteristics : transaction_access_mode | isolation_level | transaction_access_mode COMMA isolation_level | isolation_level COMMA transaction_access_mode ; transaction_access_mode : READ ONLY | READ WRITE ; isolation_level : ISOLATION LEVEL isolation_types ; isolation_types : READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE ; setExprOrDefault : DEFAULT | ON | ALL | expression ; setUserPropertyStatement : SET PROPERTY (FOR string)? userPropertyList ; roleList : identifierOrString (COMMA identifierOrString)* ; executeScriptStatement : ADMIN EXECUTE ON (FRONTEND | INTEGER_VALUE) string ; unsupportedStatement : LOCK TABLES lock_item (COMMA lock_item)* | UNLOCK TABLES ; lock_item : identifier (AS? alias=identifier)? lock_type ; lock_type : READ LOCAL? | LOW_PRIORITY? WRITE ; // ------------------------------------------- Plan Tuning Statement --------------------------------------------------- alterPlanAdvisorAddStatement : ALTER PLAN ADVISOR ADD queryStatement; truncatePlanAdvisorStatement : TRUNCATE PLAN ADVISOR; alterPlanAdvisorDropStatement : ALTER PLAN ADVISOR DROP string; showPlanAdvisorStatement : SHOW PLAN ADVISOR; // ---------------------------------------- Warehouse Statement --------------------------------------------------------- createWarehouseStatement : CREATE (WAREHOUSE) (IF NOT EXISTS)? warehouseName=identifierOrString comment? properties? ; dropWarehouseStatement : DROP WAREHOUSE (IF EXISTS)? warehouseName=identifierOrString ; suspendWarehouseStatement : SUSPEND WAREHOUSE (IF EXISTS)? identifier ; resumeWarehouseStatement : RESUME WAREHOUSE (IF EXISTS)? identifier ; setWarehouseStatement : SET SESSION? WAREHOUSE EQ? identifierOrString ; showWarehousesStatement : SHOW WAREHOUSES (LIKE pattern=string)? ; showClustersStatement : SHOW (CLUSTERS | CNGROUPS) FROM WAREHOUSE identifier ; showNodesStatement : SHOW NODES FROM WAREHOUSES (LIKE pattern=string)? | SHOW NODES FROM WAREHOUSE identifier (CNGROUP cngroupName=identifierOrString)? ; alterWarehouseStatement : ALTER WAREHOUSE warehouseName=identifierOrString modifyPropertiesClause ; createCNGroupStatement : ALTER WAREHOUSE warehouseName=identifierOrString ADD CNGROUP (IF NOT EXISTS)? cngroupName=identifierOrString comment? properties? ; dropCNGroupStatement : ALTER WAREHOUSE warehouseName=identifierOrString DROP CNGROUP (IF EXISTS)? cngroupName=identifierOrString FORCE? ; enableCNGroupStatement : ALTER WAREHOUSE warehouseName=identifierOrString ENABLE CNGROUP cngroupName=identifierOrString ; disableCNGroupStatement : ALTER WAREHOUSE warehouseName=identifierOrString DISABLE CNGROUP cngroupName=identifierOrString ; alterCNGroupStatement : ALTER WAREHOUSE warehouseName=identifierOrString MODIFY CNGROUP cngroupName=identifierOrString modifyPropertiesClause ; // ------------------------------------------- Transaction Statement --------------------------------------------------- beginStatement : START TRANSACTION (WITH CONSISTENT SNAPSHOT)? | BEGIN WORK? ; commitStatement : COMMIT WORK? (AND NO? CHAIN)? (NO? RELEASE)? ; rollbackStatement : ROLLBACK WORK? (AND NO? CHAIN)? (NO? RELEASE)? ; // ------------------------------------------- Translate Statement ----------------------------------------------------- translateStatement : TRANSLATE dialect translateSQL ; dialect : identifier ; translateSQL : .+ ; // ------------------------------------------- Query Statement --------------------------------------------------------- queryStatement : (explainDesc | optimizerTrace) ? queryRelation outfile?; queryRelation : withClause? queryNoWith ; withClause : WITH commonTableExpression (COMMA commonTableExpression)* ; queryNoWith : queryPrimary (ORDER BY sortItem (COMMA sortItem)*)? (limitElement)? ; queryPeriod : FOR? periodType BETWEEN expression AND expression | FOR? periodType FROM expression TO expression | FOR? periodType ALL | FOR? periodType AS OF end=expression ; periodType : SYSTEM_TIME | TIMESTAMP | VERSION ; queryPrimary : querySpecification #queryPrimaryDefault | subquery #queryWithParentheses | left=queryPrimary operator=INTERSECT setQuantifier? right=queryPrimary #setOperation | left=queryPrimary operator=(UNION | EXCEPT | MINUS) setQuantifier? right=queryPrimary #setOperation ; subquery : LEFT_PAREN queryRelation RIGHT_PAREN ; rowConstructor :LEFT_PAREN expressionList RIGHT_PAREN ; sortItem : expression ordering = (ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; limitConstExpr : INTEGER_VALUE | PARAMETER | userVariable ; limitElement : LIMIT limit=limitConstExpr (OFFSET offset=limitConstExpr)? | LIMIT offset=limitConstExpr COMMA limit=limitConstExpr ; querySpecification : SELECT setQuantifier? selectItem (COMMA selectItem)* fromClause ((WHERE where=expression)? (GROUP BY groupingElement)? (HAVING having=expression)? (QUALIFY qualifyFunction=selectItem comparisonOperator limit=INTEGER_VALUE)?) ; fromClause : (FROM relations pivotClause?)? #from | FROM DUAL #dual ; groupingElement : ROLLUP LEFT_PAREN (expressionList)? RIGHT_PAREN #rollup | CUBE LEFT_PAREN (expressionList)? RIGHT_PAREN #cube | GROUPING SETS LEFT_PAREN groupingSet (COMMA groupingSet)* RIGHT_PAREN #multipleGroupingSets | expressionList #singleGroupingSet ; groupingSet : LEFT_PAREN expression? (COMMA expression)* RIGHT_PAREN ; commonTableExpression : name=identifier (columnAliases)? AS LEFT_PAREN queryRelation RIGHT_PAREN ; setQuantifier : DISTINCT | ALL ; selectItem : expression (AS? (identifier | string))? #selectSingle | qualifiedName DOT ASTERISK_SYMBOL excludeClause? #selectAll | ASTERISK_SYMBOL excludeClause? #selectAll ; excludeClause : ( EXCEPT | EXCLUDE ) LEFT_PAREN identifier (COMMA identifier)* RIGHT_PAREN ; relations : relation (COMMA LATERAL? relation)* ; relation : relationPrimary joinRelation* | LEFT_PAREN relationPrimary joinRelation* RIGHT_PAREN ; relationPrimary : qualifiedName queryPeriod? partitionNames? tabletList? replicaList? sampleClause? ( AS? alias=identifier)? bracketHint? (BEFORE ts=string)? #tableAtom | LEFT_PAREN VALUES rowConstructor (COMMA rowConstructor)* RIGHT_PAREN (AS? alias=identifier columnAliases?)? #inlineTable | ASSERT_ROWS? subquery (AS? alias=identifier columnAliases?)? #subqueryWithAlias | qualifiedName LEFT_PAREN expressionList RIGHT_PAREN (AS? alias=identifier columnAliases?)? #tableFunction | TABLE LEFT_PAREN qualifiedName LEFT_PAREN argumentList RIGHT_PAREN RIGHT_PAREN (AS? alias=identifier columnAliases?)? #normalizedTableFunction | FILES propertyList (AS? alias=identifier columnAliases?)? #fileTableFunction | LEFT_PAREN relations RIGHT_PAREN #parenthesizedRelation ; pivotClause : PIVOT LEFT_PAREN pivotAggregationExpression (COMMA pivotAggregationExpression)* FOR (identifier | identifierList) IN LEFT_PAREN pivotValue (COMMA pivotValue)* RIGHT_PAREN RIGHT_PAREN ; pivotAggregationExpression : functionCall (AS? (identifier | string))? ; pivotValue : (literalExpression | literalExpressionList) (AS? (identifier | string))? ; sampleClause : SAMPLE propertyList? ; argumentList : expressionList | namedArgumentList ; namedArgumentList : namedArgument (COMMA namedArgument)* ; namedArgument : identifier FAT_ARROW expression #namedArguments ; joinRelation : crossOrInnerJoinType bracketHint? LATERAL? rightRelation=relationPrimary joinCriteria? | outerAndSemiJoinType bracketHint? LATERAL? rightRelation=relationPrimary joinCriteria ; crossOrInnerJoinType : JOIN | INNER JOIN | CROSS | CROSS JOIN ; outerAndSemiJoinType : LEFT JOIN | RIGHT JOIN | FULL JOIN | LEFT OUTER JOIN | RIGHT OUTER JOIN | FULL OUTER JOIN | LEFT SEMI JOIN | RIGHT SEMI JOIN | LEFT ANTI JOIN | RIGHT ANTI JOIN | NULL AWARE LEFT ANTI JOIN ; bracketHint : LEFT_BRACKET identifier (COMMA identifier)* RIGHT_BRACKET | LEFT_BRACKET identifier '|' primaryExpression literalExpressionList RIGHT_BRACKET ; hintMap : k=identifierOrString '=' v=literalExpression ; joinCriteria : ON expression | USING LEFT_PAREN identifier (COMMA identifier)* LEFT_PAREN ; columnAliases : LEFT_PAREN identifier (COMMA identifier)* RIGHT_PAREN ; // partitionNames should not support string, it should be identifier here only for compatibility with historical bugs partitionNames : TEMPORARY? (PARTITION | PARTITIONS) LEFT_PAREN identifierOrString (COMMA identifierOrString)* RIGHT_PAREN | TEMPORARY? (PARTITION | PARTITIONS) identifierOrString | keyPartitions ; keyPartitions : PARTITION LEFT_PAREN keyPartition (COMMA keyPartition)* RIGHT_PAREN #keyPartitionList ; tabletList : TABLET LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN ; prepareStatement : PREPARE identifier FROM prepareSql ; prepareSql : statement | SINGLE_QUOTED_TEXT ; executeStatement : EXECUTE identifier (USING '@'identifierOrString (COMMA '@'identifierOrString)*)? ; deallocateStatement : (DEALLOCATE | DROP) PREPARE identifier ; replicaList : REPLICA LEFT_PAREN INTEGER_VALUE (COMMA INTEGER_VALUE)* RIGHT_PAREN ; // ------------------------------------------- Expression -------------------------------------------------------------- /** * Operator precedences are shown in the following list, from highest precedence to the lowest. * * ! * - (unary minus), ~ (unary bit inversion) * ^ * *, /, DIV, %, MOD * -, + * & * | * = (comparison), <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP * BETWEEN, CASE WHEN * NOT * AND, && * XOR * OR, || * = (assignment) */ expressionsWithDefault : LEFT_PAREN expressionOrDefault (COMMA expressionOrDefault)* RIGHT_PAREN ; expressionOrDefault : expression | DEFAULT ; mapExpressionList : mapExpression (COMMA mapExpression)* ; mapExpression : key=expression COLON value=expression ; expressionSingleton : expression EOF ; expression : (BINARY)? booleanExpression #expressionDefault | NOT expression #logicalNot | left=expression operator=(AND|LOGICAL_AND) right=expression #logicalBinary | left=expression operator=(OR|LOGICAL_OR) right=expression #logicalBinary ; expressionList : expression (COMMA expression)* ; booleanExpression : predicate #booleanExpressionDefault | booleanExpression IS NOT? NULL #isNull | left = booleanExpression comparisonOperator right = predicate #comparison | booleanExpression comparisonOperator LEFT_PAREN queryRelation RIGHT_PAREN #scalarSubquery ; predicate : valueExpression (predicateOperations[$valueExpression.ctx])? | tupleInSubquery ; tupleInSubquery : LEFT_PAREN expression (COMMA expression)+ RIGHT_PAREN NOT? IN LEFT_PAREN queryRelation RIGHT_PAREN ; predicateOperations [ParserRuleContext value] : NOT? IN LEFT_PAREN queryRelation RIGHT_PAREN #inSubquery | NOT? IN LEFT_PAREN expressionList RIGHT_PAREN #inList | NOT? BETWEEN lower = valueExpression AND upper = predicate #between | NOT? (LIKE | RLIKE | REGEXP) pattern=valueExpression #like ; valueExpression : primaryExpression #valueExpressionDefault | left = valueExpression operator = BITXOR right = valueExpression #arithmeticBinary | left = valueExpression operator = ( ASTERISK_SYMBOL | SLASH_SYMBOL | PERCENT_SYMBOL | INT_DIV | MOD) right = valueExpression #arithmeticBinary | left = valueExpression operator = (PLUS_SYMBOL | MINUS_SYMBOL) right = valueExpression #arithmeticBinary | left = valueExpression operator = BITAND right = valueExpression #arithmeticBinary | left = valueExpression operator = BITOR right = valueExpression #arithmeticBinary | left = valueExpression operator = BIT_SHIFT_LEFT right = valueExpression #arithmeticBinary | left = valueExpression operator = BIT_SHIFT_RIGHT right = valueExpression #arithmeticBinary | left = valueExpression operator = BIT_SHIFT_RIGHT_LOGICAL right = valueExpression #arithmeticBinary ; primaryExpression : userVariable #userVariableExpression | systemVariable #systemVariableExpression | DICTIONARY_GET LEFT_PAREN expressionList RIGHT_PAREN #dictionaryGetExpr | functionCall #functionCallExpression | LEFT_BRACE FN functionCall RIGHT_BRACE #odbcFunctionCallExpression | primaryExpression COLLATE (identifier | string) #collate | literalExpression #literal | columnReference #columnRef | base = primaryExpression (DOT_IDENTIFIER | DOT fieldName = identifier ) #dereference | left = primaryExpression CONCAT right = primaryExpression #concat | operator = (MINUS_SYMBOL | PLUS_SYMBOL | BITNOT) primaryExpression #arithmeticUnary | operator = LOGICAL_NOT primaryExpression #arithmeticUnary | LEFT_PAREN expression RIGHT_PAREN #parenthesizedExpression | EXISTS LEFT_PAREN queryRelation RIGHT_PAREN #exists | subquery #subqueryExpression | CAST LEFT_PAREN expression AS type RIGHT_PAREN #cast | CONVERT LEFT_PAREN expression COMMA type RIGHT_PAREN #convert | CASE caseExpr=expression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | arrayType? LEFT_BRACKET (expressionList)? RIGHT_BRACKET #arrayConstructor | mapType LEFT_BRACE (mapExpressionList)? RIGHT_BRACE #mapConstructor | MAP LEFT_BRACE (mapExpressionList)? RIGHT_BRACE #mapConstructor | value=primaryExpression LEFT_BRACKET index=valueExpression RIGHT_BRACKET #collectionSubscript | primaryExpression LEFT_BRACKET start=INTEGER_VALUE? COLON end=INTEGER_VALUE? RIGHT_BRACKET #arraySlice | primaryExpression ARROW string #arrowExpression | (identifier | identifierList) LEFT_PAREN expression #lambdaFunctionExpr | identifierList ARROW LEFT_PAREN(expressionList)?RIGHT_PAREN #lambdaFunctionExpr | left = primaryExpression NOT? MATCH right = primaryExpression #matchExpr ; literalExpression : NULL #nullLiteral | booleanValue #booleanLiteral | number #numericLiteral | (DATE | DATETIME) string #dateLiteral | string #stringLiteral | interval #intervalLiteral | unitBoundary #unitBoundaryLiteral | binary #binaryLiteral | PARAMETER #Parameter ; functionCall : EXTRACT LEFT_PAREN identifier FROM valueExpression RIGHT_PAREN #extract | GROUPING LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN #groupingOperation | GROUPING_ID LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN #groupingOperation | informationFunctionExpression #informationFunction | specialDateTimeExpression #specialDateTime | specialFunctionExpression #specialFunction | aggregationFunction filter? over? #aggregationFunctionCall | windowFunction over #windowFunctionCall | TRANSLATE LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN #translateFunctionCall | qualifiedName LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN over? #simpleFunctionCall ; aggregationFunction : AVG LEFT_PAREN setQuantifier? expression RIGHT_PAREN | COUNT LEFT_PAREN ASTERISK_SYMBOL? RIGHT_PAREN | COUNT LEFT_PAREN (setQuantifier bracketHint?)? (expression (COMMA expression)*)? RIGHT_PAREN | MAX LEFT_PAREN setQuantifier? expression RIGHT_PAREN | MIN LEFT_PAREN setQuantifier? expression RIGHT_PAREN | SUM LEFT_PAREN setQuantifier? expression RIGHT_PAREN | ARRAY_AGG LEFT_PAREN setQuantifier? expression (ORDER BY sortItem (COMMA sortItem)*)? RIGHT_PAREN | ARRAY_AGG_DISTINCT LEFT_PAREN expression (ORDER BY sortItem (COMMA sortItem)*)? RIGHT_PAREN | GROUP_CONCAT LEFT_PAREN setQuantifier? expression (COMMA expression)* (ORDER BY sortItem (COMMA sortItem)*)? (SEPARATOR expression)? RIGHT_PAREN ; userVariable : AT identifierOrString ; systemVariable : AT AT (varType DOT)? identifier ; columnReference : identifier ; informationFunctionExpression : name = CATALOG LEFT_PAREN RIGHT_PAREN | name = DATABASE LEFT_PAREN RIGHT_PAREN | name = SCHEMA LEFT_PAREN RIGHT_PAREN | name = USER LEFT_PAREN RIGHT_PAREN | name = CURRENT_USER (LEFT_PAREN RIGHT_PAREN)? | name = CURRENT_ROLE (LEFT_PAREN RIGHT_PAREN)? | name = CURRENT_GROUP (LEFT_PAREN RIGHT_PAREN)? ; specialDateTimeExpression : name = CURRENT_DATE (LEFT_PAREN RIGHT_PAREN)? | name = CURRENT_TIME (LEFT_PAREN RIGHT_PAREN)? | name = CURRENT_TIMESTAMP (LEFT_PAREN (INTEGER_VALUE)? RIGHT_PAREN)? | name = LOCALTIME (LEFT_PAREN RIGHT_PAREN)? | name = LOCALTIMESTAMP (LEFT_PAREN RIGHT_PAREN)? ; specialFunctionExpression : CHAR LEFT_PAREN expression RIGHT_PAREN | DAY LEFT_PAREN expression RIGHT_PAREN | HOUR LEFT_PAREN expression RIGHT_PAREN | IF LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN | LEFT LEFT_PAREN expression COMMA expression RIGHT_PAREN | LIKE LEFT_PAREN expression COMMA expression RIGHT_PAREN | MINUTE LEFT_PAREN expression RIGHT_PAREN | MOD LEFT_PAREN expression COMMA expression RIGHT_PAREN | MONTH LEFT_PAREN expression RIGHT_PAREN | QUARTER LEFT_PAREN expression RIGHT_PAREN | REGEXP LEFT_PAREN expression COMMA expression RIGHT_PAREN | REPLACE LEFT_PAREN (expression (COMMA expression)*)? RIGHT_PAREN | RIGHT LEFT_PAREN expression COMMA expression RIGHT_PAREN | RLIKE LEFT_PAREN expression COMMA expression RIGHT_PAREN | SECOND LEFT_PAREN expression RIGHT_PAREN | TIMESTAMPADD LEFT_PAREN unitIdentifier COMMA expression COMMA expression RIGHT_PAREN | TIMESTAMPDIFF LEFT_PAREN unitIdentifier COMMA expression COMMA expression RIGHT_PAREN //| WEEK LEFT_PAREN expression RIGHT_PAREN TODO: Support week(expr) function | YEAR LEFT_PAREN expression RIGHT_PAREN | PASSWORD LEFT_PAREN string RIGHT_PAREN | FLOOR LEFT_PAREN expression RIGHT_PAREN | CEIL LEFT_PAREN expression RIGHT_PAREN ; windowFunction : name = ROW_NUMBER LEFT_PAREN RIGHT_PAREN | name = RANK LEFT_PAREN RIGHT_PAREN | name = DENSE_RANK LEFT_PAREN RIGHT_PAREN | name = CUME_DIST LEFT_PAREN RIGHT_PAREN | name = PERCENT_RANK LEFT_PAREN RIGHT_PAREN | name = NTILE LEFT_PAREN expression? RIGHT_PAREN | name = LEAD LEFT_PAREN (expression ignoreNulls? (COMMA expression)*)? RIGHT_PAREN ignoreNulls? | name = LAG LEFT_PAREN (expression ignoreNulls? (COMMA expression)*)? RIGHT_PAREN ignoreNulls? | name = FIRST_VALUE LEFT_PAREN (expression ignoreNulls? (COMMA expression)*)? RIGHT_PAREN ignoreNulls? | name = LAST_VALUE LEFT_PAREN (expression ignoreNulls? (COMMA expression)*)? RIGHT_PAREN ignoreNulls? ; whenClause : WHEN condition=expression THEN result=expression ; filter : FILTER LEFT_PAREN WHERE booleanExpression RIGHT_PAREN ; over : OVER LEFT_PAREN (bracketHint? PARTITION BY partition+=expression (COMMA partition+=expression)*)? (ORDER BY sortItem (COMMA sortItem)*)? windowFrame? RIGHT_PAREN ; ignoreNulls : IGNORE NULLS ; windowFrame : frameType=RANGE start=frameBound | frameType=ROWS start=frameBound | frameType=RANGE BETWEEN start=frameBound AND end=frameBound | frameType=ROWS BETWEEN start=frameBound AND end=frameBound ; frameBound : UNBOUNDED boundType=PRECEDING #unboundedFrame | UNBOUNDED boundType=FOLLOWING #unboundedFrame | CURRENT ROW #currentRowBound | expression boundType=(PRECEDING | FOLLOWING) #boundedFrame ; // ------------------------------------------- COMMON AST -------------------------------------------------------------- backupRestoreObjectDesc : backupRestoreTableDesc | (ALL (FUNCTION | FUNCTIONS) | (FUNCTION | FUNCTIONS) qualifiedName (AS identifier)?) | (ALL (TABLE | TABLES) | (TABLE | TABLES) backupRestoreTableDesc) | (ALL MATERIALIZED (VIEW | VIEWS) | MATERIALIZED (VIEW | VIEWS) qualifiedName (AS identifier)?) | (ALL (VIEW | VIEWS) | (VIEW | VIEWS) qualifiedName (AS identifier)?) ; tableDesc : qualifiedName partitionNames? ; backupRestoreTableDesc : qualifiedName partitionNames? (AS identifier)? ; explainDesc : (DESC | DESCRIBE | EXPLAIN) (LOGICAL | ANALYZE | VERBOSE | COSTS | SCHEDULER)? ; optimizerTrace : TRACE (ALL | LOGS | TIMES | VALUES | REASON) identifier? ; partitionExpr : identifier | functionCall ; partitionDesc : PARTITION BY RANGE identifierList LEFT_PAREN (rangePartitionDesc (COMMA rangePartitionDesc)*)? RIGHT_PAREN | PARTITION BY RANGE primaryExpression LEFT_PAREN (rangePartitionDesc (COMMA rangePartitionDesc)*)? RIGHT_PAREN | PARTITION BY LIST? identifierList LEFT_PAREN (listPartitionDesc (COMMA listPartitionDesc)*)? RIGHT_PAREN | PARTITION BY LIST? identifierList | PARTITION BY functionCall LEFT_PAREN (rangePartitionDesc (COMMA rangePartitionDesc)*)? RIGHT_PAREN | PARTITION BY functionCall | PARTITION BY partitionExpr (COMMA partitionExpr)* ; listPartitionDesc : singleItemListPartitionDesc | multiItemListPartitionDesc ; singleItemListPartitionDesc : PARTITION (IF NOT EXISTS)? identifier VALUES IN singleListPartitionValues propertyList? ; multiItemListPartitionDesc : PARTITION (IF NOT EXISTS)? identifier VALUES IN multiListPartitionValues propertyList? ; multiListPartitionValues :LEFT_PAREN singleListPartitionValues (COMMA singleListPartitionValues)* RIGHT_PAREN // list partition values with multi partition columns: ('a, 'b', 'c'), ('d', 'e', 'f') ; singleListPartitionValues : LEFT_PAREN listPartitionValue (COMMA listPartitionValue)* RIGHT_PAREN // list partition value: ('a, 'b', 'c') ; listPartitionValues // list partition values which can be with single or multi partition columns : singleListPartitionValues | multiListPartitionValues ; listPartitionValue : NULL | string ; stringList : LEFT_PAREN string (COMMA string)* RIGHT_PAREN ; literalExpressionList : LEFT_PAREN literalExpression (COMMA literalExpression)* RIGHT_PAREN ; rangePartitionDesc : singleRangePartition | multiRangePartition ; singleRangePartition : PARTITION (IF NOT EXISTS)? identifier VALUES partitionKeyDesc propertyList? ; multiRangePartition : START LEFT_PAREN string RIGHT_PAREN END LEFT_PAREN string RIGHT_PAREN EVERY LEFT_PAREN interval RIGHT_PAREN | START LEFT_PAREN string RIGHT_PAREN END LEFT_PAREN string RIGHT_PAREN EVERY LEFT_PAREN INTEGER_VALUE RIGHT_PAREN ; partitionRangeDesc : START LEFT_PAREN string RIGHT_PAREN END LEFT_PAREN string RIGHT_PAREN ; partitionKeyDesc : LESS THAN (MAXVALUE | partitionValueList) | LEFT_BRACKET partitionValueList COMMA partitionValueList RIGHT_PAREN ; partitionValueList : LEFT_PAREN partitionValue (COMMA partitionValue)* RIGHT_PAREN ; keyPartition : partitionColName=identifier '=' partitionColValue=literalExpression ; partitionValue : MAXVALUE | string ; distributionClause : DISTRIBUTED BY HASH identifierList (BUCKETS INTEGER_VALUE)? | DISTRIBUTED BY HASH identifierList ; distributionDesc : DISTRIBUTED BY HASH identifierList (BUCKETS INTEGER_VALUE)? | DISTRIBUTED BY HASH identifierList | DISTRIBUTED BY RANDOM (BUCKETS INTEGER_VALUE)? ; refreshSchemeDesc : REFRESH (IMMEDIATE | DEFERRED)? (ASYNC | ASYNC (START LEFT_PAREN string RIGHT_PAREN)? EVERY LEFT_PAREN interval RIGHT_PAREN | INCREMENTAL | MANUAL) ; statusDesc : ACTIVE | INACTIVE ; properties : PROPERTIES LEFT_PAREN property (COMMA property)* RIGHT_PAREN ; extProperties : BROKER properties ; propertyList : LEFT_PAREN property (COMMA property)* RIGHT_PAREN ; userPropertyList : property (COMMA property)* ; property : key=string '=' value=string ; inlineProperties : inlineProperty ( inlineProperty)* ; inlineProperty : key=identifier '=' value=string ; varType : GLOBAL | LOCAL | SESSION | VERBOSE ; comment : COMMENT string ; outfile : INTO OUTFILE file=string fileFormat? properties? ; fileFormat : FORMAT AS (identifier | string) ; string : SINGLE_QUOTED_TEXT | DOUBLE_QUOTED_TEXT ; binary : BINARY_SINGLE_QUOTED_TEXT | BINARY_DOUBLE_QUOTED_TEXT ; comparisonOperator : EQ | NEQ | LT | LTE | GT | GTE | EQ_FOR_NULL ; booleanValue : TRUE | FALSE ; interval : INTERVAL value=expression from=unitIdentifier ; taskInterval : INTERVAL value=expression from=taskUnitIdentifier ; taskUnitIdentifier : DAY | HOUR | MINUTE | SECOND ; unitIdentifier : YEAR | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | QUARTER | MILLISECOND | MICROSECOND ; unitBoundary : FLOOR | CEIL ; type : baseType | decimalType | arrayType | structType | mapType ; arrayType : ARRAY '<' type '>' ; mapType : MAP '<' type COMMA type '>' ; subfieldDesc : (identifier | nestedFieldName) type ; subfieldDescs : subfieldDesc (COMMA subfieldDesc)* ; structType : STRUCT '<' subfieldDescs '>' ; typeParameter : LEFT_PAREN INTEGER_VALUE RIGHT_PAREN ; baseType : BOOLEAN | TINYINT typeParameter? | SMALLINT typeParameter? | SIGNED INT? | SIGNED INTEGER? | UNSIGNED INT? | UNSIGNED INTEGER? | INT typeParameter? | INTEGER typeParameter? | BIGINT typeParameter? | LARGEINT typeParameter? | FLOAT | DOUBLE | DATE | DATETIME | TIME | CHAR typeParameter? | VARCHAR typeParameter? | STRING | TEXT | BITMAP | HLL | PERCENTILE | JSON | VARBINARY typeParameter? | BINARY typeParameter? ; decimalType : (DECIMAL | DECIMALV2 | DECIMAL32 | DECIMAL64 | DECIMAL128 | NUMERIC | NUMBER ) (LEFT_PAREN precision=INTEGER_VALUE (COMMA scale=INTEGER_VALUE)? RIGHT_PAREN)? ; qualifiedName : identifier (DOT_IDENTIFIER | DOT identifier)* ; tableName : qualifiedName ; writeBranch : FOR? VERSION AS OF identifier ; identifier : LETTER_IDENTIFIER #unquotedIdentifier | nonReserved #unquotedIdentifier | DIGIT_IDENTIFIER #digitIdentifier | BACKQUOTED_IDENTIFIER #backQuotedIdentifier ; identifierWithAlias : originalName=identifier (AS alias=identifier)? ; identifierWithAliasList : LEFT_PAREN identifierWithAlias (COMMA identifierWithAlias)* RIGHT_PAREN ; identifierList : LEFT_PAREN identifier (COMMA identifier)* RIGHT_PAREN ; identifierOrString : identifier | string ; identifierOrStringList : identifierOrString (COMMA identifierOrString)* ; identifierOrStringOrStar : ASTERISK_SYMBOL | identifier | string ; user : identifierOrString # userWithoutHost | identifierOrString '@' identifierOrString # userWithHost | identifierOrString '@' LEFT_BRACKET identifierOrString RIGHT_BRACKET # userWithHostAndBlanket ; assignment : identifier EQ expressionOrDefault ; assignmentList : assignment (COMMA assignment)* ; number : DECIMAL_VALUE #decimalValue | DOUBLE_VALUE #doubleValue | INTEGER_VALUE #integerValue ; nonReserved : ACCESS | ACTIVE | ADVISOR | AFTER | AGGREGATE | APPLY | ASYNC | AUTHORS | AVG | ADMIN | ANTI | AUTHENTICATION | AUTO_INCREMENT | AUTOMATED | ARRAY_AGG | ARRAY_AGG_DISTINCT | ASSERT_ROWS | AWARE | BACKEND | BACKENDS | BACKUP | BEGIN | BITMAP_UNION | BLACKLIST | BLACKHOLE | BINARY | BODY | BOOLEAN | BRANCH | BROKER | BUCKETS | BUILTIN | BASE | BEFORE | BASELINE | CACHE | CAST | CANCEL | CATALOG | CATALOGS | CEIL | CHAIN | CHARSET | CLEAN | CLEAR | CLUSTER | CLUSTERS | CNGROUP | CNGROUPS | CURRENT | COLLATION | COLUMNS | CUME_DIST | CUMULATIVE | COMMENT | COMMIT | COMMITTED | COMPUTE | CONNECTION | CONSISTENT | COSTS | COUNT | CONFIG | COMPACT | DATA | DATE | DATACACHE | DATETIME | DAY | DAYS | DECOMMISSION | DIALECT | DISABLE | DISK | DISTRIBUTION | DUPLICATE | DYNAMIC | DISTRIBUTED | DICTIONARY | DICTIONARY_GET | DEALLOCATE | ENABLE | END | ENGINE | ENGINES | ERRORS | EVENTS | EXECUTE | EXTERNAL | EXTRACT | EVERY | ENCLOSE | ESCAPE | EXPORT | FAILPOINT | FAILPOINTS | FIELDS | FILE | FILTER | FIRST | FLOOR | FOLLOWING | FORMAT | FN | FRONTEND | FRONTENDS | FOLLOWER | FREE | FUNCTIONS | GLOBAL | GRANTS | GROUP_CONCAT | HASH | HISTOGRAM | HELP | HLL_UNION | HOST | HOUR | HOURS | HUB | IDENTIFIED | IMAGE | IMPERSONATE | INACTIVE | INCREMENTAL | INDEXES | INSTALL | INTEGRATION | INTEGRATIONS | INTERMEDIATE | INTERVAL | ISOLATION | JOB | LABEL | LAST | LESS | LEVEL | LIST | LOCAL | LOCATION | LOGS | LOGICAL | LOW_PRIORITY | LOCK | LOCATIONS | MANUAL | MAP | MAPPING | MAPPINGS | MASKING | MATCH | MAPPINGS | MATERIALIZED | MAX | META | MIN | MINUTE | MINUTES | MODE | MODIFY | MONTH | MERGE | MINUS | MULTIPLE | NAME | NAMES | NEGATIVE | NO | NODE | NODES | NONE | NULLS | NUMBER | NUMERIC | OBSERVER | OF | OFFSET | ONLY | OPTIMIZER | OPEN | OPERATE | OPTION | OVERWRITE | OFF | PARTITIONS | PASSWORD | PATH | PAUSE | PENDING | PERCENTILE_UNION | PIVOT | PLAN | PLUGIN | PLUGINS | POLICY | POLICIES | PERCENT_RANK | PREDICATE | PRECEDING | PRIORITY | PROC | PROCESSLIST | PROFILE | PROFILELIST | PROVIDER | PROVIDERS | PRIVILEGES | PROBABILITY | PROPERTIES | PROPERTY | PIPE | PIPES | QUARTER | QUERY | QUERIES | QUEUE | QUOTA | QUALIFY | REASON | REMOVE | REWRITE | RANDOM | RANK | RECOVER | REFRESH | REPAIR | REPEATABLE | REPLACE_IF_NOT_NULL | REPLICA | REPOSITORY | REPOSITORIES | RESOURCE | RESOURCES | RESTORE | RESUME | RETAIN | RETENTION | RETURNS | RETRY | REVERT | ROLE | ROLES | ROLLUP | ROLLBACK | ROUTINE | ROW | RUNNING | RULE | RULES | SAMPLE | SCHEDULE | SCHEDULER | SECOND | SECURITY | SEPARATOR | SERIALIZABLE |SEMI | SESSION | SETS | SIGNED | SNAPSHOT | SNAPSHOTS | SQLBLACKLIST | START | STARROCKS | STREAM | SUM | STATUS | STOP | SKIP_HEADER | SWAP | STORAGE| STRING | STRUCT | STATS | SUBMIT | SUSPEND | SYNC | SYSTEM_TIME | TABLES | TABLET | TABLETS | TAG | TASK | TEMPORARY | TIMESTAMP | TIMESTAMPADD | TIMESTAMPDIFF | THAN | TIME | TIMES | TRANSACTION | TRACE | TRANSLATE | TRIM_SPACE | TRIGGERS | TRUNCATE | TYPE | TYPES | UNBOUNDED | UNCOMMITTED | UNSET | UNINSTALL | USAGE | USER | USERS | UNLOCK | VALUE | VARBINARY | VARIABLES | VIEW | VIEWS | VERBOSE | VERSION | VOLUME | VOLUMES | WARNINGS | WEEK | WHITELIST | WORK | WRITE | WAREHOUSE | WAREHOUSES | YEAR | DOTDOTDOT | NGRAMBF | VECTOR | FIELD | ARRAY_ELEMENT | PERSISTENT | EXCLUDE | EXCEPT ; ================================================ FILE: superior-starrocks-parser/src/main/java/io/github/melin/superior/parser/starrocks/NodePosition.java ================================================ package io.github.melin.superior.parser.starrocks; import java.io.Serializable; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.TerminalNode; // Used to record element position in the sql. ParserRuleContext records the input start and end token, // and we can transform their line and col info to NodePosition. public class NodePosition implements Serializable { public static final NodePosition ZERO = new NodePosition(0, 0); private static final long serialVersionUID = 5619050719810060066L; private final int line; private final int col; private final int endLine; private final int endCol; public NodePosition(TerminalNode node) { this(node.getSymbol().getLine(), node.getSymbol().getCharPositionInLine()); } public NodePosition(Token token) { this(token.getLine(), token.getLine()); } public NodePosition(Token start, Token end) { this(start.getLine(), start.getCharPositionInLine(), end.getLine(), end.getCharPositionInLine()); } public NodePosition(int line, int col) { this(line, col, line, col); } public NodePosition(int line, int col, int endLine, int endCol) { this.line = line; this.col = col; this.endLine = endLine; this.endCol = endCol; } public int getLine() { return line; } public int getCol() { return col; } public int getEndLine() { return endLine; } public int getEndCol() { return endCol; } public boolean isZero() { return line == 0 && col == 0 && endLine == 0 && endCol == 0; } } ================================================ FILE: superior-starrocks-parser/src/main/java/io/github/melin/superior/parser/starrocks/ParsingException.java ================================================ package io.github.melin.superior.parser.starrocks; import static java.lang.String.format; import org.apache.commons.lang3.StringUtils; public class ParsingException extends RuntimeException { private final String detailMsg; private final NodePosition pos; public ParsingException(String detailMsg, NodePosition pos) { super(detailMsg); this.detailMsg = detailMsg; this.pos = pos; } // error message should contain position info. This method will be removed in the future. public ParsingException(String formatString, Object... args) { this(format(formatString, args), NodePosition.ZERO); } @Override public String getMessage() { StringBuilder builder = new StringBuilder("Getting syntax error"); if (pos == null || pos.isZero()) { // no position info. do nothing. } else if (pos.getLine() == pos.getEndLine() && pos.getCol() == pos.getEndCol()) { builder.append(" "); builder.append(String.format("at line %s, column %s", pos.getLine(), pos.getCol())); } else { builder.append(" "); builder.append(String.format( "from line %s, column %s to line %s, column %s", pos.getLine(), pos.getCol(), pos.getEndLine(), pos.getEndCol())); } if (StringUtils.isNotEmpty(detailMsg)) { builder.append(". Detail message: "); builder.append(detailMsg); builder.append("."); } return builder.toString(); } } ================================================ FILE: superior-starrocks-parser/src/main/java/io/github/melin/superior/parser/starrocks/PostProcessListener.java ================================================ package io.github.melin.superior.parser.starrocks; import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParser; import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParserBaseListener; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.tree.TerminalNode; public class PostProcessListener extends StarRocksParserBaseListener { private final int maxTokensNum; private final int maxExprChildCount; public PostProcessListener(int maxTokensNum, int maxExprChildCount) { this.maxTokensNum = maxTokensNum; this.maxExprChildCount = maxExprChildCount; } @Override public void visitTerminal(TerminalNode node) { Token token = node.getSymbol(); int index = token.getTokenIndex(); if (index >= maxTokensNum) { throw new ParsingException( "Statement exceeds maximum length limit, please consider modify ''parse_tokens_limit'' session variable"); } } @Override public void exitExpressionList(StarRocksParser.ExpressionListContext ctx) { long childCount = ctx.children.stream() .filter(child -> child instanceof StarRocksParser.ExpressionContext) .count(); if (childCount > maxExprChildCount) { NodePosition pos = new NodePosition(ctx.start, ctx.stop); String msg = String.format( "The number of exprs are %s exceeded the maximum limit %s, please consider modify " + "''expr_children_limit'' in BE conf", childCount, maxExprChildCount); throw new ParsingException(msg, pos); } } @Override public void exitExpressionsWithDefault(StarRocksParser.ExpressionsWithDefaultContext ctx) { long childCount = ctx.expressionOrDefault().size(); if (childCount > maxExprChildCount) { NodePosition pos = new NodePosition(ctx.start, ctx.stop); String msg = String.format( "The number of children in expr are %s exceeded the maximum limit %s, please consider modify " + "''expr_children_limit'' in BE conf", childCount, maxExprChildCount); throw new ParsingException(msg, pos); } } @Override public void exitInsertStatement(StarRocksParser.InsertStatementContext ctx) { long childCount = ctx.expressionsWithDefault().size(); if (childCount > maxExprChildCount) { NodePosition pos = new NodePosition(ctx.start, ctx.stop); String msg = String.format( "The inserted rows are {0} exceeded the maximum limit {1}, please consider modify " + "''expr_children_limit'' in BE conf", childCount, maxExprChildCount); throw new ParsingException(msg, pos); } } } ================================================ FILE: superior-starrocks-parser/src/main/java/io/github/melin/superior/parser/starrocks/SqlModeHelper.java ================================================ package io.github.melin.superior.parser.starrocks; public class SqlModeHelper { public static final long MODE_DEFAULT = 32L; public static final long MODE_PIPES_AS_CONCAT = 1L << 1; } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.starrocks import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(StarRocksParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: StarRocksParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(StarRocksParser._ATN)) } } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/StarRocksAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.starrocks import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.* import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.* import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.* import io.github.melin.superior.common.relational.io.AlterLoadTable import io.github.melin.superior.common.relational.io.CancelLoadTable import io.github.melin.superior.common.relational.io.ExportTable import io.github.melin.superior.common.relational.io.LoadTable import io.github.melin.superior.common.relational.table.ColumnRel import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParser.* import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParserBaseVisitor import io.github.melin.superior.parser.starrocks.relational.* import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 9:59 上午 */ class StarRocksAntlr4Visitor(val splitSql: Boolean = false) : StarRocksParserBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var queryStmts: ArrayList = arrayListOf() private var inputTables: ArrayList = arrayListOf() private var outputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() private var functionNames: HashSet = hashSetOf() private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() private var mvRefreshType: String = "Sync" fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitSqlStatements(ctx: SqlStatementsContext): Statement? { ctx.singleStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else if ( StringUtils.equalsIgnoreCase("DESC", startNode) || StringUtils.equalsIgnoreCase("DESCRIBE", startNode) ) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) DescStatement(*keyWords.toTypedArray()) } else { val statement = this.visitSingleStatement(it) if (statement == null) { throw SQLParserException("not support sql") } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() outputTables = arrayListOf() cteTempTables = arrayListOf() functionNames = hashSetOf() } override fun visitCreateExternalCatalogStatement(ctx: CreateExternalCatalogStatementContext): Statement { val catalogName: String = CommonUtils.cleanQuote(ctx.catalogName.text) val properties = parseOptions(ctx.properties()) return CreateCatalog(catalogName, properties) } override fun visitDropExternalCatalogStatement(ctx: DropExternalCatalogStatementContext): Statement { val catalogName: String = CommonUtils.cleanQuote(ctx.catalogName.text) return DropCatalog(catalogName) } override fun visitCreateDbStatement(ctx: CreateDbStatementContext): Statement { val catalogName: String? = if (ctx.catalog != null) CommonUtils.cleanQuote(ctx.catalog.text) else null val databaseName: String = CommonUtils.cleanQuote(ctx.database.text) val properties = parseOptions(ctx.properties()) val ifNotExists = ctx.NOT() != null return CreateDatabase(catalogName, databaseName, properties, ifNotExists) } override fun visitDropDbStatement(ctx: DropDbStatementContext): Statement { val catalogName: String? = if (ctx.catalog != null) CommonUtils.cleanQuote(ctx.catalog.text) else null val databaseName: String = CommonUtils.cleanQuote(ctx.database.text) val ifExists = ctx.EXISTS() != null return DropDatabase(catalogName, databaseName, ifExists) } override fun visitAlterDbQuotaStatement(ctx: AlterDbQuotaStatementContext): Statement { val databaseName: String = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val quota = CommonUtils.cleanQuote(ctx.identifier().get(1).text) val action = AlterDbPropsAction() action.properties.put("quota", quota) return AlterDatabase(AlterActionType.SET_PROPS, databaseName, action) } override fun visitAlterDatabaseRenameStatement(ctx: AlterDatabaseRenameStatementContext): Statement { val databaseName: String = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val newDatabaseName = CommonUtils.cleanQuote(ctx.identifier().get(1).text) val action = RenameDbAction(newDatabaseName) return AlterDatabase(AlterActionType.RENAME, databaseName, action) } override fun visitAlterMaterializedViewStatement(ctx: AlterMaterializedViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) if (ctx.refreshSchemeDesc() != null) { return AlterMaterializedView(tableId, AlterTableAction(AlterActionType.REFRESH_MV)) } else if (ctx.tableRenameClause() != null) { val newName = ctx.tableRenameClause().identifier().text return AlterMaterializedView(tableId, RenameAction(TableId(newName))) } else { val properties = parseOptions(ctx.modifyPropertiesClause().propertyList()) val action = AlterPropsAction() action.properties.putAll(properties) return AlterMaterializedView(tableId, action) } } override fun visitCreateTableStatement(ctx: CreateTableStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val comment = if (ctx.comment() != null) CommonUtils.cleanQuote(ctx.comment().text) else null val columnRels: List = ctx.columnDesc().map { column -> val columnName = column.identifier().text val dataType = column.type().text val colComment = if (column.comment() != null) CommonUtils.cleanQuote(column.comment().string().text) else null ColumnRel(columnName, dataType, colComment) } val keyDesc = ctx.keyDesc() var modelType = "" if (keyDesc != null) { if (keyDesc.DUPLICATE() != null) { modelType = "duplicate" } else if (keyDesc.AGGREGATE() != null) { modelType = "aggregate" } else if (keyDesc.UNIQUE() != null) { modelType = "unique" } else if (keyDesc.PRIMARY() != null) { modelType = "primary" } } var partitionType: PartitionType? = null if (ctx.partitionDesc() != null) { if (ctx.partitionDesc().RANGE() != null) { partitionType = PartitionType.RANGE } else if (ctx.partitionDesc().functionCall() != null) { partitionType = PartitionType.EXPRESSION } else { partitionType = PartitionType.LIST } } val table = CreateTable(tableId, TableType.STARROCKS, comment, columnRels) table.modelType = modelType table.partitionType = partitionType return table } override fun visitCreateTableAsSelectStatement(ctx: CreateTableAsSelectStatementContext): Statement? { val tableId = parseTableName(ctx.qualifiedName()) val comment = if (ctx.comment() != null) CommonUtils.cleanQuote(ctx.comment().text) else null val ifNotExists = ctx.EXISTS() != null val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt val createTable = CreateTableAsSelect(tableId, queryStmt, comment) createTable.ifNotExists = ifNotExists val properties = parseOptions(ctx.properties()) createTable.properties = properties return createTable } override fun visitCreateViewStatement(ctx: CreateViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val comment: String? = if (ctx.comment() != null) CommonUtils.cleanQuote(ctx.comment().string().text) else null val columns = parseColumnNameWithComment(ctx.columnNameWithComment()) val ifNotExists = ctx.NOT() != null val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt val createView = CreateView(tableId, queryStmt, comment, ifNotExists, columns) this.visitQueryStatement(ctx.queryStatement()) return createView } override fun visitCreateMaterializedViewStatement(ctx: CreateMaterializedViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val comment: String? = if (ctx.comment() != null) CommonUtils.cleanQuote(ctx.comment().string().text) else null val columns = parseColumnNameWithComment(ctx.columnNameWithComment()) val ifNotExists = ctx.NOT() != null val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt val createView = CreateMaterializedView(tableId, queryStmt, comment, ifNotExists, columns) ctx.materializedViewDesc().forEach { this.visitMaterializedViewDesc(it) } createView.modelType = mvRefreshType this.visitQueryStatement(ctx.queryStatement()) return createView } override fun visitRefreshSchemeDesc(ctx: RefreshSchemeDescContext): Statement? { if (ctx.ASYNC() != null) { mvRefreshType = "Async" } else if (ctx.MANUAL() != null) { mvRefreshType = "Manual" } else if (ctx.INCREMENTAL() != null) { mvRefreshType = "Incremental" } return null } override fun visitRefreshMaterializedViewStatement(ctx: RefreshMaterializedViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val force: Boolean = ctx.FORCE() != null val mode: String = if (ctx.SYNC() != null) "Sync" else "Async" var partitionStart: String? = null var partitionEnd: String? = null if (ctx.partitionRangeDesc() != null) { val values = ctx.partitionRangeDesc().string() partitionStart = CommonUtils.cleanQuote(values.get(0).text) partitionEnd = CommonUtils.cleanQuote(values.get(1).text) } return RefreshMaterializedView(tableId, force, mode, partitionStart, partitionEnd) } override fun visitCancelRefreshMaterializedViewStatement( ctx: CancelRefreshMaterializedViewStatementContext ): Statement { val tableId = parseTableName(ctx.qualifiedName()) return CancelRefreshMaterializedView(tableId) } override fun visitDropTableStatement(ctx: DropTableStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val ifExists = ctx.EXISTS() != null val dropTable = DropTable(tableId, ifExists) dropTable.force = ctx.FORCE() != null return dropTable } override fun visitDropViewStatement(ctx: DropViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val ifExists = ctx.EXISTS() != null return DropView(tableId, ifExists) } override fun visitDropMaterializedViewStatement(ctx: DropMaterializedViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val ifExists = ctx.EXISTS() != null return DropMaterializedView(tableId, ifExists) } override fun visitCreateIndexStatement(ctx: CreateIndexStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val indexName = ctx.indexName.text val comment = if (ctx.comment() != null) CommonUtils.cleanQuote(ctx.comment().text) else null val columns = ctx.identifierList().identifier().map { identifier -> IndexColumnName(identifier.text) } val createIndex = CreateIndex(indexName) createIndex.comment = comment createIndex.indexColumnNames.addAll(columns) return AlterTable(tableId, createIndex) } override fun visitDropIndexStatement(ctx: DropIndexStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val indexName = ctx.indexName.text val dropIndex = DropIndex(indexName) return AlterTable(tableId, dropIndex) } override fun visitAlterTableStatement(ctx: AlterTableStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) return AlterTable(tableId) } override fun visitAlterViewStatement(ctx: AlterViewStatementContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val queryStmt = this.visitQueryStatement(ctx.queryStatement()) as QueryStmt val action = AlterViewAction(queryStmt) return AlterTable(tableId, action) } override fun visitQueryStatement(ctx: QueryStatementContext): Statement { currentOptType = StatementType.SELECT super.visitQueryRelation(ctx.queryRelation()) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) val querySql = source(ctx) queryStmt.setSql(querySql) queryStmts.add(queryStmt) return queryStmt } override fun visitDeleteStatement(ctx: DeleteStatementContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.qualifiedName()) if (ctx.withClause() != null) { visitWithClause(ctx.withClause()) } visit(ctx.where) if (ctx.relations() != null) { visit(ctx.relations()) } return DeleteTable(tableId, inputTables) } override fun visitUpdateStatement(ctx: UpdateStatementContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableName(ctx.qualifiedName()) if (ctx.withClause() != null) { visitWithClause(ctx.withClause()) } visit(ctx.where) visit(ctx.fromClause()) return UpdateTable(tableId, inputTables) } override fun visitInsertStatement(ctx: InsertStatementContext): Statement { val queryStmt = if (ctx.queryStatement() != null) { this.visitQueryStatement(ctx.queryStatement()) as QueryStmt } else { QueryStmt() } if (ctx.FILES() == null) { val tableId = parseTableName(ctx.qualifiedName()) currentOptType = StatementType.INSERT val insertTable = if (ctx.INTO() != null) InsertTable(InsertMode.INTO, queryStmt, tableId) else InsertTable(InsertMode.OVERWRITE, queryStmt, tableId) if (ctx.expressionsWithDefault().size > 0) { val rows: ArrayList> = ArrayList() ctx.expressionsWithDefault().forEach { var text = it.text text = StringUtils.substringBetween(text, "(", ")").trim() text = CommonUtils.cleanQuote(text) rows.add(listOf(text)) } insertTable.rows = rows } return insertTable } else { val filesProperties = parseOptions(ctx.propertyList()) currentOptType = StatementType.INSERT return if (ctx.INTO() != null) InsertFiles(InsertMode.INTO, queryStmt, filesProperties) else InsertFiles(InsertMode.OVERWRITE, queryStmt, filesProperties) } } override fun visitSubmitTaskStatement(ctx: SubmitTaskStatementContext): Statement { val taskName: String? = if (ctx.qualifiedName() != null) ctx.qualifiedName().text else null if (ctx.insertStatement() != null) { val taskExecSql = source(ctx.insertStatement()) return SubmitTask(taskName, taskExecSql) } else if (ctx.insertStatement() != null) { val taskExecSql = source(ctx.insertStatement()) return SubmitTask(taskName, taskExecSql) } else { val taskExecSql = source(ctx.dataCacheSelectStatement()) return SubmitTask(taskName, taskExecSql) } } override fun visitDropTaskStatement(ctx: DropTaskStatementContext): Statement { val taskName = ctx.qualifiedName().text return DropTask(taskName) } override fun visitCreateRoutineLoadStatement(ctx: CreateRoutineLoadStatementContext): Statement { val catalogName: String? = if (ctx.db != null && ctx.db.identifier().size == 2) CommonUtils.cleanQuote(ctx.db.identifier().get(1).text) else null val schemaName: String? = if (ctx.db != null && ctx.db.identifier().size > 0) CommonUtils.cleanQuote(ctx.db.identifier().get(0).text) else null val jobName = ctx.name.text val tableId = parseTableName(ctx.table) val jobProperties = if (ctx.jobProperties() != null) parseOptions(ctx.jobProperties().properties()) else null val loadPropertiesExpr = source(ctx.loadPropertiesExpr()) val source = ctx.source.text val sourceProperties = if (ctx.dataSourceProperties() != null) parseOptions(ctx.dataSourceProperties().propertyList()) else null return CreateRoutineLoad( catalogName, schemaName, jobName, tableId, loadPropertiesExpr, jobProperties, source, sourceProperties ) } override fun visitAlterRoutineLoadStatement(ctx: AlterRoutineLoadStatementContext): Statement { val catalogName: String? = if (ctx.db != null && ctx.db.identifier().size == 2) CommonUtils.cleanQuote(ctx.db.identifier().get(1).text) else null val schemaName: String? = if (ctx.db != null && ctx.db.identifier().size > 0) CommonUtils.cleanQuote(ctx.db.identifier().get(0).text) else null val jobName = ctx.name.text val jobProperties = if (ctx.jobProperties() != null) parseOptions(ctx.jobProperties().properties()) else null val loadPropertiesExpr = source(ctx.loadPropertiesExpr()) var source: String? = null var sourceProperties: Map? = null if (ctx.dataSource() != null) { source = ctx.dataSource().source.text sourceProperties = parseOptions(ctx.dataSource().dataSourceProperties().propertyList()) } return AlterRoutineLoad( catalogName, schemaName, jobName, loadPropertiesExpr, jobProperties, source, sourceProperties ) } override fun visitPauseRoutineLoadStatement(ctx: PauseRoutineLoadStatementContext): Statement { val catalogName: String? = if (ctx.db != null && ctx.db.identifier().size == 2) CommonUtils.cleanQuote(ctx.db.identifier().get(1).text) else null val schemaName: String? = if (ctx.db != null && ctx.db.identifier().size > 0) CommonUtils.cleanQuote(ctx.db.identifier().get(0).text) else null val jobName = ctx.name.text return PauseRoutineLoad(catalogName, schemaName, jobName) } override fun visitResumeRoutineLoadStatement(ctx: ResumeRoutineLoadStatementContext): Statement { val catalogName: String? = if (ctx.db != null && ctx.db.identifier().size == 2) CommonUtils.cleanQuote(ctx.db.identifier().get(1).text) else null val schemaName: String? = if (ctx.db != null && ctx.db.identifier().size > 0) CommonUtils.cleanQuote(ctx.db.identifier().get(0).text) else null val jobName = ctx.name.text return ResumeRoutineLoad(catalogName, schemaName, jobName) } override fun visitStopRoutineLoadStatement(ctx: StopRoutineLoadStatementContext): Statement { val catalogName: String? = if (ctx.db != null && ctx.db.identifier().size == 2) CommonUtils.cleanQuote(ctx.db.identifier().get(1).text) else null val schemaName: String? = if (ctx.db != null && ctx.db.identifier().size > 0) CommonUtils.cleanQuote(ctx.db.identifier().get(0).text) else null val jobName = ctx.name.text return StopRoutineLoad(catalogName, schemaName, jobName) } override fun visitLoadStatement(ctx: LoadStatementContext): Statement { val schemaName: String? = if (ctx.label.db != null) CommonUtils.cleanQuote(ctx.label.db.text) else null val labelName = ctx.label.label.text val tableNames = arrayListOf() ctx.dataDescList().dataDesc().forEach { it -> if (it.dstTableName != null) { tableNames.add(it.dstTableName.text) } } return LoadTable(schemaName, labelName, tableNames) } override fun visitAlterLoadStatement(ctx: AlterLoadStatementContext): Statement { val schemaName: String? = if (ctx.db != null) CommonUtils.cleanQuote(ctx.db.text) else null val labelName = ctx.identifier().text return AlterLoadTable(schemaName, labelName) } override fun visitCancelLoadStatement(ctx: CancelLoadStatementContext): Statement { val schemaName: String? = if (ctx.FROM() != null) ctx.identifier().text else null val expression: String = ctx.expression().text var labelName: String = StringUtils.substringAfter(expression, "=") labelName = CommonUtils.cleanQuote(labelName.trim()) return CancelLoadTable(schemaName, labelName) } override fun visitExportStatement(ctx: ExportStatementContext): Statement { val tableId = parseTableName(ctx.tableDesc().qualifiedName()) val filePath = CommonUtils.cleanQuote(ctx.string().text) val properties = parseOptions(ctx.properties()) return ExportTable(tableId, filePath, properties) } override fun visitCancelExportStatement(ctx: CancelExportStatementContext): Statement { val database: String? = if (ctx.catalog != null) ctx.catalog.text else null val expr = ctx.expression().text var queryId: String = StringUtils.substringBetween(expr, "\"", "\"") if (StringUtils.isBlank(queryId)) { queryId = StringUtils.substringBetween(expr, "'", "'") } return CancelExport(database, queryId) } override fun visitCreateFunctionStatement(ctx: CreateFunctionStatementContext): Statement { val functionId = parseTableName(ctx.qualifiedName()) val global = ctx.GLOBAL() != null val properties = parseOptions(ctx.properties()) val argumentTypes = parseTypeList(ctx.typeList()) val createFunction = CreateFunction( FunctionId(functionId.schemaName, functionId.tableName), arrayListOf(), ) createFunction.global = global createFunction.properties = properties createFunction.argumentTypes = argumentTypes createFunction.returnType = ctx.returnType.text return createFunction } override fun visitDropFunctionStatement(ctx: DropFunctionStatementContext): Statement { val functionId = parseTableName(ctx.qualifiedName()) val argumentTypes = parseTypeList(ctx.typeList()) val dropFunction = DropFunction(FunctionId(functionId.schemaName, functionId.tableName)) dropFunction.argumentTypes = argumentTypes return dropFunction } override fun visitQualifiedName(ctx: QualifiedNameContext): Statement? { if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.CREATE_TABLE_AS_SELECT || currentOptType == StatementType.CREATE_VIEW || currentOptType == StatementType.CREATE_MATERIALIZED_VIEW || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.MERGE || currentOptType == StatementType.INSERT || currentOptType == StatementType.CREATE_FUNCTION ) { val tableId = parseTableName(ctx) if (!inputTables.contains(tableId) && !cteTempTables.contains(tableId)) { inputTables.add(tableId) } } return null } override fun visitSimpleFunctionCall(ctx: SimpleFunctionCallContext): Statement? { if ( StatementType.SELECT == currentOptType || StatementType.CREATE_VIEW == currentOptType || StatementType.CREATE_MATERIALIZED_VIEW == currentOptType || StatementType.INSERT == currentOptType || StatementType.CREATE_TABLE_AS_SELECT == currentOptType ) { val names = ctx.qualifiedName().identifier() if (names.size == 3) { val catalog = StringUtils.lowerCase(names.get(0).text) val schema = StringUtils.lowerCase(names.get(1).text) val funcName = StringUtils.lowerCase(names.get(2).text) functionNames.add(FunctionId(catalog, schema, funcName)) } else if (names.size == 2) { val schema = StringUtils.lowerCase(names.get(0).text) val funcName = StringUtils.lowerCase(names.get(1).text) functionNames.add(FunctionId(schema, funcName)) } else if (names.size == 1) { val funcName = StringUtils.lowerCase(names.get(0).text) functionNames.add(FunctionId(funcName)) } } return null } override fun visitAggregationFunctionCall(ctx: AggregationFunctionCallContext): Statement? { if ( StatementType.SELECT == currentOptType || StatementType.CREATE_VIEW == currentOptType || StatementType.CREATE_MATERIALIZED_VIEW == currentOptType || StatementType.INSERT == currentOptType || StatementType.CREATE_TABLE_AS_SELECT == currentOptType ) { val funcName = ctx.aggregationFunction().getChild(0).text.lowercase() functionNames.add(FunctionId(funcName)) } return null } override fun visitSubqueryWithAlias(ctx: SubqueryWithAliasContext): Statement? { return this.visitSubquery(ctx.subquery()) } override fun visitSelectAll(ctx: SelectAllContext): Statement? { return null; } override fun visitWithClause(ctx: WithClauseContext): Statement? { ctx.commonTableExpression().forEach { cteTempTables.add(TableId(it.name.text)) } return super.visitWithClause(ctx) } override fun visitLimitElement(ctx: LimitElementContext): Statement? { if (ctx.limit != null) { limit = ctx.limit.text.toInt() } if (ctx.offset != null) { offset = ctx.offset.text.toInt() } return super.visitLimitElement(ctx) } fun parseTableName(ctx: QualifiedNameContext): TableId { return if (ctx.identifier().size == 3 || ctx.children.size == 4) { if (ctx.identifier().size == 3) { val catalotName = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val schemaName = CommonUtils.cleanQuote(ctx.identifier().get(1).text) val tableName = CommonUtils.cleanQuote(ctx.identifier().get(2).text) TableId(catalotName, schemaName, tableName) } else { // hive.bigdata.1v1_users 表名数字开头场景 val catalotName = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val schemaName = CommonUtils.cleanQuote(ctx.identifier().get(1).text) val tableName = ctx.getChild(3).text.substring(1) TableId(catalotName, schemaName, tableName) } } else if (ctx.identifier().size == 2 || ctx.children.size == 2) { if (ctx.identifier().size == 2) { val schemaName = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val tableName = CommonUtils.cleanQuote(ctx.identifier().get(1).text) TableId(schemaName, tableName) } else { // bigdata.1v1_users 表名数字开头场景 val schemaName = CommonUtils.cleanQuote(ctx.identifier().get(0).text) val tableName = ctx.getChild(1).text.substring(1) TableId(schemaName, tableName) } } else if (ctx.identifier().size == 1) { val tableName = CommonUtils.cleanQuote(ctx.identifier().get(0).text) TableId(tableName) } else { throw SQLParserException("parse qualifiedName error: " + ctx.identifier().size) } } private fun parseOptions(ctx: PropertiesContext?): Map { val properties = HashMap() if (ctx != null) { ctx.property().forEach { item -> val property = item as PropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } } return properties } private fun parseColumnNameWithComment(columns: List): List { return columns.map { col -> val name = col.columnName.text val comment = CommonUtils.cleanQuote(col.comment().string().text) ColumnRel(name, null, comment) } } private fun parseOptions(ctx: PropertyListContext?): Map { val properties = HashMap() if (ctx != null) { ctx.property().forEach { item -> val property = item as PropertyContext val key = CommonUtils.cleanQuote(property.key.text) val value = CommonUtils.cleanQuote(property.value.text) properties.put(key, value) } } return properties } private fun parseTypeList(ctx: TypeListContext?): List { val types = java.util.ArrayList() if (ctx != null) { ctx.type().forEach { item -> val type = item as TypeContext types.add(type.text) } if (ctx.DOTDOTDOT() != null) { types.add(ctx.DOTDOTDOT().text) } } return types } } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/StarRocksHelper.kt ================================================ package io.github.melin.superior.parser.starrocks import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.antlr4.UpperCaseCharStream import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.starrocks.antlr4.StarRocksLexer import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParser import io.github.melin.superior.parser.starrocks.antlr4.StarRocksParserBaseVisitor import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2020/6/30 10:01 上午 */ object StarRocksHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until StarRocksLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = StarRocksLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = StarRocksAntlr4Visitor(false) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = StarRocksAntlr4Visitor(true) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = StarRocksParserBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: StarRocksParserBaseVisitor) { val charStream = UpperCaseCharStream(CharStreams.fromString(command)) val lexer = StarRocksLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = StarRocksParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.addParseListener(PostProcessListener(3500000, 10000)) try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. sqlVisitor.visit(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/AlterRoutineLoad.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class AlterRoutineLoad( val catalogName: String?, val schemaName: String?, val jobName: String, val loadPropertiesExpr: String, val jobProperties: Map?, val source: String?, val sourceProperties: Map? ) : Statement() { override val statementType = StatementType.SR_ALTER_ROUTINE_LOAD override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/CancelRefreshMaterializedView.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class CancelRefreshMaterializedView(val tableId: TableId) : Statement() { override val statementType = StatementType.CANCEL_REFRESH_MV override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/CreateRoutineLoad.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId data class CreateRoutineLoad( val catalogName: String?, val schemaName: String?, val jobName: String, val tableId: TableId, val loadPropertiesExpr: String, val jobProperties: Map?, val source: String, val sourceProperties: Map? ) : Statement() { override val statementType = StatementType.SR_CREATE_ROUTINE_LOAD override val privilegeType = PrivilegeType.CREATE override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/DropTask.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class DropTask(val taskName: String) : Statement() { override val statementType = StatementType.SR_DROP_TASK override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/PauseRoutineLoad.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class PauseRoutineLoad(val catalogName: String?, val schemaName: String?, val jobName: String) : Statement() { override val statementType = StatementType.SR_PAUSE_ROUTINE_LOAD override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/ResumeRoutineLoad.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class ResumeRoutineLoad(val catalogName: String?, val schemaName: String?, val jobName: String) : Statement() { override val statementType = StatementType.SR_RESUME_ROUTINE_LOAD override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/StopRoutineLoad.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class StopRoutineLoad(val catalogName: String?, val schemaName: String?, val jobName: String) : Statement() { override val statementType = StatementType.SR_STOP_ROUTINE_LOAD override val privilegeType = PrivilegeType.ADMIN override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/main/kotlin/io/github/melin/superior/parser/starrocks/relational/SubmitTask.kt ================================================ package io.github.melin.superior.parser.starrocks.relational import io.github.melin.superior.common.PrivilegeType import io.github.melin.superior.common.SqlType import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.Statement data class SubmitTask(val taskName: String?, val taskExecSql: String) : Statement() { override val statementType = StatementType.SR_SUBMIT_TASK override val privilegeType = PrivilegeType.OTHER override val sqlType = SqlType.DML } ================================================ FILE: superior-starrocks-parser/src/test/kotlin/io/github/melin/superior/parser/starrocks/StarRocksSqlParserDdlTest.kt ================================================ package io.github.melin.superior.parser.starrocks import io.github.melin.superior.common.StatementType.* import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.PartitionType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.alter.* import io.github.melin.superior.common.relational.common.RefreshMaterializedView import io.github.melin.superior.common.relational.create.* import io.github.melin.superior.common.relational.drop.* import io.github.melin.superior.parser.starrocks.relational.CancelRefreshMaterializedView import org.junit.Assert import org.junit.Test class StarRocksSqlParserDdlTest { @Test fun createCatalogTest() { val sql = """ CREATE EXTERNAL CATALOG iceberg_metastore_catalog PROPERTIES( "type"="iceberg", "iceberg.catalog.type"="hive", "iceberg.catalog.hive.metastore.uris"="thrift://x.x.x.x:9083" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateCatalog) { Assert.assertEquals(CREATE_CATALOG, statement.statementType) Assert.assertEquals("iceberg_metastore_catalog", statement.catalogName) } else { Assert.fail() } } @Test fun dropCatalogTest() { val sql = """ DROP CATALOG iceberg_metastore_catalog; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropCatalog) { Assert.assertEquals(DROP_CATALOG, statement.statementType) Assert.assertEquals("iceberg_metastore_catalog", statement.catalogName) } else { Assert.fail() } } @Test fun createDatabaseTest() { val sql = """ CREATE DATABASE IF Not EXISTS db_test; Drop DATABASE IF EXISTS db_test1; """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) val createDatabse = statements.get(0) val dropDatabase = statements.get(1) if (createDatabse is CreateDatabase) { Assert.assertEquals("db_test", createDatabse.databaseName) } if (dropDatabase is CreateDatabase) { Assert.assertEquals("db_test1", dropDatabase.databaseName) } } @Test fun dropDatabaseTest() { val sql = """ DROP DATABASE IF EXISTS db_test; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropDatabase) { Assert.assertEquals(DROP_DATABASE, statement.statementType) Assert.assertEquals("db_test", statement.databaseName) } else { Assert.fail() } } @Test fun alterDatabaseTest() { val sql = """ ALTER DATABASE example_db SET DATA QUOTA 100G; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterDatabase) { Assert.assertEquals(ALTER_DATABASE, statement.statementType) Assert.assertEquals("example_db", statement.databaseName) } else { Assert.fail() } } @Test fun renameDatabaseTest() { val sql = """ ALTER DATABASE example_db RENAME example_db2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterDatabase) { Assert.assertEquals(ALTER_DATABASE, statement.statementType) Assert.assertEquals("example_db", statement.databaseName) val action = statement.firstAction() as RenameDbAction Assert.assertEquals("example_db2", action.newDatabaseName) } else { Assert.fail() } } @Test fun createTableTest() { val sql = """ create table meta_role ( id int not null, tenant_id int null comment '租户ID', code varchar(255) null comment '角色code, 字母数字和下划线', name varchar(255) null comment '角色名称,一般为中文', type varchar(32) not null comment '角色类型:superadmin、workspaceadmin、dataadmin、custom', order_index int null, creater varchar(45) null, modifier varchar(45) null, gmt_created datetime null, gmt_modified datetime null ) ENGINE = olap PRIMARY KEY(id) DISTRIBUTED BY HASH (id) BUCKETS 10; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(CREATE_TABLE, statement.statementType) Assert.assertEquals("meta_role", statement.tableId.tableName) Assert.assertEquals("primary", statement.modelType) } else { Assert.fail() } } @Test fun createTableTest0() { val sql = """ CREATE TABLE site_access1 ( event_day DATETIME NOT NULL, site_id INT DEFAULT '10', city_code VARCHAR(100), user_name VARCHAR(32) DEFAULT '', pv BIGINT DEFAULT '0' ) DUPLICATE KEY(event_day, site_id, city_code, user_name) PARTITION BY date_trunc('day', event_day) DISTRIBUTED BY HASH(event_day, site_id); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateTable) { Assert.assertEquals(CREATE_TABLE, statement.statementType) Assert.assertEquals("site_access1", statement.tableId.tableName) Assert.assertEquals("duplicate", statement.modelType) Assert.assertEquals(PartitionType.EXPRESSION, statement.partitionType) } else { Assert.fail() } } @Test fun dropTableTest() { val sql = """ DROP TABLE IF EXISTS example_db.My_table force; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(DROP_TABLE, statement.statementType) Assert.assertEquals(TableId("example_db", "My_table"), statement.tableId) Assert.assertTrue(statement.force) } else { Assert.fail() } } @Test fun createViewTest() { val sql = """ CREATE VIEW example_db.example_view ( k1 COMMENT "first key", k2 COMMENT "second key", k3 COMMENT "third key", v1 COMMENT "first value" ) COMMENT "my first view" AS SELECT c1 as k1, k2, k3, SUM(v1) FROM example_table WHERE k1 = 20160112 GROUP BY k1,k2,k3; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateView) { Assert.assertEquals(CREATE_VIEW, statement.statementType) Assert.assertEquals("my first view", statement.comment) Assert.assertEquals(4, statement.columnRels?.size) Assert.assertEquals(TableId("example_db", "example_view"), statement.tableId) Assert.assertEquals(TableId("example_table"), statement.queryStmt.inputTables.get(0)) } else { Assert.fail() } } @Test fun dropViewTest() { val sql = """ DROP VIEW IF EXISTS example_db.example_view; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropView) { Assert.assertEquals(DROP_VIEW, statement.statementType) Assert.assertEquals(TableId("example_db", "example_view"), statement.tableId) } else { Assert.fail() } } @Test fun createMaterializedViewTest() { val sql = """ CREATE MATERIALIZED VIEW example_db.lo_mv1 DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 10 REFRESH ASYNC AS select lo_orderkey, lo_custkey, sum(lo_quantity) as total_quantity, sum(lo_revenue) as total_revenue, count(lo_shipmode) as shipmode_count from lineorder group by lo_orderkey, lo_custkey order by lo_orderkey; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateMaterializedView) { Assert.assertEquals(CREATE_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals("Async", statement.modelType) Assert.assertEquals(TableId("example_db", "lo_mv1"), statement.tableId) Assert.assertEquals(TableId("lineorder"), statement.queryStmt.inputTables.get(0)) } else { Assert.fail() } } @Test fun dropMaterializedViewTest() { val sql = """ DROP MATERIALIZED VIEW IF EXISTS k1_k2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropMaterializedView) { Assert.assertEquals(DROP_MATERIALIZED_VIEW, statement.statementType) Assert.assertEquals(TableId("k1_k2"), statement.tableId) } else { Assert.fail() } } @Test fun alterMaterializedViewTest() { val sql = """ ALTER MATERIALIZED VIEW lo_mv1 RENAME lo_mv1_new_name; ALTER MATERIALIZED VIEW lo_mv2 REFRESH ASYNC EVERY(INTERVAL 1 DAY); ALTER MATERIALIZED VIEW mv1 SET ("session.query_timeout" = "40000"); """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) Assert.assertEquals(3, statements.size) } @Test fun refreshMaterializedViewTest() { val sql = """ REFRESH MATERIALIZED VIEW lo_mv1 PARTITION START ("2020-02-01") END ("2020-03-01") FORCE; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is RefreshMaterializedView) { Assert.assertEquals(REFRESH_MV, statement.statementType) Assert.assertEquals("lo_mv1", statement.tableId.tableName) Assert.assertEquals("2020-02-01", statement.partitionStart) Assert.assertEquals("2020-03-01", statement.partitionEnd) Assert.assertTrue(statement.force) Assert.assertEquals("Async", statement.mode) } } @Test fun cancelRefreshMaterializedViewTest() { val sql = """ CANCEL REFRESH MATERIALIZED VIEW lo_mv1; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CancelRefreshMaterializedView) { Assert.assertEquals(CANCEL_REFRESH_MV, statement.statementType) Assert.assertEquals("lo_mv1", statement.tableId.tableName) } } @Test fun createIndexTest() { val sql = """ CREATE INDEX index3 ON sales_records (item_id) USING BITMAP COMMENT ''; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(ALTER_TABLE, statement.statementType) val createIndex = statement.firstAction() as CreateIndex Assert.assertEquals("index3", createIndex.indexName) Assert.assertEquals("sales_records", statement.tableId.tableName) Assert.assertEquals(1, createIndex.indexColumnNames.size) } else { Assert.fail() } } @Test fun dropIndexTest() { val sql = """ DROP INDEX index3 ON sales_records; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterTable) { Assert.assertEquals(ALTER_TABLE, statement.statementType) val dropIndex = statement.firstAction() as DropIndex Assert.assertEquals("index3", dropIndex.indexName) Assert.assertEquals("sales_records", statement.tableId.tableName) } else { Assert.fail() } } @Test fun createFuncTest() { val sql = """ CREATE GLOBAL FUNCTION MY_UDF_JSON_GET(string, string) RETURNS string properties ( "symbol" = "com.starrocks.udf.sample.UDFJsonGet", "type" = "StarrocksJar", "file" = "http://http_host:http_port/udf-1.0-SNAPSHOT-jar-with-dependencies.jar" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateFunction) { Assert.assertEquals(CREATE_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("MY_UDF_JSON_GET"), statement.functionId) Assert.assertEquals("string", statement.returnType) Assert.assertEquals(2, statement.argumentTypes?.size) Assert.assertEquals(3, statement.properties?.size) } else { Assert.fail() } } @Test fun dropFuncTest() { val sql = """ DROP GLOBAL FUNCTION MY_UDF_JSON_GET(string, string) """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DropFunction) { Assert.assertEquals(DROP_FUNCTION, statement.statementType) Assert.assertEquals(FunctionId("MY_UDF_JSON_GET"), statement.functionId) Assert.assertEquals(2, statement.argumentTypes?.size) } else { Assert.fail() } } } ================================================ FILE: superior-starrocks-parser/src/test/kotlin/io/github/melin/superior/parser/starrocks/StarRocksSqlParserDmlTest.kt ================================================ package io.github.melin.superior.parser.starrocks import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.parser.starrocks.relational.DropTask import io.github.melin.superior.parser.starrocks.relational.SubmitTask import org.junit.Assert import org.junit.Test class StarRocksSqlParserDmlTest { @Test fun selectTest0() { val sql = """ SELECT * FROM hive1.hive_db.hive_table limit 10 offset 20; select hello('test', 23) """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) Assert.assertEquals(2, statements.size) val statement = statements.get(0) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(10, statement.limit) Assert.assertEquals(20, statement.offset) Assert.assertEquals(TableId("hive1", "hive_db", "hive_table"), statement.inputTables.get(0)) } else { Assert.fail() } val statement1 = statements.get(1) if (statement1 is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement1.statementType) Assert.assertEquals(0, statement1.inputTables.size) } else { Assert.fail() } } @Test fun selectTest1() { val sql = """ with t1 as (select * from bigdata.users), t2 as (select 2) select * from t1 union all select * from t2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("bigdata", "users"), statement.inputTables.get(0)) } else { Assert.fail() } } @Test fun deleteTest0() { val sql = """ DELETE FROM my_table PARTITION p1 WHERE k1 = 3; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("my_table", statement.tableId.tableName) Assert.assertEquals(0, statement.inputTables.size) } else { Assert.fail() } } @Test fun deleteTest1() { val sql = """ DELETE FROM score_board WHERE name IN (select name from users where country = "China"); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("score_board", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("users", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun deleteTest2() { val sql = """ WITH foo_producers as ( SELECT * from producers where producers.name = 'foo' ) DELETE FROM films USING foo_producers WHERE producer_id = foo_producers.id; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("films", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("producers", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun updateTest1() { val sql = """ UPDATE employees SET sales_count = sales_count + 1 FROM accounts WHERE accounts.name = 'Acme Corporation' AND employees.id = accounts.sales_person; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("accounts", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun updateTest2() { val sql = """ WITH acme_accounts as ( SELECT * from accounts WHERE accounts.name = 'Acme Corporation' ) UPDATE employees SET sales_count = sales_count + 1 FROM acme_accounts WHERE employees.id = acme_accounts.sales_person; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is UpdateTable) { Assert.assertEquals(StatementType.UPDATE, statement.statementType) Assert.assertEquals("employees", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals("accounts", statement.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun insertTest1() { val sql = """ INSERT INTO test SELECT * FROM test2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("test", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) Assert.assertEquals("test2", statement.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun insertTest2() { val sql = """ INSERT INTO test PARTITION(p1, p2) WITH LABEL `label1` SELECT * FROM test2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("test", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) Assert.assertEquals("test2", statement.queryStmt.inputTables.get(0).tableName) } else { Assert.fail() } } @Test fun insertTest3() { val sql = """ INSERT INTO test.`table1` VALUES (1, "test", 23) """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("table1", statement.tableId.tableName) Assert.assertEquals(0, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest4() { val sql = """ INSERT OVERWRITE FILES( "path" = "s3://test/test.parquest", "format" = "parquet", "compression" = "uncompressed", "target_max_file_size" = "10240", -- 1M "aws.s3.access_key" = "test_access_key", "aws.s3.secret_key" = "test_secret_key", "aws.s3.region" = "test-region-1" ) SELECT * FROM test_db.test_table; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is InsertFiles) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(7, statement.properties.size) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun insertTest5() { val sql = """ INSERT INTO target_table (id, cnt) SELECT u.id, COUNT(o.order_id) FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100 GROUP BY u.id """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals(2, statement.queryStmt.inputTables.size) Assert.assertEquals(1, statement.queryStmt.functionNames.size) } else { Assert.fail() } } @Test fun showTest() { val sql = """ SHOW CREATE MATERIALIZED VIEW lo_mv1; SHOW CREATE TABLE example_db.example_table; SHOW DELETE FROM bigdata; """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) Assert.assertEquals(3, statements.size) val statement = statements.get(2) as ShowStatement Assert.assertTrue(statement.checkSql("SHOW DELETE FROM")) Assert.assertFalse(statement.checkSql("SHOW DELETE")) } @Test fun taskTest() { val sql = """ SUBMIT /*+set_var(query_timeout=100000)*/ TASK test1 AS INSERT OVERWRITE insert_wiki_edit SELECT * FROM source_wiki_edit; DROP TASK test1 """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) Assert.assertEquals(2, statements.size) val submitTask = statements.get(0) as SubmitTask Assert.assertEquals("test1", submitTask.taskName) val dropTask = statements.get(1) as DropTask Assert.assertEquals("test1", dropTask.taskName) } @Test fun ctasTest() { val sql = """ CREATE TABLE order_new (a, b, c) AS SELECT k1, k2, k3 FROM orders; """ .trimIndent() val statements = StarRocksHelper.parseMultiStatement(sql) Assert.assertEquals(1, statements.size) val statement = statements.get(0) as CreateTableAsSelect Assert.assertEquals("order_new", statement.tableId.tableName) Assert.assertEquals("orders", statement.queryStmt.inputTables.get(0).tableName) } // 排除表别名 @Test fun selectTest() { val sql = """ select t1.* from ( select * from `default`.person ) t1 """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } // 校验数字开头表 @Test fun select1Test() { val sql = """ SELECT * FROM users.1v1_user """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("users", "1v1_user"), statement.inputTables.get(0)) } else { Assert.fail() } } // 校验数字开头表 @Test fun select2Test() { val sql = """ SELECT * FROM hive.users.1v1_user """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(TableId("hive", "users", "1v1_user"), statement.inputTables.get(0)) } else { Assert.fail() } } } ================================================ FILE: superior-starrocks-parser/src/test/kotlin/io/github/melin/superior/parser/starrocks/StarRocksSqlParserLoadAndExportTest.kt ================================================ package io.github.melin.superior.parser.starrocks import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.* import io.github.melin.superior.common.relational.io.AlterLoadTable import io.github.melin.superior.common.relational.io.CancelLoadTable import io.github.melin.superior.common.relational.io.ExportTable import io.github.melin.superior.common.relational.io.LoadTable import io.github.melin.superior.parser.starrocks.relational.* import org.junit.Assert import org.junit.Test class StarRocksSqlParserLoadAndExportTest { @Test fun createRoutineLoadTest() { val sql = """ CREATE ROUTINE LOAD example_db.example_tbl1_ordertest1 ON example_tbl1 COLUMNS TERMINATED BY ",", COLUMNS (order_id, pay_dt, customer_name, nationality, temp_gender, price) PROPERTIES ( "desired_concurrent_number" = "5" ) FROM KAFKA ( "kafka_broker_list" = "172.18.5.44:9092", "kafka_topic" = "ordertest1", "property.kafka_default_offsets" = "OFFSET_BEGINNING" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateRoutineLoad) { Assert.assertEquals(StatementType.SR_CREATE_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertEquals("example_db", statement.schemaName) Assert.assertEquals("example_tbl1_ordertest1", statement.jobName) Assert.assertEquals(TableId("example_tbl1"), statement.tableId) Assert.assertEquals("KAFKA", statement.source) } else { Assert.fail() } } @Test fun alterRoutineLoadTest() { val sql = """ ALTER ROUTINE LOAD FOR example_tbl2_ordertest2 PROPERTIES ( "desired_concurrent_number" = "6" ) FROM kafka ( "kafka_partitions" = "0,1,2,3,4,5,6,7", "kafka_offsets" = "OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_END,OFFSET_END,OFFSET_END,OFFSET_END" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterRoutineLoad) { Assert.assertEquals(StatementType.SR_ALTER_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) Assert.assertEquals("kafka", statement.source) } else { Assert.fail() } } @Test fun pauseRoutineLoadTest() { val sql = """ PAUSE ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is PauseRoutineLoad) { Assert.assertEquals(StatementType.SR_PAUSE_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } @Test fun resumeRoutineLoadTest() { val sql = """ RESUME ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is ResumeRoutineLoad) { Assert.assertEquals(StatementType.SR_RESUME_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } @Test fun stopRoutineLoadTest() { val sql = """ STOP ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is StopRoutineLoad) { Assert.assertEquals(StatementType.SR_STOP_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } @Test fun createLoadTest() { val sql = """ LOAD LABEL test_db.label_brokerload_multiplefile_multipletable ( DATA INFILE("hdfs://:/user/starrocks/file1.csv") INTO TABLE table1 COLUMNS TERMINATED BY "," (id, name, score), DATA INFILE("hdfs://:/user/starrocks/file2.csv") INTO TABLE table2 COLUMNS TERMINATED BY "," (id, name, score) ) PROPERTIES ( "timeout" = "3600" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is LoadTable) { Assert.assertEquals(StatementType.LOAD_TABLE, statement.statementType) Assert.assertEquals("test_db", statement.schemaName) Assert.assertEquals("label_brokerload_multiplefile_multipletable", statement.labelName) Assert.assertEquals(2, statement.tableNames.size) Assert.assertEquals("table1", statement.tableNames.get(0)) } else { Assert.fail() } } @Test fun cancelLoadTest() { val sql = """ CANCEL LOAD FROM db1 WHERE LABEL = "label"; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CancelLoadTable) { Assert.assertEquals(StatementType.CANCEL_LOAD_TABLE, statement.statementType) Assert.assertEquals("db1", statement.schemaName) Assert.assertEquals("label", statement.labelName) } else { Assert.fail() } } @Test fun alterLoadTest() { val sql = """ ALTER LOAD FOR test_db.label1 properties ( 'priority'='HIGHEST' ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterLoadTable) { Assert.assertEquals(StatementType.ALTER_LOAD_TABLE, statement.statementType) Assert.assertEquals("test_db", statement.schemaName) Assert.assertEquals("label1", statement.labelName) } else { Assert.fail() } } @Test fun createExportTest() { val sql = """ EXPORT TABLE testTbl TO "s3a://s3-package/export/" WITH BROKER ( "aws.s3.access_key" = "xxx", "aws.s3.secret_key" = "yyy", "aws.s3.region" = "zzz" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is ExportTable) { Assert.assertEquals(StatementType.EXPORT_TABLE, statement.statementType) Assert.assertEquals("testTbl", statement.tableId.tableName) Assert.assertEquals("s3a://s3-package/export/", statement.path) } else { Assert.fail() } } @Test fun cancelExportTest() { val sql = """ CANCEL Export FROM example_db WHERE queryid = "921d8f80-7c9d-11eb-9342-acde48001121"; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CancelExport) { Assert.assertEquals(StatementType.CANCEL_EXPORT, statement.statementType) Assert.assertEquals("example_db", statement.database) Assert.assertEquals("921d8f80-7c9d-11eb-9342-acde48001121", statement.queryId) } else { Assert.fail() } } } ================================================ FILE: superior-starrocks-parser/src/test/kotlin/io/github/melin/superior/parser/starrocks/StarRocksSqlParserRoutineLoadTest.kt ================================================ package io.github.melin.superior.parser.starrocks import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.parser.starrocks.relational.* import org.junit.Assert import org.junit.Test class StarRocksSqlParserRoutineLoadTest { @Test fun createRoutineLoadTest() { val sql = """ CREATE ROUTINE LOAD example_db.example_tbl1_ordertest1 ON example_tbl1 COLUMNS TERMINATED BY ",", COLUMNS (order_id, pay_dt, customer_name, nationality, temp_gender, price) PROPERTIES ( "desired_concurrent_number" = "5" ) FROM KAFKA ( "kafka_broker_list" = "172.18.5.44:9092", "kafka_topic" = "ordertest1", "property.kafka_default_offsets" = "OFFSET_BEGINNING" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is CreateRoutineLoad) { Assert.assertEquals(StatementType.SR_CREATE_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertEquals("example_db", statement.schemaName) Assert.assertEquals("example_tbl1_ordertest1", statement.jobName) Assert.assertEquals(TableId("example_tbl1"), statement.tableId) Assert.assertEquals("KAFKA", statement.source) } else { Assert.fail() } } @Test fun alterRoutineLoadTest() { val sql = """ ALTER ROUTINE LOAD FOR example_tbl2_ordertest2 PROPERTIES ( "desired_concurrent_number" = "6" ) FROM kafka ( "kafka_partitions" = "0,1,2,3,4,5,6,7", "kafka_offsets" = "OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_BEGINNING,OFFSET_END,OFFSET_END,OFFSET_END,OFFSET_END" ); """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is AlterRoutineLoad) { Assert.assertEquals(StatementType.SR_ALTER_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) Assert.assertEquals("kafka", statement.source) } else { Assert.fail() } } @Test fun pauseRoutineLoadTest() { val sql = """ PAUSE ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is PauseRoutineLoad) { Assert.assertEquals(StatementType.SR_PAUSE_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } @Test fun resumeRoutineLoadTest() { val sql = """ RESUME ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is ResumeRoutineLoad) { Assert.assertEquals(StatementType.SR_RESUME_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } @Test fun stopRoutineLoadTest() { val sql = """ STOP ROUTINE LOAD FOR example_tbl2_ordertest2; """ .trimIndent() val statement = StarRocksHelper.parseStatement(sql) if (statement is StopRoutineLoad) { Assert.assertEquals(StatementType.SR_STOP_ROUTINE_LOAD, statement.statementType) Assert.assertNull(statement.catalogName) Assert.assertNull(statement.schemaName) Assert.assertEquals("example_tbl2_ordertest2", statement.jobName) } else { Assert.fail() } } } ================================================ FILE: superior-starrocks-parser/src/test/resources/log4j2.xml ================================================ ================================================ FILE: superior-trino-parser/pom.xml ================================================ 4.0.0 io.github.melin.superior superior-sql-parser 4.0.23 superior-trino-parser superior-trino-parser io.github.melin.superior superior-common-parser ${project.version} ================================================ FILE: superior-trino-parser/src/main/antlr4/io/github/melin/superior/parser/trino/antlr4/TrinoSqlBase.g4 ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ grammar TrinoSqlBase; tokens { DELIMITER } sqlStatements : singleStatement* EOF ; singleStatement : statement ';'? ; standaloneExpression : expression EOF ; standalonePathSpecification : pathSpecification EOF ; standaloneType : type EOF ; standaloneRowPattern : rowPattern EOF ; standaloneFunctionSpecification : functionSpecification EOF ; statement : rootQuery #statementDefault | USE schema=identifier #use | USE catalog=identifier '.' schema=identifier #use | CREATE CATALOG (IF NOT EXISTS)? catalog=identifier USING connectorName=identifier (COMMENT string)? (AUTHORIZATION principal)? (WITH properties)? #createCatalog | DROP CATALOG (IF EXISTS)? catalog=identifier (CASCADE | RESTRICT)? #dropCatalog | CREATE SCHEMA (IF NOT EXISTS)? qualifiedName (AUTHORIZATION principal)? (WITH properties)? #createSchema | DROP SCHEMA (IF EXISTS)? qualifiedName (CASCADE | RESTRICT)? #dropSchema | ALTER SCHEMA qualifiedName RENAME TO identifier #renameSchema | ALTER SCHEMA qualifiedName SET AUTHORIZATION principal #setSchemaAuthorization | CREATE (OR REPLACE)? TABLE (IF NOT EXISTS)? qualifiedName columnAliases? (COMMENT string)? (WITH properties)? AS (rootQuery | '('rootQuery')') (WITH (NO)? DATA)? #createTableAsSelect | CREATE (OR REPLACE)? TABLE (IF NOT EXISTS)? qualifiedName '(' tableElement (',' tableElement)* ')' (COMMENT string)? (WITH properties)? #createTable | DROP TABLE (IF EXISTS)? qualifiedName #dropTable | INSERT INTO qualifiedName columnAliases? rootQuery #insertInto | DELETE FROM qualifiedName (whereClause)? #delete | TRUNCATE TABLE qualifiedName #truncateTable | COMMENT ON TABLE qualifiedName IS (string | NULL) #commentTable | COMMENT ON VIEW qualifiedName IS (string | NULL) #commentView | COMMENT ON COLUMN qualifiedName IS (string | NULL) #commentColumn | ALTER TABLE (IF EXISTS)? from=qualifiedName RENAME TO to=qualifiedName #renameTable | ALTER TABLE (IF EXISTS)? tableName=qualifiedName ADD COLUMN (IF NOT EXISTS)? column=columnDefinition #addColumn | ALTER TABLE (IF EXISTS)? tableName=qualifiedName RENAME COLUMN (IF EXISTS)? from=qualifiedName TO to=identifier #renameColumn | ALTER TABLE (IF EXISTS)? tableName=qualifiedName DROP COLUMN (IF EXISTS)? column=qualifiedName #dropColumn | ALTER TABLE (IF EXISTS)? tableName=qualifiedName ALTER COLUMN columnName=qualifiedName SET DATA TYPE type #setColumnType | ALTER TABLE (IF EXISTS)? tableName=qualifiedName ALTER COLUMN columnName=identifier DROP NOT NULL #dropNotNullConstraint | ALTER TABLE tableName=qualifiedName SET AUTHORIZATION principal #setTableAuthorization | ALTER TABLE tableName=qualifiedName SET PROPERTIES propertyAssignments #setTableProperties | ALTER TABLE tableName=qualifiedName EXECUTE procedureName=identifier ('(' (callArgument (',' callArgument)*)? ')')? (WHERE where=booleanExpression)? #tableExecute | ANALYZE qualifiedName (WITH properties)? #analyze | CREATE (OR REPLACE)? MATERIALIZED VIEW (IF NOT EXISTS)? qualifiedName (GRACE PERIOD interval)? (COMMENT string)? (WITH properties)? AS rootQuery #createMaterializedView | CREATE (OR REPLACE)? VIEW qualifiedName (COMMENT string)? (SECURITY (DEFINER | INVOKER))? AS rootQuery #createView | REFRESH MATERIALIZED VIEW qualifiedName #refreshMaterializedView | DROP MATERIALIZED VIEW (IF EXISTS)? qualifiedName #dropMaterializedView | ALTER MATERIALIZED VIEW (IF EXISTS)? from=qualifiedName RENAME TO to=qualifiedName #renameMaterializedView | ALTER MATERIALIZED VIEW qualifiedName SET PROPERTIES propertyAssignments #setMaterializedViewProperties | DROP VIEW (IF EXISTS)? qualifiedName #dropView | ALTER VIEW from=qualifiedName RENAME TO to=qualifiedName #renameView | ALTER VIEW from=qualifiedName SET AUTHORIZATION principal #setViewAuthorization | CALL qualifiedName '(' (callArgument (',' callArgument)*)? ')' #call | CREATE (OR REPLACE)? functionSpecification #createFunction | DROP FUNCTION (IF EXISTS)? functionDeclaration #dropFunction | CREATE ROLE name=identifier (WITH ADMIN grantor)? (IN catalog=identifier)? #createRole | DROP ROLE name=identifier (IN catalog=identifier)? #dropRole | GRANT privilegeOrRole (',' privilegeOrRole)* TO principal (',' principal)* (WITH ADMIN OPTION)? (GRANTED BY grantor)? (IN catalog=identifier)? #grantRoles | GRANT ((privilegeOrRole (',' privilegeOrRole)*) | ALL PRIVILEGES) ON grantObject TO principal (WITH GRANT OPTION)? #grantPrivileges | REVOKE (ADMIN OPTION FOR)? privilegeOrRole (',' privilegeOrRole)* FROM principal (',' principal)* (GRANTED BY grantor)? (IN catalog=identifier)? #revokeRoles | REVOKE (GRANT OPTION FOR)? ((privilegeOrRole (',' privilegeOrRole)*) | ALL PRIVILEGES) ON grantObject FROM grantee=principal #revokePrivileges | DENY (privilege (',' privilege)* | ALL PRIVILEGES) ON grantObject TO grantee=principal #deny | SET ROLE (ALL | NONE | role=identifier) (IN catalog=identifier)? #setRole | SHOW GRANTS (ON grantObject)? #showGrants | EXPLAIN ('(' explainOption (',' explainOption)* ')')? statement #explain | EXPLAIN ANALYZE VERBOSE? statement #explainAnalyze | SHOW CREATE TABLE qualifiedName #showCreateTable | SHOW CREATE SCHEMA qualifiedName #showCreateSchema | SHOW CREATE VIEW qualifiedName #showCreateView | SHOW CREATE MATERIALIZED VIEW qualifiedName #showCreateMaterializedView | SHOW TABLES ((FROM | IN) qualifiedName)? (LIKE pattern=string (ESCAPE escape=string)?)? #showTables | SHOW SCHEMAS ((FROM | IN) identifier)? (LIKE pattern=string (ESCAPE escape=string)?)? #showSchemas | SHOW CATALOGS (LIKE pattern=string (ESCAPE escape=string)?)? #showCatalogs | SHOW COLUMNS (FROM | IN) qualifiedName (LIKE pattern=string (ESCAPE escape=string)?)? #showColumns | SHOW STATS FOR qualifiedName #showStats | SHOW STATS FOR '(' rootQuery ')' #showStatsForQuery | SHOW CURRENT? ROLES ((FROM | IN) identifier)? #showRoles | SHOW ROLE GRANTS ((FROM | IN) identifier)? #showRoleGrants | DESCRIBE qualifiedName #showColumns | DESC qualifiedName #showColumns | SHOW FUNCTIONS ((FROM | IN) qualifiedName)? (LIKE pattern=string (ESCAPE escape=string)?)? #showFunctions | SHOW SESSION (LIKE pattern=string (ESCAPE escape=string)?)? #showSession | SET SESSION AUTHORIZATION authorizationUser #setSessionAuthorization | RESET SESSION AUTHORIZATION #resetSessionAuthorization | SET SESSION qualifiedName EQ expression #setSession | RESET SESSION qualifiedName #resetSession | START TRANSACTION (transactionMode (',' transactionMode)*)? #startTransaction | COMMIT WORK? #commit | ROLLBACK WORK? #rollback | PREPARE identifier FROM statement #prepare | DEALLOCATE PREPARE identifier #deallocate | EXECUTE identifier (USING expression (',' expression)*)? #execute | EXECUTE IMMEDIATE string (USING expression (',' expression)*)? #executeImmediate | DESCRIBE INPUT identifier #describeInput | DESCRIBE OUTPUT identifier #describeOutput | SET PATH pathSpecification #setPath | SET TIME ZONE (LOCAL | expression) #setTimeZone | UPDATE qualifiedName SET updateAssignment (',' updateAssignment)* (whereClause)? #update | MERGE INTO qualifiedName (AS? identifier)? USING relation ON expression mergeCase+ #merge ; rootQuery : withFunction? query ; withFunction : WITH functionSpecification (',' functionSpecification)* ; query : with? queryNoWith ; with : WITH RECURSIVE? namedQuery (',' namedQuery)* ; tableElement : columnDefinition | likeClause ; columnDefinition : qualifiedName type (NOT NULL)? (COMMENT string)? (WITH properties)? ; likeClause : LIKE qualifiedName (optionType=(INCLUDING | EXCLUDING) PROPERTIES)? ; properties : '(' propertyAssignments ')' ; propertyAssignments : property (',' property)* ; property : identifier EQ propertyValue ; propertyValue : DEFAULT #defaultPropertyValue | expression #nonDefaultPropertyValue ; queryNoWith : queryTerm (ORDER BY sortItem (',' sortItem)*)? (OFFSET offset=rowCount (ROW | ROWS)?)? ( (LIMIT limit=limitRowCount) | (FETCH (FIRST | NEXT) (fetchFirst=rowCount)? (ROW | ROWS) (ONLY | WITH TIES)) )? ; limitRowCount : ALL | rowCount ; rowCount : INTEGER_VALUE | QUESTION_MARK ; queryTerm : queryPrimary #queryTermDefault | left=queryTerm operator=INTERSECT setQuantifier? right=queryTerm #setOperation | left=queryTerm operator=(UNION | EXCEPT) setQuantifier? right=queryTerm #setOperation ; queryPrimary : querySpecification #queryPrimaryDefault | TABLE qualifiedName #table | VALUES expression (',' expression)* #inlineTable | '(' queryNoWith ')' #subquery ; sortItem : expression ordering=(ASC | DESC)? (NULLS nullOrdering=(FIRST | LAST))? ; querySpecification : SELECT setQuantifier? selectItem (',' selectItem)* (FROM relation (',' relation)*)? (WHERE where=booleanExpression)? (GROUP BY groupBy)? (HAVING having=booleanExpression)? (WINDOW windowDefinition (',' windowDefinition)*)? ; groupBy : setQuantifier? groupingElement (',' groupingElement)* ; groupingElement : groupingSet #singleGroupingSet | ROLLUP '(' (groupingSet (',' groupingSet)*)? ')' #rollup | CUBE '(' (groupingSet (',' groupingSet)*)? ')' #cube | GROUPING SETS '(' groupingSet (',' groupingSet)* ')' #multipleGroupingSets ; groupingSet : '(' (expression (',' expression)*)? ')' | expression ; windowDefinition : name=identifier AS '(' windowSpecification ')' ; windowSpecification : (existingWindowName=identifier)? (PARTITION BY partition+=expression (',' partition+=expression)*)? (ORDER BY sortItem (',' sortItem)*)? windowFrame? ; namedQuery : name=identifier (columnAliases)? AS '(' query ')' ; setQuantifier : DISTINCT | ALL ; selectItem : expression (AS? identifier)? #selectSingle | primaryExpression '.' ASTERISK (AS columnAliases)? #selectAll | ASTERISK #selectAll ; relation : left=relation ( CROSS JOIN right=sampledRelation | joinType JOIN rightRelation=relation joinCriteria | NATURAL joinType JOIN right=sampledRelation ) #joinRelation | sampledRelation #relationDefault ; joinType : INNER? | LEFT OUTER? | RIGHT OUTER? | FULL OUTER? ; joinCriteria : ON booleanExpression | USING '(' identifier (',' identifier)* ')' ; sampledRelation : patternRecognition ( TABLESAMPLE sampleType '(' percentage=expression ')' )? ; sampleType : BERNOULLI | SYSTEM ; trimsSpecification : LEADING | TRAILING | BOTH ; listAggOverflowBehavior : ERROR | TRUNCATE string? listaggCountIndication ; listaggCountIndication : WITH COUNT | WITHOUT COUNT ; patternRecognition : aliasedRelation ( MATCH_RECOGNIZE '(' (PARTITION BY partition+=expression (',' partition+=expression)*)? (ORDER BY sortItem (',' sortItem)*)? (MEASURES measureDefinition (',' measureDefinition)*)? rowsPerMatch? (AFTER MATCH skipTo)? (INITIAL | SEEK)? PATTERN '(' rowPattern ')' (SUBSET subsetDefinition (',' subsetDefinition)*)? DEFINE variableDefinition (',' variableDefinition)* ')' (AS? identifier columnAliases?)? )? ; measureDefinition : expression AS identifier ; rowsPerMatch : ONE ROW PER MATCH | ALL ROWS PER MATCH emptyMatchHandling? ; emptyMatchHandling : SHOW EMPTY MATCHES | OMIT EMPTY MATCHES | WITH UNMATCHED ROWS ; skipTo : 'SKIP' TO NEXT ROW | 'SKIP' PAST LAST ROW | 'SKIP' TO FIRST identifier | 'SKIP' TO LAST identifier | 'SKIP' TO identifier ; subsetDefinition : name=identifier EQ '(' union+=identifier (',' union+=identifier)* ')' ; variableDefinition : identifier AS expression ; aliasedRelation : relationPrimary (AS? identifier columnAliases?)? ; columnAliases : '(' identifier (',' identifier)* ')' ; relationPrimary : qualifiedName queryPeriod? #tableName | '(' query ')' #subqueryRelation | UNNEST '(' expression (',' expression)* ')' (WITH ORDINALITY)? #unnest | LATERAL '(' query ')' #lateral | TABLE '(' tableFunctionCall ')' #tableFunctionInvocation | '(' relation ')' #parenthesizedRelation | JSON_TABLE '(' jsonPathInvocation COLUMNS '(' jsonTableColumn (',' jsonTableColumn)* ')' (PLAN '(' jsonTableSpecificPlan ')' | PLAN DEFAULT '(' jsonTableDefaultPlan ')' )? ((ERROR | EMPTY) ON ERROR)? ')' #jsonTable ; jsonTableColumn : identifier FOR ORDINALITY #ordinalityColumn | identifier type (PATH string)? (emptyBehavior=jsonValueBehavior ON EMPTY)? (errorBehavior=jsonValueBehavior ON ERROR)? #valueColumn | identifier type FORMAT jsonRepresentation (PATH string)? (jsonQueryWrapperBehavior WRAPPER)? ((KEEP | OMIT) QUOTES (ON SCALAR TEXT_STRING)?)? (emptyBehavior=jsonQueryBehavior ON EMPTY)? (errorBehavior=jsonQueryBehavior ON ERROR)? #queryColumn | NESTED PATH? string (AS identifier)? COLUMNS '(' jsonTableColumn (',' jsonTableColumn)* ')' #nestedColumns ; jsonTableSpecificPlan : jsonTablePathName #leafPlan | jsonTablePathName (OUTER | INNER) planPrimary #joinPlan | planPrimary UNION planPrimary (UNION planPrimary)* #unionPlan | planPrimary CROSS planPrimary (CROSS planPrimary)* #crossPlan ; jsonTablePathName : identifier ; planPrimary : jsonTablePathName | '(' jsonTableSpecificPlan ')' ; jsonTableDefaultPlan : (OUTER | INNER) (',' (UNION | CROSS))? | (UNION | CROSS) (',' (OUTER | INNER))? ; tableFunctionCall : qualifiedName '(' (tableFunctionArgument (',' tableFunctionArgument)*)? (COPARTITION copartitionTables (',' copartitionTables)*)? ')' ; tableFunctionArgument : (identifier '=>')? (tableArgument | descriptorArgument | expression) // descriptor before expression to avoid parsing descriptor as a function call ; tableArgument : tableArgumentRelation (PARTITION BY ('(' (expression (',' expression)*)? ')' | expression))? (PRUNE WHEN EMPTY | KEEP WHEN EMPTY)? (ORDER BY ('(' sortItem (',' sortItem)* ')' | sortItem))? ; tableArgumentRelation : TABLE '(' qualifiedName ')' (AS? identifier columnAliases?)? #tableArgumentTable | TABLE '(' query ')' (AS? identifier columnAliases?)? #tableArgumentQuery ; descriptorArgument : DESCRIPTOR '(' descriptorField (',' descriptorField)* ')' | CAST '(' NULL AS DESCRIPTOR ')' ; descriptorField : identifier type? ; copartitionTables : '(' qualifiedName ',' qualifiedName (',' qualifiedName)* ')' ; expression : booleanExpression ; whereClause : WHERE booleanExpression ; booleanExpression : valueExpression predicate[$valueExpression.ctx]? #predicated | NOT booleanExpression #logicalNot | booleanExpression AND booleanExpression #and | booleanExpression OR booleanExpression #or ; // workaround for https://github.com/antlr/antlr4/issues/780 predicate[ParserRuleContext value] : comparisonOperator right=valueExpression #comparison | comparisonOperator comparisonQuantifier '(' query ')' #quantifiedComparison | NOT? BETWEEN lower=valueExpression AND upper=valueExpression #between | NOT? IN '(' expression (',' expression)* ')' #inList | NOT? IN '(' query ')' #inSubquery | NOT? LIKE pattern=valueExpression (ESCAPE escape=valueExpression)? #like | IS NOT? NULL #nullPredicate | IS NOT? DISTINCT FROM right=valueExpression #distinctFrom ; valueExpression : primaryExpression #valueExpressionDefault | valueExpression AT timeZoneSpecifier #atTimeZone | operator=(MINUS | PLUS) valueExpression #arithmeticUnary | left=valueExpression operator=(ASTERISK | SLASH | PERCENT) right=valueExpression #arithmeticBinary | left=valueExpression operator=(PLUS | MINUS) right=valueExpression #arithmeticBinary | left=valueExpression CONCAT right=valueExpression #concatenation ; primaryExpression : NULL #nullLiteral | interval #intervalLiteral | identifier string #typeConstructor | DOUBLE PRECISION string #typeConstructor | number #numericLiteral | booleanValue #booleanLiteral | string #stringLiteral | BINARY_LITERAL #binaryLiteral | QUESTION_MARK #parameter | POSITION '(' valueExpression IN valueExpression ')' #position | '(' expression (',' expression)+ ')' #rowConstructor | ROW '(' expression (',' expression)* ')' #rowConstructor | name=LISTAGG '(' setQuantifier? expression (',' string)? (ON OVERFLOW listAggOverflowBehavior)? ')' (WITHIN GROUP '(' ORDER BY sortItem (',' sortItem)* ')') filter? #listagg | processingMode? qualifiedName '(' (label=identifier '.')? ASTERISK ')' filter? over? #functionCall | processingMode? qualifiedName '(' (setQuantifier? expression (',' expression)*)? (ORDER BY sortItem (',' sortItem)*)? ')' filter? (nullTreatment? over)? #functionCall | identifier over #measure | identifier '->' expression #lambda | '(' (identifier (',' identifier)*)? ')' '->' expression #lambda | '(' query ')' #subqueryExpression // This is an extension to ANSI SQL, which considers EXISTS to be a | EXISTS '(' query ')' #exists | CASE operand=expression whenClause+ (ELSE elseExpression=expression)? END #simpleCase | CASE whenClause+ (ELSE elseExpression=expression)? END #searchedCase | CAST '(' expression AS type ')' #cast | TRY_CAST '(' expression AS type ')' #cast | ARRAY '[' (expression (',' expression)*)? ']' #arrayConstructor | value=primaryExpression '[' index=valueExpression ']' #subscript | identifier #columnReference | base=primaryExpression '.' fieldName=identifier #dereference | name=CURRENT_DATE #currentDate | name=CURRENT_TIME ('(' precision=INTEGER_VALUE ')')? #currentTime | name=CURRENT_TIMESTAMP ('(' precision=INTEGER_VALUE ')')? #currentTimestamp | name=LOCALTIME ('(' precision=INTEGER_VALUE ')')? #localTime | name=LOCALTIMESTAMP ('(' precision=INTEGER_VALUE ')')? #localTimestamp | name=CURRENT_USER #currentUser | name=CURRENT_CATALOG #currentCatalog | name=CURRENT_SCHEMA #currentSchema | name=CURRENT_PATH #currentPath | TRIM '(' (trimsSpecification? trimChar=valueExpression? FROM)? trimSource=valueExpression ')' #trim | TRIM '(' trimSource=valueExpression ',' trimChar=valueExpression ')' #trim | SUBSTRING '(' valueExpression FROM valueExpression (FOR valueExpression)? ')' #substring | NORMALIZE '(' valueExpression (',' normalForm)? ')' #normalize | EXTRACT '(' identifier FROM valueExpression ')' #extract | '(' expression ')' #parenthesizedExpression | GROUPING '(' (qualifiedName (',' qualifiedName)*)? ')' #groupingOperation | JSON_EXISTS '(' jsonPathInvocation (jsonExistsErrorBehavior ON ERROR)? ')' #jsonExists | JSON_VALUE '(' jsonPathInvocation (RETURNING type)? (emptyBehavior=jsonValueBehavior ON EMPTY)? (errorBehavior=jsonValueBehavior ON ERROR)? ')' #jsonValue | JSON_QUERY '(' jsonPathInvocation (RETURNING type (FORMAT jsonRepresentation)?)? (jsonQueryWrapperBehavior WRAPPER)? ((KEEP | OMIT) QUOTES (ON SCALAR TEXT_STRING)?)? (emptyBehavior=jsonQueryBehavior ON EMPTY)? (errorBehavior=jsonQueryBehavior ON ERROR)? ')' #jsonQuery | JSON_OBJECT '(' ( jsonObjectMember (',' jsonObjectMember)* (NULL ON NULL | ABSENT ON NULL)? (WITH UNIQUE KEYS? | WITHOUT UNIQUE KEYS?)? )? (RETURNING type (FORMAT jsonRepresentation)?)? ')' #jsonObject | JSON_ARRAY '(' ( jsonValueExpression (',' jsonValueExpression)* (NULL ON NULL | ABSENT ON NULL)? )? (RETURNING type (FORMAT jsonRepresentation)?)? ')' #jsonArray ; jsonPathInvocation : jsonValueExpression ',' path=string (AS pathName=identifier)? (PASSING jsonArgument (',' jsonArgument)*)? ; jsonValueExpression : expression (FORMAT jsonRepresentation)? ; jsonRepresentation : JSON (ENCODING (UTF8 | UTF16 | UTF32))? // TODO add implementation-defined JSON representation option ; jsonArgument : jsonValueExpression AS identifier ; jsonExistsErrorBehavior : TRUE | FALSE | UNKNOWN | ERROR ; jsonValueBehavior : ERROR | NULL | DEFAULT expression ; jsonQueryWrapperBehavior : WITHOUT ARRAY? | WITH (CONDITIONAL | UNCONDITIONAL)? ARRAY? ; jsonQueryBehavior : ERROR | NULL | EMPTY ARRAY | EMPTY OBJECT ; jsonObjectMember : KEY? expression VALUE jsonValueExpression | expression ':' jsonValueExpression ; processingMode : RUNNING | FINAL ; nullTreatment : IGNORE NULLS | RESPECT NULLS ; string : STRING #basicStringLiteral | UNICODE_STRING (UESCAPE STRING)? #unicodeStringLiteral ; timeZoneSpecifier : TIME ZONE interval #timeZoneInterval | TIME ZONE string #timeZoneString ; comparisonOperator : EQ | NEQ | LT | LTE | GT | GTE ; comparisonQuantifier : ALL | SOME | ANY ; booleanValue : TRUE | FALSE ; interval : INTERVAL sign=(PLUS | MINUS)? string from=intervalField (TO to=intervalField)? ; intervalField : YEAR | MONTH | DAY | HOUR | MINUTE | SECOND ; normalForm : NFD | NFC | NFKD | NFKC ; type : ROW '(' rowField (',' rowField)* ')' #rowType | INTERVAL from=intervalField (TO to=intervalField)? #intervalType | base=TIMESTAMP ('(' precision = typeParameter ')')? (WITHOUT TIME ZONE)? #dateTimeType | base=TIMESTAMP ('(' precision = typeParameter ')')? WITH TIME ZONE #dateTimeType | base=TIME ('(' precision = typeParameter ')')? (WITHOUT TIME ZONE)? #dateTimeType | base=TIME ('(' precision = typeParameter ')')? WITH TIME ZONE #dateTimeType | DOUBLE PRECISION #doublePrecisionType | ARRAY '<' type '>' #legacyArrayType | MAP '<' keyType=type ',' valueType=type '>' #legacyMapType | type ARRAY ('[' INTEGER_VALUE ']')? #arrayType | identifier ('(' typeParameter (',' typeParameter)* ')')? #genericType ; rowField : type | identifier type; typeParameter : INTEGER_VALUE | type ; whenClause : WHEN condition=expression THEN result=expression ; filter : FILTER '(' WHERE booleanExpression ')' ; mergeCase : WHEN MATCHED (AND condition=expression)? THEN UPDATE SET targets+=identifier EQ values+=expression (',' targets+=identifier EQ values+=expression)* #mergeUpdate | WHEN MATCHED (AND condition=expression)? THEN DELETE #mergeDelete | WHEN NOT MATCHED (AND condition=expression)? THEN INSERT ('(' targets+=identifier (',' targets+=identifier)* ')')? VALUES '(' values+=expression (',' values+=expression)* ')' #mergeInsert ; over : OVER (windowName=identifier | '(' windowSpecification ')') ; windowFrame : (MEASURES measureDefinition (',' measureDefinition)*)? frameExtent (AFTER MATCH skipTo)? (INITIAL | SEEK)? (PATTERN '(' rowPattern ')')? (SUBSET subsetDefinition (',' subsetDefinition)*)? (DEFINE variableDefinition (',' variableDefinition)*)? ; frameExtent : frameType=RANGE start=frameBound | frameType=ROWS start=frameBound | frameType=GROUPS start=frameBound | frameType=RANGE BETWEEN start=frameBound AND end=frameBound | frameType=ROWS BETWEEN start=frameBound AND end=frameBound | frameType=GROUPS BETWEEN start=frameBound AND end=frameBound ; frameBound : UNBOUNDED boundType=PRECEDING #unboundedFrame | UNBOUNDED boundType=FOLLOWING #unboundedFrame | CURRENT ROW #currentRowBound | expression boundType=(PRECEDING | FOLLOWING) #boundedFrame ; rowPattern : patternPrimary patternQuantifier? #quantifiedPrimary | rowPattern rowPattern #patternConcatenation | rowPattern '|' rowPattern #patternAlternation ; patternPrimary : identifier #patternVariable | '(' ')' #emptyPattern | PERMUTE '(' rowPattern (',' rowPattern)* ')' #patternPermutation | '(' rowPattern ')' #groupedPattern | '^' #partitionStartAnchor | '$' #partitionEndAnchor | '{-' rowPattern '-}' #excludedPattern ; patternQuantifier : ASTERISK (reluctant=QUESTION_MARK)? #zeroOrMoreQuantifier | PLUS (reluctant=QUESTION_MARK)? #oneOrMoreQuantifier | QUESTION_MARK (reluctant=QUESTION_MARK)? #zeroOrOneQuantifier | '{' exactly=INTEGER_VALUE '}' (reluctant=QUESTION_MARK)? #rangeQuantifier | '{' (atLeast=INTEGER_VALUE)? ',' (atMost=INTEGER_VALUE)? '}' (reluctant=QUESTION_MARK)? #rangeQuantifier ; updateAssignment : identifier EQ expression ; explainOption : FORMAT value=(TEXT | GRAPHVIZ | JSON) #explainFormat | TYPE value=(LOGICAL | DISTRIBUTED | VALIDATE | IO) #explainType ; transactionMode : ISOLATION LEVEL levelOfIsolation #isolationLevel | READ accessMode=(ONLY | WRITE) #transactionAccessMode ; levelOfIsolation : READ UNCOMMITTED #readUncommitted | READ COMMITTED #readCommitted | REPEATABLE READ #repeatableRead | SERIALIZABLE #serializable ; callArgument : expression #positionalArgument | identifier '=>' expression #namedArgument ; pathElement : identifier '.' identifier #qualifiedArgument | identifier #unqualifiedArgument ; pathSpecification : pathElement (',' pathElement)* ; functionSpecification : FUNCTION functionDeclaration returnsClause routineCharacteristic* controlStatement ; functionDeclaration : qualifiedName '(' (parameterDeclaration (',' parameterDeclaration)*)? ')' ; parameterDeclaration : identifier? type ; returnsClause : RETURNS type ; routineCharacteristic : LANGUAGE identifier #languageCharacteristic | NOT? DETERMINISTIC #deterministicCharacteristic | RETURNS NULL ON NULL INPUT #returnsNullOnNullInputCharacteristic | CALLED ON NULL INPUT #calledOnNullInputCharacteristic | SECURITY (DEFINER | INVOKER) #securityCharacteristic | COMMENT string #commentCharacteristic ; controlStatement : RETURN valueExpression #returnStatement | SET identifier EQ expression #assignmentStatement | CASE expression caseStatementWhenClause+ elseClause? END CASE #simpleCaseStatement | CASE caseStatementWhenClause+ elseClause? END CASE #searchedCaseStatement | IF expression THEN sqlStatementList elseIfClause* elseClause? END IF #ifStatement | ITERATE identifier #iterateStatement | LEAVE identifier #leaveStatement | BEGIN (variableDeclaration SEMICOLON)* sqlStatementList? END #compoundStatement | (label=identifier ':')? LOOP sqlStatementList END LOOP #loopStatement | (label=identifier ':')? WHILE expression DO sqlStatementList END WHILE #whileStatement | (label=identifier ':')? REPEAT sqlStatementList UNTIL expression END REPEAT #repeatStatement ; caseStatementWhenClause : WHEN expression THEN sqlStatementList ; elseIfClause : ELSEIF expression THEN sqlStatementList ; elseClause : ELSE sqlStatementList ; variableDeclaration : DECLARE identifier (',' identifier)* type (DEFAULT valueExpression)? ; sqlStatementList : (controlStatement SEMICOLON)+ ; privilege : CREATE | SELECT | DELETE | INSERT | UPDATE | identifier ; entityKind : TABLE | SCHEMA | identifier ; grantObject : entityKind? qualifiedName ; qualifiedName : identifier ('.' identifier)* ; queryPeriod : FOR rangeType AS OF end=valueExpression ; rangeType : TIMESTAMP | VERSION ; grantor : principal #specifiedPrincipal | CURRENT_USER #currentUserGrantor | CURRENT_ROLE #currentRoleGrantor ; principal : identifier #unspecifiedPrincipal | USER identifier #userPrincipal | ROLE identifier #rolePrincipal ; roles : identifier (',' identifier)* ; privilegeOrRole : CREATE | SELECT | DELETE | INSERT | UPDATE | identifier ; identifier : IDENTIFIER #unquotedIdentifier | QUOTED_IDENTIFIER #quotedIdentifier | nonReserved #unquotedIdentifier | BACKQUOTED_IDENTIFIER #backQuotedIdentifier | DIGIT_IDENTIFIER #digitIdentifier ; number : MINUS? DECIMAL_VALUE #decimalLiteral | MINUS? DOUBLE_VALUE #doubleLiteral | MINUS? INTEGER_VALUE #integerLiteral ; authorizationUser : identifier #identifierUser | string #stringUser ; nonReserved // IMPORTANT: this rule must only contain tokens. Nested rules are not supported. See SqlParser.exitNonReserved : ABSENT | ADD | ADMIN | AFTER | ALL | ANALYZE | ANY | ARRAY | ASC | AT | AUTHORIZATION | BEGIN | BERNOULLI | BOTH | CALL | CALLED | CASCADE | CATALOG | CATALOGS | COLUMN | COLUMNS | COMMENT | COMMIT | COMMITTED | CONDITIONAL | COPARTITION | COUNT | CURRENT | DATA | DATE | DAY | DECLARE | DEFAULT | DEFINE | DEFINER | DENY | DESC | DESCRIPTOR | DETERMINISTIC | DISTRIBUTED | DO | DOUBLE | ELSEIF | EMPTY | ENCODING | ERROR | EXCLUDING | EXPLAIN | FETCH | FILTER | FINAL | FIRST | FOLLOWING | FORMAT | FUNCTION | FUNCTIONS | GRACE | GRANT | GRANTED | GRANTS | GRAPHVIZ | GROUPS | HOUR | IF | IGNORE | IMMEDIATE | INCLUDING | INITIAL | INPUT | INTERVAL | INVOKER | IO | ITERATE | ISOLATION | JSON | KEEP | KEY | KEYS | LANGUAGE | LAST | LATERAL | LEADING | LEAVE | LEVEL | LIMIT | LOCAL | LOGICAL | LOOP | MAP | MATCH | MATCHED | MATCHES | MATCH_RECOGNIZE | MATERIALIZED | MEASURES | MERGE | MINUTE | MONTH | NESTED | NEXT | NFC | NFD | NFKC | NFKD | NO | NONE | NULLIF | NULLS | OBJECT | OF | OFFSET | OMIT | ONE | ONLY | OPTION | ORDINALITY | OUTPUT | OVER | OVERFLOW | PARTITION | PARTITIONS | PASSING | PAST | PATH | PATTERN | PER | PERIOD | PERMUTE | PLAN | POSITION | PRECEDING | PRECISION | PRIVILEGES | PROPERTIES | PRUNE | QUOTES | RANGE | READ | REFRESH | RENAME | REPEAT | REPEATABLE | REPLACE | RESET | RESPECT | RESTRICT | RETURN | RETURNING | RETURNS | REVOKE | ROLE | ROLES | ROLLBACK | ROW | ROWS | RUNNING | SCALAR | SCHEMA | SCHEMAS | SECOND | SECURITY | SEEK | SERIALIZABLE | SESSION | SET | SETS | SHOW | SOME | START | STATS | SUBSET | SUBSTRING | SYSTEM | TABLES | TABLESAMPLE | TEXT | TEXT_STRING | TIES | TIME | TIMESTAMP | TO | TRAILING | TRANSACTION | TRUNCATE | TRY_CAST | TYPE | UNBOUNDED | UNCOMMITTED | UNCONDITIONAL | UNIQUE | UNKNOWN | UNMATCHED | UNTIL | UPDATE | USE | USER | UTF16 | UTF32 | UTF8 | VALIDATE | VALUE | VERBOSE | VERSION | VIEW | WHILE | WINDOW | WITHIN | WITHOUT | WORK | WRAPPER | WRITE | YEAR | ZONE ; ABSENT: 'ABSENT'; ADD: 'ADD'; ADMIN: 'ADMIN'; AFTER: 'AFTER'; ALL: 'ALL'; ALTER: 'ALTER'; ANALYZE: 'ANALYZE'; AND: 'AND'; ANY: 'ANY'; ARRAY: 'ARRAY'; AS: 'AS'; ASC: 'ASC'; AT: 'AT'; AUTHORIZATION: 'AUTHORIZATION'; BEGIN: 'BEGIN'; BERNOULLI: 'BERNOULLI'; BETWEEN: 'BETWEEN'; BOTH: 'BOTH'; BY: 'BY'; CALL: 'CALL'; CALLED: 'CALLED'; CASCADE: 'CASCADE'; CASE: 'CASE'; CAST: 'CAST'; CATALOG: 'CATALOG'; CATALOGS: 'CATALOGS'; COLUMN: 'COLUMN'; COLUMNS: 'COLUMNS'; COMMENT: 'COMMENT'; COMMIT: 'COMMIT'; COMMITTED: 'COMMITTED'; CONDITIONAL: 'CONDITIONAL'; CONSTRAINT: 'CONSTRAINT'; COUNT: 'COUNT'; COPARTITION: 'COPARTITION'; CREATE: 'CREATE'; CROSS: 'CROSS'; CUBE: 'CUBE'; CURRENT: 'CURRENT'; CURRENT_CATALOG: 'CURRENT_CATALOG'; CURRENT_DATE: 'CURRENT_DATE'; CURRENT_PATH: 'CURRENT_PATH'; CURRENT_ROLE: 'CURRENT_ROLE'; CURRENT_SCHEMA: 'CURRENT_SCHEMA'; CURRENT_TIME: 'CURRENT_TIME'; CURRENT_TIMESTAMP: 'CURRENT_TIMESTAMP'; CURRENT_USER: 'CURRENT_USER'; DATA: 'DATA'; DATE: 'DATE'; DAY: 'DAY'; DEALLOCATE: 'DEALLOCATE'; DECLARE: 'DECLARE'; DEFAULT: 'DEFAULT'; DEFINE: 'DEFINE'; DEFINER: 'DEFINER'; DELETE: 'DELETE'; DENY: 'DENY'; DESC: 'DESC'; DESCRIBE: 'DESCRIBE'; DESCRIPTOR: 'DESCRIPTOR'; DETERMINISTIC: 'DETERMINISTIC'; DISTINCT: 'DISTINCT'; DISTRIBUTED: 'DISTRIBUTED'; DO: 'DO'; DOUBLE: 'DOUBLE'; DROP: 'DROP'; ELSE: 'ELSE'; EMPTY: 'EMPTY'; ELSEIF: 'ELSEIF'; ENCODING: 'ENCODING'; END: 'END'; ERROR: 'ERROR'; ESCAPE: 'ESCAPE'; EXCEPT: 'EXCEPT'; EXCLUDING: 'EXCLUDING'; EXECUTE: 'EXECUTE'; EXISTS: 'EXISTS'; EXPLAIN: 'EXPLAIN'; EXTRACT: 'EXTRACT'; FALSE: 'FALSE'; FETCH: 'FETCH'; FILTER: 'FILTER'; FINAL: 'FINAL'; FIRST: 'FIRST'; FOLLOWING: 'FOLLOWING'; FOR: 'FOR'; FORMAT: 'FORMAT'; FROM: 'FROM'; FULL: 'FULL'; FUNCTION: 'FUNCTION'; FUNCTIONS: 'FUNCTIONS'; GRACE: 'GRACE'; GRANT: 'GRANT'; GRANTED: 'GRANTED'; GRANTS: 'GRANTS'; GRAPHVIZ: 'GRAPHVIZ'; GROUP: 'GROUP'; GROUPING: 'GROUPING'; GROUPS: 'GROUPS'; HAVING: 'HAVING'; HOUR: 'HOUR'; IF: 'IF'; IGNORE: 'IGNORE'; IMMEDIATE: 'IMMEDIATE'; IN: 'IN'; INCLUDING: 'INCLUDING'; INITIAL: 'INITIAL'; INNER: 'INNER'; INPUT: 'INPUT'; INSERT: 'INSERT'; INTERSECT: 'INTERSECT'; INTERVAL: 'INTERVAL'; INTO: 'INTO'; INVOKER: 'INVOKER'; IO: 'IO'; IS: 'IS'; ISOLATION: 'ISOLATION'; ITERATE: 'ITERATE'; JOIN: 'JOIN'; JSON: 'JSON'; JSON_ARRAY: 'JSON_ARRAY'; JSON_EXISTS: 'JSON_EXISTS'; JSON_OBJECT: 'JSON_OBJECT'; JSON_QUERY: 'JSON_QUERY'; JSON_TABLE: 'JSON_TABLE'; JSON_VALUE: 'JSON_VALUE'; KEEP: 'KEEP'; KEY: 'KEY'; KEYS: 'KEYS'; LANGUAGE: 'LANGUAGE'; LAST: 'LAST'; LATERAL: 'LATERAL'; LEADING: 'LEADING'; LEAVE: 'LEAVE'; LEFT: 'LEFT'; LEVEL: 'LEVEL'; LIKE: 'LIKE'; LIMIT: 'LIMIT'; LISTAGG: 'LISTAGG'; LOCAL: 'LOCAL'; LOCALTIME: 'LOCALTIME'; LOCALTIMESTAMP: 'LOCALTIMESTAMP'; LOGICAL: 'LOGICAL'; LOOP: 'LOOP'; MAP: 'MAP'; MATCH: 'MATCH'; MATCHED: 'MATCHED'; MATCHES: 'MATCHES'; MATCH_RECOGNIZE: 'MATCH_RECOGNIZE'; MATERIALIZED: 'MATERIALIZED'; MEASURES: 'MEASURES'; MERGE: 'MERGE'; MINUTE: 'MINUTE'; MONTH: 'MONTH'; NATURAL: 'NATURAL'; NESTED: 'NESTED'; NEXT: 'NEXT'; NFC : 'NFC'; NFD : 'NFD'; NFKC : 'NFKC'; NFKD : 'NFKD'; NO: 'NO'; NONE: 'NONE'; NORMALIZE: 'NORMALIZE'; NOT: 'NOT'; NULL: 'NULL'; NULLIF: 'NULLIF'; NULLS: 'NULLS'; OBJECT: 'OBJECT'; OF: 'OF'; OFFSET: 'OFFSET'; OMIT: 'OMIT'; ON: 'ON'; ONE: 'ONE'; ONLY: 'ONLY'; OPTION: 'OPTION'; OR: 'OR'; ORDER: 'ORDER'; ORDINALITY: 'ORDINALITY'; OUTER: 'OUTER'; OUTPUT: 'OUTPUT'; OVER: 'OVER'; OVERFLOW: 'OVERFLOW'; PARTITION: 'PARTITION'; PARTITIONS: 'PARTITIONS'; PASSING: 'PASSING'; PAST: 'PAST'; PATH: 'PATH'; PATTERN: 'PATTERN'; PER: 'PER'; PERIOD: 'PERIOD'; PERMUTE: 'PERMUTE'; PLAN : 'PLAN'; POSITION: 'POSITION'; PRECEDING: 'PRECEDING'; PRECISION: 'PRECISION'; PREPARE: 'PREPARE'; PRIVILEGES: 'PRIVILEGES'; PROPERTIES: 'PROPERTIES'; PRUNE: 'PRUNE'; QUOTES: 'QUOTES'; RANGE: 'RANGE'; READ: 'READ'; RECURSIVE: 'RECURSIVE'; REFRESH: 'REFRESH'; RENAME: 'RENAME'; REPEAT: 'REPEAT'; REPEATABLE: 'REPEATABLE'; REPLACE: 'REPLACE'; RESET: 'RESET'; RESPECT: 'RESPECT'; RESTRICT: 'RESTRICT'; RETURN: 'RETURN'; RETURNING: 'RETURNING'; RETURNS: 'RETURNS'; REVOKE: 'REVOKE'; RIGHT: 'RIGHT'; ROLE: 'ROLE'; ROLES: 'ROLES'; ROLLBACK: 'ROLLBACK'; ROLLUP: 'ROLLUP'; ROW: 'ROW'; ROWS: 'ROWS'; RUNNING: 'RUNNING'; SCALAR: 'SCALAR'; SCHEMA: 'SCHEMA'; SCHEMAS: 'SCHEMAS'; SECOND: 'SECOND'; SECURITY: 'SECURITY'; SEEK: 'SEEK'; SELECT: 'SELECT'; SERIALIZABLE: 'SERIALIZABLE'; SESSION: 'SESSION'; SET: 'SET'; SETS: 'SETS'; SHOW: 'SHOW'; SOME: 'SOME'; START: 'START'; STATS: 'STATS'; SUBSET: 'SUBSET'; SUBSTRING: 'SUBSTRING'; SYSTEM: 'SYSTEM'; TABLE: 'TABLE'; TABLES: 'TABLES'; TABLESAMPLE: 'TABLESAMPLE'; TEXT: 'TEXT'; TEXT_STRING: 'STRING'; THEN: 'THEN'; TIES: 'TIES'; TIME: 'TIME'; TIMESTAMP: 'TIMESTAMP'; TO: 'TO'; TRAILING: 'TRAILING'; TRANSACTION: 'TRANSACTION'; TRIM: 'TRIM'; TRUE: 'TRUE'; TRUNCATE: 'TRUNCATE'; TRY_CAST: 'TRY_CAST'; TYPE: 'TYPE'; UESCAPE: 'UESCAPE'; UNBOUNDED: 'UNBOUNDED'; UNCOMMITTED: 'UNCOMMITTED'; UNCONDITIONAL: 'UNCONDITIONAL'; UNION: 'UNION'; UNIQUE: 'UNIQUE'; UNKNOWN: 'UNKNOWN'; UNMATCHED: 'UNMATCHED'; UNNEST: 'UNNEST'; UNTIL: 'UNTIL'; UPDATE: 'UPDATE'; USE: 'USE'; USER: 'USER'; USING: 'USING'; UTF16: 'UTF16'; UTF32: 'UTF32'; UTF8: 'UTF8'; VALIDATE: 'VALIDATE'; VALUE: 'VALUE'; VALUES: 'VALUES'; VERBOSE: 'VERBOSE'; VERSION: 'VERSION'; VIEW: 'VIEW'; WHEN: 'WHEN'; WHERE: 'WHERE'; WHILE: 'WHILE'; WINDOW: 'WINDOW'; WITH: 'WITH'; WITHIN: 'WITHIN'; WITHOUT: 'WITHOUT'; WORK: 'WORK'; WRAPPER: 'WRAPPER'; WRITE: 'WRITE'; YEAR: 'YEAR'; ZONE: 'ZONE'; EQ: '='; NEQ: '<>' | '!='; LT: '<'; LTE: '<='; GT: '>'; GTE: '>='; PLUS: '+'; MINUS: '-'; ASTERISK: '*'; SLASH: '/'; PERCENT: '%'; CONCAT: '||'; QUESTION_MARK: '?'; SEMICOLON: ';'; STRING : '\'' ( ~'\'' | '\'\'' )* '\'' ; UNICODE_STRING : 'U&\'' ( ~'\'' | '\'\'' )* '\'' ; // Note: we allow any character inside the binary literal and validate // its a correct literal when the AST is being constructed. This // allows us to provide more meaningful error messages to the user BINARY_LITERAL : 'X\'' (~'\'')* '\'' ; INTEGER_VALUE : DECIMAL_INTEGER | HEXADECIMAL_INTEGER | OCTAL_INTEGER | BINARY_INTEGER ; DECIMAL_VALUE : DECIMAL_INTEGER '.' DECIMAL_INTEGER? | '.' DECIMAL_INTEGER ; DOUBLE_VALUE : DIGIT+ ('.' DIGIT*)? EXPONENT | '.' DIGIT+ EXPONENT ; IDENTIFIER : (LETTER | '_') (LETTER | DIGIT | '_')* ; DIGIT_IDENTIFIER : DIGIT (LETTER | DIGIT | '_')+ ; QUOTED_IDENTIFIER : '"' ( ~'"' | '""' )* '"' ; BACKQUOTED_IDENTIFIER : '`' ( ~'`' | '``' )* '`' ; fragment DECIMAL_INTEGER : DIGIT ('_'? DIGIT)* ; fragment HEXADECIMAL_INTEGER : '0X' ('_'? (DIGIT | [A-F]))+ ; fragment OCTAL_INTEGER : '0O' ('_'? [0-7])+ ; fragment BINARY_INTEGER : '0B' ('_'? [01])+ ; fragment EXPONENT : 'E' [+-]? DIGIT+ ; fragment DIGIT : [0-9] ; fragment LETTER : [A-Z] ; SIMPLE_COMMENT : '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN) ; BRACKETED_COMMENT : '/*' .*? '*/' -> channel(HIDDEN) ; WS : [ \r\n\t]+ -> channel(HIDDEN) ; // Catch-all for anything we can't recognize. // We use this to be able to ignore and recover all the text // when splitting statements with DelimiterLexer UNRECOGNIZED : . ; ================================================ FILE: superior-trino-parser/src/main/java/io/github/melin/superior/parser/trino/CaseInsensitiveStream.java ================================================ /* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.github.melin.superior.parser.trino; import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.IntStream; import org.antlr.v4.runtime.misc.Interval; public class CaseInsensitiveStream implements CharStream { private final CharStream stream; public CaseInsensitiveStream(CharStream stream) { this.stream = stream; } @Override public String getText(Interval interval) { return stream.getText(interval); } @Override public void consume() { stream.consume(); } @Override public int LA(int i) { int result = stream.LA(i); switch (result) { case 0: case IntStream.EOF: return result; default: return Character.toUpperCase(result); } } @Override public int mark() { return stream.mark(); } @Override public void release(int marker) { stream.release(marker); } @Override public int index() { return stream.index(); } @Override public void seek(int index) { stream.seek(index); } @Override public int size() { return stream.size(); } @Override public String getSourceName() { return stream.getSourceName(); } } ================================================ FILE: superior-trino-parser/src/main/kotlin/io/github/melin/superior/parser/trino/AbstractSqlParser.kt ================================================ package io.github.melin.superior.parser.spark import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseParser import java.util.concurrent.atomic.AtomicReference object AbstractSqlParser { private val parserCaches = AtomicReference(AntlrCaches(TrinoSqlBaseParser._ATN)) /** * Install the parser caches into the given parser. * * This method should be called before parsing any input. */ fun installCaches(parser: TrinoSqlBaseParser): Unit = parserCaches.get().installCaches(parser) /** * Drop the existing parser caches and create a new one. * * ANTLR retains caches in its parser that are never released. This speeds up parsing of future input, but it can * consume a lot of memory depending on the input seen so far. * * This method provides a mechanism to free the retained caches, which can be useful after parsing very large SQL * inputs, especially if those large inputs are unlikely to be similar to future inputs seen by the driver. */ fun refreshParserCaches() { parserCaches.set(AntlrCaches(TrinoSqlBaseParser._ATN)) } } ================================================ FILE: superior-trino-parser/src/main/kotlin/io/github/melin/superior/parser/trino/TrinoSqlAntlr4Visitor.kt ================================================ package io.github.melin.superior.parser.trino import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.* import io.github.melin.superior.common.antlr4.ParserUtils.source import io.github.melin.superior.common.relational.DefaultStatement import io.github.melin.superior.common.relational.FunctionId import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.common.relational.TableId import io.github.melin.superior.common.relational.common.ShowStatement import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.* import io.github.melin.superior.common.relational.drop.DropTable import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseBaseVisitor import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseParser import org.antlr.v4.runtime.tree.RuleNode import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ class TrinoSqlAntlr4Visitor(val splitSql: Boolean = false, val command: String?) : TrinoSqlBaseBaseVisitor() { private var currentOptType: StatementType = StatementType.UNKOWN private var limit: Int? = null private var offset: Int? = null private var inputTables: ArrayList = arrayListOf() private var cteTempTables: ArrayList = arrayListOf() private var functionNames: HashSet = hashSetOf() private var statements: ArrayList = arrayListOf() private val sqls: ArrayList = arrayListOf() fun getSqlStatements(): List { return statements } fun getSplitSqls(): List { return sqls } override fun shouldVisitNextChild(node: RuleNode, currentResult: Statement?): Boolean { return if (currentResult == null) true else false } override fun visitSqlStatements(ctx: TrinoSqlBaseParser.SqlStatementsContext): Statement? { ctx.singleStatement().forEach { var sql = source(it) if (splitSql) { if (StringUtils.endsWith(sql, ";")) { sql = StringUtils.substringBeforeLast(sql, ";") } sqls.add(sql) } else { val startNode = it.start.text val statement = if (StringUtils.equalsIgnoreCase("show", startNode)) { val keyWords: ArrayList = arrayListOf() CommonUtils.findShowStatementKeyWord(keyWords, it) ShowStatement(*keyWords.toTypedArray()) } else { var statement = this.visitSingleStatement(it) if (statement == null) { statement = DefaultStatement(StatementType.UNKOWN) } statement } statement.setSql(sql) statements.add(statement) clean() } } return null } private fun clean() { currentOptType = StatementType.UNKOWN limit = null offset = null inputTables = arrayListOf() cteTempTables = arrayListOf() } override fun visitStatementDefault(ctx: TrinoSqlBaseParser.StatementDefaultContext): Statement? { if (StringUtils.equalsIgnoreCase("select", ctx.start.text)) { currentOptType = StatementType.SELECT super.visitRootQuery(ctx.rootQuery()) val limit = ctx.rootQuery()?.query()?.queryNoWith()?.limit?.text?.toInt() return QueryStmt(inputTables, limit) } else { return null } } private fun parseRootQuery(ctx: TrinoSqlBaseParser.RootQueryContext): QueryStmt { currentOptType = StatementType.SELECT this.visitRootQuery(ctx) val queryStmt = QueryStmt(inputTables, limit, offset) queryStmt.functionNames.addAll(functionNames) val querySql = source(ctx) queryStmt.setSql(querySql) return queryStmt } override fun visitCreateTableAsSelect(ctx: TrinoSqlBaseParser.CreateTableAsSelectContext): Statement? { currentOptType = StatementType.CREATE_TABLE_AS_SELECT val tableId = parseTableName(ctx.qualifiedName()) val queryStmt = parseRootQuery(ctx.rootQuery()) val createTable = CreateTableAsSelect(tableId, queryStmt) createTable.lifeCycle = 7 return createTable } override fun visitDropTable(ctx: TrinoSqlBaseParser.DropTableContext): Statement? { val tableId = parseTableName(ctx.qualifiedName()) val dropTable = DropTable(tableId) dropTable.ifExists = ctx.EXISTS() != null return dropTable } override fun visitInsertInto(ctx: TrinoSqlBaseParser.InsertIntoContext): Statement { val tableId = parseTableName(ctx.qualifiedName()) val queryStmt = parseRootQuery(ctx.rootQuery()) val stmt = InsertTable(InsertMode.INTO, queryStmt, tableId) return stmt } override fun visitDelete(ctx: TrinoSqlBaseParser.DeleteContext): Statement { currentOptType = StatementType.DELETE val tableId = parseTableName(ctx.qualifiedName()) if (ctx.whereClause() != null) { super.visitWhereClause(ctx.whereClause()) } return DeleteTable(tableId, inputTables) } override fun visitUpdate(ctx: TrinoSqlBaseParser.UpdateContext): Statement { currentOptType = StatementType.UPDATE val tableId = parseTableName(ctx.qualifiedName()) if (ctx.whereClause() != null) { super.visitWhereClause(ctx.whereClause()) } return UpdateTable(tableId, inputTables) } override fun visitMerge(ctx: TrinoSqlBaseParser.MergeContext): Statement { currentOptType = StatementType.MERGE val targetTable = parseTableName(ctx.qualifiedName()) val mergeTable = MergeTable(targetTable = targetTable) // @TODO mergeTable.inputTables = inputTables return mergeTable } override fun visitExplain(ctx: TrinoSqlBaseParser.ExplainContext): Statement? { return DefaultStatement(StatementType.EXPLAIN) } override fun visitQualifiedName(ctx: TrinoSqlBaseParser.QualifiedNameContext): Statement? { if (!(ctx.parent is TrinoSqlBaseParser.TableNameContext)) { return null } if ( currentOptType == StatementType.SELECT || currentOptType == StatementType.INSERT || currentOptType == StatementType.UPDATE || currentOptType == StatementType.DELETE || currentOptType == StatementType.MERGE || currentOptType == StatementType.CREATE_TABLE_AS_SELECT ) { val tableName = parseTableName(ctx) inputTables.add(tableName) } return null } private fun parseTableName(ctx: TrinoSqlBaseParser.QualifiedNameContext): TableId { val list = ctx.identifier() var catalogName: String? = null var databaseName: String? = null val tableName = if (list.size == 1) { ctx.text } else if (list.size == 2) { val index = StringUtils.lastIndexOf(ctx.text, ".") databaseName = StringUtils.substring(ctx.text, 0, index) StringUtils.substring(ctx.text, index + 1) } else { val items = StringUtils.split(ctx.text, ".") catalogName = items[0] databaseName = items[1] items[2] } return TableId(catalogName, databaseName, tableName) } } ================================================ FILE: superior-trino-parser/src/main/kotlin/io/github/melin/superior/parser/trino/TrinoSqlHelper.kt ================================================ package io.github.melin.superior.parser.trino import com.github.melin.superior.sql.parser.util.CommonUtils import io.github.melin.superior.common.antlr4.AntlrCaches import io.github.melin.superior.common.antlr4.ParseErrorListener import io.github.melin.superior.common.antlr4.ParseException import io.github.melin.superior.common.relational.Statement import io.github.melin.superior.parser.spark.AbstractSqlParser import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseBaseVisitor import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseLexer import io.github.melin.superior.parser.trino.antlr4.TrinoSqlBaseParser import org.antlr.v4.runtime.CharStreams import org.antlr.v4.runtime.CommonTokenStream import org.antlr.v4.runtime.atn.PredictionMode import org.antlr.v4.runtime.misc.ParseCancellationException import org.apache.commons.lang3.StringUtils /** Created by libinsong on 2018/1/10. */ object TrinoSqlHelper { @JvmStatic fun sqlKeywords(): List { val keywords = hashSetOf() (0 until TrinoSqlBaseLexer.VOCABULARY.maxTokenType).forEach { idx -> val name = TrinoSqlBaseLexer.VOCABULARY.getLiteralName(idx) if (name != null) { val matchResult = CommonUtils.KEYWORD_REGEX.find(name) if (matchResult != null) { keywords.add(matchResult.groupValues.get(1)) } } } return keywords.sorted() } @JvmStatic fun parseStatement(command: String): Statement { val statements = this.parseMultiStatement(command) if (statements.size != 1) { throw IllegalStateException("only parser one sql, sql count: " + statements.size) } else { return statements.get(0) } } @JvmStatic fun parseMultiStatement(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = TrinoSqlAntlr4Visitor(false, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSqlStatements() } @JvmStatic fun splitSql(command: String): List { val trimCmd = StringUtils.trim(command) val sqlVisitor = TrinoSqlAntlr4Visitor(true, trimCmd) innerParseStatement(trimCmd, sqlVisitor) return sqlVisitor.getSplitSqls() } @JvmStatic fun checkSqlSyntax(command: String) { val sqlVisitor = TrinoSqlBaseBaseVisitor() innerParseStatement(command, sqlVisitor) } private fun innerParseStatement(command: String, sqlVisitor: TrinoSqlBaseBaseVisitor) { val charStream = CaseInsensitiveStream(CharStreams.fromString(command)) val lexer = TrinoSqlBaseLexer(charStream) lexer.removeErrorListeners() lexer.addErrorListener(ParseErrorListener()) val tokenStream = CommonTokenStream(lexer) val parser = TrinoSqlBaseParser(tokenStream) AbstractSqlParser.installCaches(parser) parser.removeErrorListeners() parser.addErrorListener(ParseErrorListener()) parser.interpreter.predictionMode = PredictionMode.SLL try { try { // first, try parsing with potentially faster SLL mode sqlVisitor.visit(parser.sqlStatements()) } catch (e: ParseCancellationException) { tokenStream.seek(0) // rewind input stream parser.reset() // Try Again. parser.interpreter.predictionMode = PredictionMode.LL sqlVisitor.visit(parser.sqlStatements()) } } catch (e: ParseException) { if (StringUtils.isNotBlank(e.command)) { throw e } else { throw e.withCommand(command) } } finally { val releaseAntlrCache = System.getenv(AntlrCaches.RELEASE_ANTLR_CACHE_AFTER_PARSING) if (releaseAntlrCache == null || "true".equals(releaseAntlrCache)) { AbstractSqlParser.refreshParserCaches() } } } } ================================================ FILE: superior-trino-parser/src/test/kotlin/io/github/melin/superior/parser/trino/TrinoSqlParserTest.kt ================================================ package io.github.melin.superior.parser.trino import io.github.melin.superior.common.StatementType import io.github.melin.superior.common.relational.create.CreateTableAsSelect import io.github.melin.superior.common.relational.dml.DeleteTable import io.github.melin.superior.common.relational.dml.InsertTable import io.github.melin.superior.common.relational.dml.QueryStmt import io.github.melin.superior.common.relational.drop.DropTable import org.junit.Assert import org.junit.Test /** Created by libinsong on 2018/1/10. */ class TrinoSqlParserTest { @Test fun queryTest0() { val sql = """ select a.* from datacompute1.datacompute.dc_job a left join datacompute1.datacompute.dc_job_scheduler b on a.id=b.job_id """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(2, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryTest1() { val sql = """ SELECT COUNT(app_name) AS "应用名" FROM (SELECT * FROM ops.dwd_app_to_container_wt WHERE ds=date_format(CURRENT_DATE - interval '1' DAY, "%Y%m%d") ) tdbi_view """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } @Test fun queryLimitTest() { val sql = """ select * from preso_table limit 10 """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is QueryStmt) { Assert.assertEquals(StatementType.SELECT, statement.statementType) Assert.assertEquals(1, statement.inputTables.size) Assert.assertEquals(10, statement.limit) } else { Assert.fail() } } @Test fun createTableSelectTest() { val sql = """ create table dd_s_s as select * from bigdata.test_demo_test limit 1 """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is CreateTableAsSelect) { Assert.assertEquals(StatementType.CREATE_TABLE_AS_SELECT, statement.statementType) Assert.assertEquals("dd_s_s", statement.tableId.tableName) Assert.assertEquals(1, statement.queryStmt.inputTables.size) } else { Assert.fail() } } @Test fun dropTableTest() { val sql = """ drop table if exists bigdata.tdl_small_files_2 """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is DropTable) { Assert.assertEquals(StatementType.DROP_TABLE, statement.statementType) Assert.assertEquals("bigdata", statement.tableId.schemaName) Assert.assertEquals("tdl_small_files_2", statement.tableId.tableName) } else { Assert.fail() } } @Test fun insertTest() { val sql = """ insert into orders select * from new_orders; """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is InsertTable) { Assert.assertEquals(StatementType.INSERT, statement.statementType) Assert.assertEquals("orders", statement.tableId.tableName) } else { Assert.fail() } } @Test fun deleteTest() { val sql = """ DELETE FROM lineitem WHERE orderkey IN (SELECT orderkey FROM orders WHERE priority = 'LOW'); """ .trimIndent() val statement = TrinoSqlHelper.parseStatement(sql) if (statement is DeleteTable) { Assert.assertEquals(StatementType.DELETE, statement.statementType) Assert.assertEquals("lineitem", statement.tableId.tableName) Assert.assertEquals(1, statement.inputTables.size) } else { Assert.fail() } } } ================================================ FILE: superior-trino-parser/src/test/resources/log4j2.xml ================================================