forUpdateOf = x.getForUpdateOf();
+ if (forUpdateOf != null && forUpdateOf.size() > 0)
+ chameFeatureNotSupportLog("for_update_of statement" + getTypeAttribute(x));
+ if (bracket) {
+ print(')');
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlOutFileExpr x) {
+ logger.error("openGauss does not support OUTFILE" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ /**
+ * translate join statement
+ * mysql support INNER、CROSS、LEFT [OUTER]、RIGHT [OUTER]、NATURAL、STRAIGHT_JOIN field
+ * openGauss only support STRAIGHT_JOIN field
+ *
+ * Since mysql and openGauss only have the difference of STRAIGHT_JOIN in the join clause,
+ * the translation function can be realized by rewriting printJoinType
+ *
+ * @param x JOIN_STATEMENT statement
+ * @return false
+ * @see MySqlToOpenGaussOutputVisitor#printJoinType(SQLJoinTableSource.JoinType)
+ * @see MySQL JOIN_STATEMENT syntax
+ * @see PostgreSQL JOIN_STATEMENT syntax
+ */
+ @Override
+ public boolean visit(SQLJoinTableSource x) {
+ return super.visit(x);
+ }
+
+ /**
+ * Special treatment for STRAIGHT_JOIN join type, STRAIGHT_JOIN function is similar to JOIN, use JOIN instead
+ *
+ * @param joinType table link type
+ */
+ @Override
+ protected void printJoinType(SQLJoinTableSource.JoinType joinType) {
+ if (joinType.equals(SQLJoinTableSource.JoinType.STRAIGHT_JOIN)) {
+ printUcase(SQLJoinTableSource.JoinType.JOIN.name);
+ } else {
+ super.printJoinType(joinType);
+ }
+ }
+
+ /**
+ * translate limit statement
+ * When druid reads the mysql limit clause, it converts it to limit [ offset_count ] row_count format
+ * openGauss only supports limit row_count offset offset_count format
+ *
+ * @param x limit statement
+ * @return false
+ */
+ @Override
+ public boolean visit(SQLLimit x) {
+ // translate limit row_count
+ SQLExpr rowCount = x.getRowCount();
+ if (rowCount != null) {
+ printUcase("LIMIT");
+ print0(" ");
+ printExpr(rowCount);
+ }
+ // translate offset offset_count
+ SQLExpr offset = x.getOffset();
+ if (offset != null) {
+ print0(" ");
+ printUcase("OFFSET");
+ print0(" ");
+ printExpr(offset);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateTableStatement x) {
+ SQLPartitionBy partitionBy = x.getPartitioning();
+ boolean isPartition = partitionBy != null;
+ this.print0(this.ucase ? "CREATE " : "create ");
+ if (SQLCreateTableStatement.Type.GLOBAL_TEMPORARY.equals(x.getType())) {
+ if (!isPartition) {
+ printUcase("TEMPORARY ");
+ } else {
+ printUcaseNotSupportWord("temporary");
+ gaussFeatureNotSupportLog("temporary and partition at the same time" + getTypeAttribute(x));
+ }
+ }
+ printUcase("table ");
+ if (x.isIfNotExists()) {
+ this.print0(this.ucase ? "IF NOT EXISTS " : "if not exists ");
+ }
+ this.printTableSourceExpr(x.getName());
+ if (x.getLike() != null) {
+ this.print0(" (");
+ this.print0(this.ucase ? "LIKE " : "like ");
+ x.getLike().accept(this);
+ /* mysql like 默认保留 默认值表达式,存储引擎属性,check 约束,注释 */
+ String uIncluding = " INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE";
+ String lIncluding = " including defaults including constraints including indexs including storage";
+ this.print0(this.ucase ? uIncluding : lIncluding);
+ this.print0(")");
+ return false;
+ }
+ this.printTableElements(x.getTableElementList());
+ List tableOptions = x.getTableOptions();
+ Iterator var16 = tableOptions.iterator();
+ while (var16.hasNext()) {
+ SQLAssignItem option = (SQLAssignItem) var16.next();
+ String key = ((SQLIdentifierExpr) option.getTarget()).getName();
+ if ("TABLESPACE".equals(key)) {
+ this.print(' ');
+ this.print0(this.ucase ? key : key.toLowerCase());
+ this.print(' ');
+ option.getValue().accept(this);
+ }
+ else
+ {
+ printUcaseNotSupportWord(option.toString());
+ gaussFeatureNotSupportLog("tableOption " + key + " when it creates table" + getTypeAttribute(x));
+ }
+ }
+ SQLExpr comment = x.getComment();
+ if (comment != null) {
+ printUcaseNotSupportWord("comment " + x.getComment());
+ gaussFeatureNotSupportLog("COMMENT in column_definition when it creates table" + getTypeAttribute(x));
+ }
+ if (isPartition) {
+ println();
+ print0(this.ucase ? "PARTITION BY " : "partition by ");
+ partitionBy.accept(this);
+ }
+
+ if (x.isReplace()) {
+ printUcaseNotSupportWord("replace");
+ gaussFeatureNotSupportLog("REPLACE when it creates table" + getTypeAttribute(x));
+ } else if (x.isIgnore()) {
+ printUcaseNotSupportWord("ignore");
+ gaussFeatureNotSupportLog("IGNORE when it creates table" + getTypeAttribute(x));
+ }
+ if (x.getSelect() != null) {
+ logger.error(
+ "AS query_expression in create table statement have essentially different between mysql and openGuass"
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ Iterator var21 = x.getOptionHints().iterator();
+ while (var21.hasNext()) {
+ SQLCommentHint hint = (SQLCommentHint) var21.next();
+ this.print(' ');
+ hint.accept(this);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLPartitionByHash x) {
+ if (x.getColumns().size() > 1 || x.getColumns().size() == 0) {
+ logger.error("the number of columns of 'partition by' hash cannot exceed 1 or equal 0 at openGauss "
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ if (!checkColumnName(x)) {
+ logger.error("chameleon does not support partition by hash(methodInvokeExpr)" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+ if (x.isLinear()) {
+ printUcaseNotSupportWord("linear");
+ gaussFeatureNotSupportLog("linear hash of partition" + getTypeAttribute(x));
+ }
+ this.print0(this.ucase ? "HASH (" : "hash (");
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ this.printPartitionsCountAndSubPartitions(x);
+ if (x.getPartitions().size() > 0) {
+ this.printSQLPartitions(x.getPartitions());
+ } else {
+ logger.error("partition name must be specified in openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLSubPartitionByHash x) {
+ if(x.getExpr() instanceof SQLMethodInvokeExpr){
+ logger.error(
+ "chameleon does not support partition by hash(methodInvokeExpr)" + getTypeAttribute(x));
+ errHandle(x,"hash(methodInvoke)");
+ return false;
+ }
+ if (x.isLinear()) {
+ printUcaseNotSupportWord("linear");
+ gaussFeatureNotSupportLog("linear hash of partition" + getTypeAttribute(x));
+ } else {
+ printUcase("SUBPARTITION BY HASH ");
+ }
+ this.print('(');
+ x.getExpr().accept(this);
+ this.print(')');
+ if (x.getSubPartitionsCount() != null) {
+ printUcaseNotSupportWord("subpartitions " + x.getSubPartitionsCount());
+ gaussFeatureNotSupportLog("specifying subpartition count" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlPartitionByKey x) {
+ gaussFeatureNotSupportLog("key of partition, hash will be used"+getTypeAttribute(x));
+ if (x.getColumns().size() > 1 || x.getColumns().size() == 0) {
+ logger.error("the number of columns of partition by hash cannot exceed 1 or equal 0 at openGauss ");
+ errHandle(x);
+ }
+ if (x.isLinear()) {
+ printUcaseNotSupportWord("linear");
+ gaussFeatureNotSupportLog("linear hash of partition" + getTypeAttribute(x));
+ }
+ this.print0(this.ucase ? "HASH" : "hash");
+ if (!"".equals(x.getAlgorithm() + ""))
+ {
+ printUcaseNotSupportWord("algorithm=" + x.getAlgorithm());
+ gaussFeatureNotSupportLog("algorithm of partition by key" + getTypeAttribute(x));
+ }
+ this.print('(');
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ this.printPartitionsCountAndSubPartitions(x);
+ if (x.getPartitions().size() > 0) {
+ this.printSQLPartitions(x.getPartitions());
+ } else {
+ logger.error("partition name must be specified in openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlSubPartitionByKey x) {
+ gaussFeatureNotSupportLog("key of subPartition, hash will be used" + getTypeAttribute(x));
+ if (x.getColumns().size() > 1 || x.getColumns().size() == 0) {
+ logger.error("the number of columns of subPartition by hash cannot exceed 1 or equal 0 at openGauss "
+ + getTypeAttribute(x));
+ errHandle(x,"improper number of columns");
+ return false;
+ }
+ if (x.isLinear()) {
+ printUcaseNotSupportWord("linear");
+ gaussFeatureNotSupportLog("linear key of subPartition" + getTypeAttribute(x));
+ }
+ printUcase("subPartition by hash (");
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ if (x.getSubPartitionsCount() != null) {
+ printUcaseNotSupportWord("subpartitions " + x.getSubPartitionsCount());
+ gaussFeatureNotSupportLog("specifying subPartition count" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLPartitionByRange x) {
+ if (!checkColumnName(x)) {
+ logger.error("chameleon does not support partition by range(methodInvokeExpr)" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ if (x.getColumns().size() > 4 || x.getColumns().size() == 0) {
+ logger.error("the number of columns of partition by range cannot exceed 4 or equal 0 at openGauss "
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ printUcase("range (");
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ this.printPartitionsCountAndSubPartitions(x);
+ if (x.getPartitions().size() > 0) {
+ this.print(" (");
+ ++this.indentCount;
+ int i = 0;
+ for (int size = x.getPartitions().size(); i < size; ++i) {
+ if (i != 0) {
+ this.print(',');
+ }
+ this.println();
+ ((SQLPartition) x.getPartitions().get(i)).accept(this);
+ }
+ --this.indentCount;
+ this.println();
+ this.print(')');
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLPartitionByList x) {
+ if (x.getColumns().size() > 1 || x.getColumns().size() == 0) {
+ logger.error("the number of columns of 'partition by' list cannot exceed 1 or equal 0 at openGauss "
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ if (!checkColumnName(x)) {
+ logger.error("chameleon does not support partition by list(methodInvokeExpr)" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ this.print0(this.ucase ? "LIST " : "list ");
+ if (x.getColumns().size() == 1) {
+ this.print('(');
+ ((SQLExpr) x.getColumns().get(0)).accept(this);
+ this.print0(")");
+ } else {
+ this.print0(this.ucase ? "COLUMNS (" : "columns (");
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print0(")");
+ }
+ this.printPartitionsCountAndSubPartitions(x);
+ this.printSQLPartitions(x.getPartitions());
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLPartitionValue x) {
+ if (x.getOperator() == SQLPartitionValue.Operator.LessThan && DbType.oracle != this.getDbType()
+ && x.getItems().size() == 1 && x.getItems().get(0) instanceof SQLIdentifierExpr) {
+ SQLIdentifierExpr ident = (SQLIdentifierExpr) x.getItems().get(0);
+ if ("MAXVALUE".equalsIgnoreCase(ident.getName())) {
+ this.print0(this.ucase ? "VALUES LESS THAN MAXVALUE" : "values less than maxvalue");
+ return false;
+ }
+ }
+ if (x.getOperator() == SQLPartitionValue.Operator.LessThan) {
+ this.print0(this.ucase ? "VALUES LESS THAN (" : "values less than (");
+ } else if (x.getOperator() == SQLPartitionValue.Operator.In) {
+ this.print0(this.ucase ? "VALUES (" : "values (");
+ } else {
+ this.print(this.ucase ? "VALUES (" : "values (");
+ }
+ this.printAndAccept(x.getItems(), ", ", false);
+ this.print(')');
+ return false;
+ }
+
+ private boolean checkColumnName(SQLPartitionBy x) {
+ Iterator var4 = x.getColumns().iterator();
+ while (var4.hasNext()) {
+ SQLExpr column = (SQLExpr) var4.next();
+ if (!(column instanceof SQLName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public void printSQLPartitions(List partitions) {
+ int partitionsSize = partitions.size();
+ if (partitionsSize > 0) {
+ this.print0(" (");
+ ++this.indentCount;
+ for (int i = 0; i < partitionsSize; ++i) {
+ this.println();
+ ((SQLPartition) partitions.get(i)).accept(this);
+ if (i != partitionsSize - 1) {
+ this.print0(", ");
+ }
+ }
+ --this.indentCount;
+ this.println();
+ this.print(')');
+ }
+
+ }
+
+ public boolean visit(SQLPartition x) {
+ printUcase("partition ");
+ x.getName().accept(this);
+ if (x.getValues() != null) {
+ this.print(' ');
+ x.getValues().accept(this);
+ }
+ if (x.getDataDirectory() != null) {
+ printNotSupportWord((this.ucase ? "DATA DIRECTORY " : "data directory ") + x.getDataDirectory());
+ gaussFeatureNotSupportLog("specifying data directory at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getIndexDirectory() != null) {
+ printNotSupportWord((this.ucase ? "INDEX DIRECTORY " : "index directory ") + x.getIndexDirectory());
+ gaussFeatureNotSupportLog("specifying index directory at partition definition" + getTypeAttribute(x));
+ }
+ ++this.indentCount;
+ this.printOracleSegmentAttributes(x);
+ if (x.getEngine() != null) {
+ printNotSupportWord((this.ucase ? "STORAGE ENGINE " : "storage engine ") + x.getEngine());
+ gaussFeatureNotSupportLog("specifying engine at partition definition"+getTypeAttribute(x));
+ }
+ --this.indentCount;
+ if (x.getMaxRows() != null) {
+ printNotSupportWord((this.ucase ? " MAX_ROWS " : " max_rows ") + x.getMaxRows());
+ gaussFeatureNotSupportLog("specifying max_rows at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getMinRows() != null) {
+ printNotSupportWord((this.ucase ? " MIN_ROWS " : " min_rows ") + x.getMinRows());
+ gaussFeatureNotSupportLog("specifying min_rows at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getComment() != null) {
+ printNotSupportWord((this.ucase? " COMMENT " : " comment ") + x.getComment());
+ gaussFeatureNotSupportLog("specifying comment at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getSubPartitionsCount() != null) {
+ printUcaseNotSupportWord("subpartitions " + x.getSubPartitionsCount());
+ gaussFeatureNotSupportLog("specifying subPartition at partition definition" + getTypeAttribute(x));
+ }
+ SQLObject parent = x.getParent();
+ if (x.getSubPartitions().size() > 0) {
+ this.print(" (");
+ ++this.indentCount;
+ for(int i = 0; i < x.getSubPartitions().size(); ++i) {
+ if (i != 0) {
+ this.print(',');
+ }
+ this.println();
+ ((SQLSubPartition)x.getSubPartitions().get(i)).accept(this);
+ }
+ --this.indentCount;
+ this.println();
+ this.print(')');
+ }else if (parent instanceof SQLPartitionBy && ((SQLPartitionBy)parent).getSubPartitionBy() != null){
+ logger.error("subPartition name must be specified in openGauss" + getTypeAttribute(x));
+ errHandle(x,"subPartition name");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLSubPartition x) {
+ this.print0(this.ucase ? "SUBPARTITION " : "subpartition ");
+ x.getName().accept(this);
+ if (x.getValues() != null) {
+ this.print(' ');
+ x.getValues().accept(this);
+ }
+ if (x.getDataDirectory() != null) {
+ printNotSupportWord((this.ucase ? "DATA DIRECTORY " : "data directory ") + x.getDataDirectory());
+ gaussFeatureNotSupportLog("specifying data directory at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getIndexDirectory() != null) {
+ printNotSupportWord((this.ucase ? "INDEX DIRECTORY " : "index directory ") + x.getIndexDirectory());
+ gaussFeatureNotSupportLog("specifying index directory at partition definition" + getTypeAttribute(x));
+ }
+ ++this.indentCount;
+ this.printOracleSegmentAttributes(x);
+ if (x.getEngine() != null) {
+ printNotSupportWord((this.ucase ? "STORAGE ENGINE " : "storage engine ") + x.getEngine());
+ gaussFeatureNotSupportLog("specifying engine at partition definition" + getTypeAttribute(x));
+ }
+ --this.indentCount;
+ if (x.getMaxRows() != null) {
+ printNotSupportWord((this.ucase ? " MAX_ROWS " : " max_rows ") + x.getMaxRows());
+ gaussFeatureNotSupportLog("specifying max_rows at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getMinRows() != null) {
+ printNotSupportWord((this.ucase ? " MIN_ROWS " : " min_rows ") + x.getMinRows());
+ gaussFeatureNotSupportLog("specifying min_rows at partition definition" + getTypeAttribute(x));
+ }
+ if (x.getComment() != null) {
+ printNotSupportWord((this.ucase? " COMMENT " : " comment ") + x.getComment());
+ gaussFeatureNotSupportLog("specifying comment at partition definition" + getTypeAttribute(x));
+ }
+ SQLName tableSpace = x.getTablespace();
+ if (tableSpace != null) {
+ this.print0(this.ucase ? " TABLESPACE " : " tablespace ");
+ tableSpace.accept(this);
+ }
+ return false;
+ }
+
+ @Override
+ protected void printPartitionsCountAndSubPartitions(SQLPartitionBy x) {
+ SQLExpr partitionsCount = x.getPartitionsCount();
+ if (partitionsCount != null && x.getParent() instanceof MySqlCreateTableStatement) {
+ printUcaseNotSupportWord("partitions " + partitionsCount);
+ gaussFeatureNotSupportLog("specifying partition count"+getTypeAttribute(x));
+ }
+ if (x.getSubPartitionBy() != null) {
+ this.println();
+ x.getSubPartitionBy().accept(this);
+ }
+ }
+
+ @Override
+ public boolean visit(MySqlCreateTableStatement.TableSpaceOption x) {
+ x.getName().accept(this);
+ if (x.getStorage() != null) {
+ printUcaseNotSupportWord("storage " + x.getStorage());
+ gaussFeatureNotSupportLog("specifying storage of tablespace" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLColumnDefinition x) {
+ boolean parameterized = this.parameterized;
+ this.parameterized = false;
+ x.getName().setParent(x);
+ x.getName().accept(this);
+ SQLDataType dataType = x.getDataType();
+ if (dataType != null) {
+ this.print(' ');
+ dataType.accept(this);
+ }
+ SQLExpr generatedAlawsAs = x.getGeneratedAlawsAs();
+ if (generatedAlawsAs != null) {
+ printUcaseNotSupportWord("GENERATED ALWAYS AS (" + generatedAlawsAs + ")");
+ gaussFeatureNotSupportLog("GENERATED ALWAYS AS in column definition" + getTypeAttribute(x));
+ }
+ if (x.isVirtual()) {
+ printUcaseNotSupportWord("virtual");
+ gaussFeatureNotSupportLog("VIRTUAL in column definition" + getTypeAttribute(x));
+ }
+ if (x.isVisible()) {
+ printUcaseNotSupportWord("visible");
+ gaussFeatureNotSupportLog("VISIBLE in column definition" + getTypeAttribute(x));
+ }
+ SQLExpr charsetExpr = x.getCharsetExpr();
+ if (charsetExpr != null) {
+ printUcaseNotSupportWord("character set " + charsetExpr);
+ gaussFeatureNotSupportLog("CHARACTER SET in column definition" + getTypeAttribute(x));
+ }
+ SQLExpr collateExpr = x.getCollateExpr();
+ if (collateExpr != null) {
+ printUcaseNotSupportWord("collate " + collateExpr);
+ gaussFeatureNotSupportLog("collate in column definition" + getTypeAttribute(x));
+ }
+ Iterator var7 = x.getConstraints().iterator();
+ while (var7.hasNext()) {
+ SQLColumnConstraint item = (SQLColumnConstraint) var7.next();
+ if (!(item instanceof SQLColumnReference)) {
+ this.print(' ');
+ item.accept(this);
+ }
+ }
+ SQLExpr defaultExpr = x.getDefaultExpr();
+ if (defaultExpr != null) {
+ this.print0(this.ucase ? " DEFAULT " : " default ");
+ defaultExpr.accept(this);
+ }
+ if (x.getComment() != null) {
+ printNotSupportWord((this.ucase? "COMMENT " : "comment ") + x.getComment());
+ chameFeatureNotSupportLog("COMMENT in column definition"+getTypeAttribute(x));
+ }
+ SQLExpr format = x.getFormat();
+ if (format != null) {
+ printNotSupportWord((this.ucase? "COLUMN_FORMAT " : "comment_format") + format);
+ gaussFeatureNotSupportLog("COLUMN FORMAT in column definition"+getTypeAttribute(x));
+ }
+ SQLExpr storage = x.getStorage();
+ if (storage != null) {
+ printUcaseNotSupportWord("storage " + storage);
+ gaussFeatureNotSupportLog("STORAGE in column definition" + getTypeAttribute(x));
+ }
+ // SQLExpr onUpdate = x.getOnUpdate();
+ // if (onUpdate != null) {
+ // this.print0(this.ucase ? " ON UPDATE " : " on update ");
+ // onUpdate.accept(this);
+ // }
+ if (x.getAsExpr() != null) {
+ printUcaseNotSupportWord("as");
+ gaussFeatureNotSupportLog("AS in column definition" + getTypeAttribute(x));
+ }
+ Iterator var17 = x.getConstraints().iterator();
+ while (var17.hasNext()) {
+ SQLColumnConstraint item = (SQLColumnConstraint) var17.next();
+ if (item instanceof SQLColumnReference) {
+ this.print(' ');
+ item.accept(this);
+ }
+ }
+ this.parameterized = parameterized;
+ return false;
+ }
+
+ @Override
+ public boolean visit(MysqlForeignKey x) {
+ if (x.isHasConstraint()) {
+ this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
+ if (x.getName() != null) {
+ x.getName().accept(this);
+ this.print(' ');
+ }
+ }
+ this.print0(this.ucase ? "FOREIGN KEY" : "foreign key");
+ if (x.getIndexName() != null) {
+ printNotSupportWord((this.ucase ? "FOREIGN KEY NAME " : "foreign key name ") + x.getIndexName());
+ gaussFeatureNotSupportLog("specifying the index name of foreign key" + getTypeAttribute(x));
+ }
+ this.print0(" (");
+ this.printAndAccept(x.getReferencingColumns(), ", ");
+ this.print(')');
+ this.print0(this.ucase ? " REFERENCES " : " references ");
+ x.getReferencedTableName().accept(this);
+ this.print0(" (");
+ this.printAndAccept(x.getReferencedColumns(), ", ");
+ this.print(')');
+ SQLForeignKeyImpl.Match match = x.getReferenceMatch();
+ if (match != null) {
+ this.print0(this.ucase ? " MATCH " : " match ");
+ this.print0(this.ucase ? match.name : match.name_lcase);
+ }
+ if (x.getOnDelete() != null) {
+ this.print0(this.ucase ? " ON DELETE " : " on delete ");
+ this.print0(this.ucase ? x.getOnDelete().name : x.getOnDelete().name_lcase);
+ }
+ if (x.getOnUpdate() != null) {
+ this.print0(this.ucase ? " ON UPDATE " : " on update ");
+ this.print0(this.ucase ? x.getOnUpdate().name : x.getOnUpdate().name_lcase);
+ }
+ return false;
+ }
+
+ @Override
+ /* index fulltext spatial */
+ public boolean visit(MySqlTableIndex x) {
+ print("\n-- ");
+ String indexType = x.getIndexType();
+ boolean indexTypePrinted = false;
+ if ("FULLTEXT".equalsIgnoreCase(indexType)) {
+ this.print0(this.ucase ? "FULLTEXT " : "fulltext ");
+ indexTypePrinted = true;
+ } else if ("SPATIAL".equalsIgnoreCase(indexType)) {
+ this.print0(this.ucase ? "SPATIAL " : "spatial ");
+ indexTypePrinted = true;
+ } else if ("CLUSTERED".equalsIgnoreCase(indexType)) {
+ this.print0(this.ucase ? "CLUSTERED " : "clustered ");
+ indexTypePrinted = true;
+ } else if ("CLUSTERING".equalsIgnoreCase(indexType)) {
+ this.print0(this.ucase ? "CLUSTERING " : "clustering ");
+ indexTypePrinted = true;
+ }
+ if (x.getIndexDefinition().isGlobal()) {
+ this.print0(this.ucase ? "GLOBAL " : "global ");
+ } else if (x.getIndexDefinition().isLocal()) {
+ this.print0(this.ucase ? "LOCAL " : "local ");
+ }
+ this.print0(this.ucase ? "INDEX" : "index");
+ if (x.getName() != null) {
+ this.print(' ');
+ x.getName().accept(this);
+ }
+ if (indexType != null && !indexTypePrinted && "ANN".equals(indexType)) {
+ this.print0(" ");
+ this.print0(indexType);
+ }
+ if (Boolean.TRUE.equals(x.getAttribute("ads.index"))) {
+ if (x.getIndexDefinition().isHashMapType()) {
+ this.print0(this.ucase ? " HASHMAP" : " hashmap");
+ } else if (x.getIndexDefinition().isHashType()) {
+ this.print0(this.ucase ? " HASH" : " hash");
+ }
+ }
+ String using = x.getIndexDefinition().hasOptions() ? x.getIndexDefinition().getOptions().getIndexType() : null;
+ if (using != null) {
+ this.print0(this.ucase ? " USING " : " using ");
+ this.print0(using);
+ }
+ this.print('(');
+ int i;
+ for(i = x.getColumns().size(); i < i; ++i) {
+ if (i != 0) {
+ this.print0(", ");
+ }
+ ((SQLSelectOrderByItem)x.getColumns().get(i)).accept(this);
+ }
+ this.print(')');
+ if (x.getAnalyzerName() != null) {
+ this.print0(this.ucase ? " WITH ANALYZER " : " with analyzer ");
+ x.getAnalyzerName().accept(this);
+ } else {
+ if (x.getIndexAnalyzerName() != null) {
+ this.print0(this.ucase ? " WITH INDEX ANALYZER " : " with index analyzer ");
+ x.getIndexAnalyzerName().accept(this);
+ }
+ if (x.getQueryAnalyzerName() != null) {
+ this.print0(this.ucase ? " WITH QUERY ANALYZER " : " with query analyzer ");
+ x.getQueryAnalyzerName().accept(this);
+ }
+ if (x.getWithDicName() != null) {
+ this.printUcase(" WITH DICT ");
+ x.getWithDicName().accept(this);
+ }
+ }
+ List covering = x.getCovering();
+ if (null != covering && covering.size() > 0) {
+ this.print0(this.ucase ? " COVERING " : " covering ");
+ this.print('(');
+ i = 0;
+ for(int size = covering.size(); i < size; ++i) {
+ if (i != 0) {
+ this.print0(", ");
+ }
+ ((SQLName)covering.get(i)).accept(this);
+ }
+ this.print(')');
+ }
+ SQLExpr dbPartitionBy = x.getDbPartitionBy();
+ if (dbPartitionBy != null) {
+ this.print0(this.ucase ? " DBPARTITION BY " : " dbpartition by ");
+ dbPartitionBy.accept(this);
+ }
+ SQLExpr tablePartitionBy = x.getTablePartitionBy();
+ if (tablePartitionBy != null) {
+ this.print0(this.ucase ? " TBPARTITION BY " : " tbpartition by ");
+ tablePartitionBy.accept(this);
+ }
+ SQLExpr tablePartitions = x.getTablePartitions();
+ if (tablePartitions != null) {
+ this.print0(this.ucase ? " TBPARTITIONS " : " tbpartitions ");
+ tablePartitions.accept(this);
+ }
+ if (x.getIndexDefinition().hasOptions()) {
+ x.getIndexDefinition().getOptions().accept(this);
+ }
+ print("\n");
+ gaussFeatureNotSupportLog("specifying index" + getTypeAttribute(x));
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlKey x) {
+ print("\n-- ");
+ if (x.isHasConstraint()) {
+ this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
+ if (x.getName() != null) {
+ x.getName().accept(this);
+ this.print(' ');
+ }
+ }
+ String indexType = x.getIndexType();
+ boolean fullText = "FULLTEXT".equalsIgnoreCase(indexType);
+ boolean clustering = "CLUSTERING".equalsIgnoreCase(indexType);
+ boolean clustered = "CLUSTERED".equalsIgnoreCase(indexType);
+ if (fullText) {
+ this.print0(this.ucase ? "FULLTEXT " : "fulltext ");
+ } else if (clustering) {
+ this.print0(this.ucase ? "CLUSTERING " : "clustering ");
+ } else if (clustered) {
+ this.print0(this.ucase ? "CLUSTERED " : "CLUSTERED ");
+ }
+ this.print0(this.ucase ? "KEY" : "key");
+ SQLName name = x.getName();
+ if (name != null) {
+ this.print(' ');
+ name.accept(this);
+ }
+ if (indexType != null && !fullText && !clustering && !clustered) {
+ this.print0(this.ucase ? " USING " : " using ");
+ this.print0(indexType);
+ }
+ this.print0(" (");
+ int i = 0;
+ for(int size = x.getColumns().size(); i < size; ++i) {
+ if (i != 0) {
+ this.print0(", ");
+ }
+ ((SQLSelectOrderByItem)x.getColumns().get(i)).accept(this);
+ }
+ this.print(')');
+ SQLIndexDefinition indexDefinition = x.getIndexDefinition();
+ if (indexDefinition.hasOptions()) {
+ indexDefinition.getOptions().accept(this);
+ }
+ SQLExpr comment = x.getComment();
+ if (indexDefinition.hasOptions() && indexDefinition.getOptions().getComment() == comment) {
+ comment = null;
+ }
+ if (comment != null) {
+ this.print0(this.ucase ? " COMMENT " : " comment ");
+ this.printExpr(comment);
+ }
+ print("\n");
+ gaussFeatureNotSupportLog("specifying key when it creates table" + getTypeAttribute(x));
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCheck x) {
+ SQLName name = x.getName();
+ if (name != null) {
+ this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
+ name.accept(this);
+ this.print(' ');
+ }
+ this.print0(this.ucase ? "CHECK (" : "check (");
+ ++this.indentCount;
+ x.getExpr().accept(this);
+ --this.indentCount;
+ this.print(')');
+ Boolean enforced = x.getEnforced();
+ if (enforced != null) {
+ printUcaseNotSupportWord(enforced ? " ENFORCED" : " NOT ENFORCED");
+ gaussFeatureNotSupportLog("check enforced in column definition" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDataType x) {
+ this.printDataType(x);
+ if (x instanceof SQLDataTypeImpl) {
+ SQLDataTypeImpl dataTypeImpl = (SQLDataTypeImpl) x;
+ if (dataTypeImpl.isUnsigned()) {
+ printUcaseNotSupportWord("unsigned");
+ gaussFeatureNotSupportLog("unsigned" + getTypeAttribute(x));
+ }
+ if (dataTypeImpl.isZerofill()) {
+ printUcaseNotSupportWord("zerofill");
+ gaussFeatureNotSupportLog("zerofill" + getTypeAttribute(x));
+ }
+ }
+ if (x instanceof SQLCharacterDataType) {
+ SQLCharacterDataType charType = (SQLCharacterDataType) x;
+ if (charType.getCharSetName() != null) {
+ printNotSupportWord((this.ucase ? " CHARACTER SET " : " character set ") + charType.getCharSetName());
+ logger.warn("openGauss does not support character set" + getTypeAttribute(x));
+ if (charType.getCollate() != null) {
+ printNotSupportWord((this.ucase ? " CHARACTER SET " : " character set ") + charType.getCollate());
+ }
+ }
+ List hints = ((SQLCharacterDataType) x).hints;
+ if (hints != null) {
+ this.print(' ');
+ Iterator var4 = hints.iterator();
+ while (var4.hasNext()) {
+ SQLCommentHint hint = (SQLCommentHint) var4.next();
+ hint.accept(this);
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCharacterDataType x) {
+ this.printDataType(x);
+ if (x.getCharSetName() != null) {
+ printNotSupportWord((this.ucase ? " CHARACTER SET " : " character set ") + x.getCharSetName());
+ logger.warn("openGauss does not support character set" + getTypeAttribute(x));
+ if (x.getCollate() != null) {
+ printNotSupportWord((this.ucase ? " CHARACTER SET " : " character set ") + x.getCollate());
+ }
+ }
+ List hints = x.hints;
+ if (hints != null) {
+ this.print(' ');
+ Iterator var3 = hints.iterator();
+ while (var3.hasNext()) {
+ SQLCommentHint hint = (SQLCommentHint) var3.next();
+ hint.accept(this);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void printTableElements(List tableElementList) {
+ int size = tableElementList.size();
+ if (size != 0) {
+ this.print0(" (");
+ ++this.indentCount;
+ this.println();
+ // Indicates whether this element is printed
+ boolean[] noPrints = new boolean[size];
+ for(int i = 0; i < size; i++){
+ SQLTableElement element = tableElementList.get(i);
+ noPrints[i] = (element instanceof MySqlTableIndex || element instanceof MySqlKey &&
+ !(element instanceof MySqlUnique || element instanceof MySqlPrimaryKey));
+ }
+ // Indicates whether to print commas
+ boolean[] noDots = new boolean[size];
+ boolean prev = true;
+ for (int i = size - 1; i > 0; i--) {
+ noDots[i] = noPrints[i] && prev;
+ prev = noDots[i];
+ }
+ for (int i = 0; i < size; ++i) {
+ SQLTableElement element = tableElementList.get(i);
+ element.accept(this);
+ boolean printDot = (i != size - 1 && !noDots[i + 1] && !noPrints[i]);
+ if (printDot) {
+ this.print(',');
+ }
+ if (this.isPrettyFormat() && element.hasAfterComment()) {
+ this.print(' ');
+ this.printlnComment(element.getAfterCommentsDirect());
+ }
+ if (printDot ) {
+ this.println();
+ }
+ }
+ --this.indentCount;
+ this.println();
+ this.print(')');
+ }
+ }
+
+ @Override
+ protected void printDataType(SQLDataType x) {
+ boolean parameterized = this.parameterized;
+ this.parameterized = false;
+ SQLDataType dataType = OpenGaussDataTypeTransformUtil.transformOpenGaussToMysql(x);
+ this.print0(dataType.getName());
+ List arguments = dataType.getArguments();
+ if (arguments.size() > 0) {
+ this.print('(');
+ int i = 0;
+ for (int size = arguments.size(); i < size; ++i) {
+ if (i != 0) {
+ this.print0(", ");
+ }
+ this.printExpr((SQLExpr) arguments.get(i), false);
+ }
+ this.print(')');
+ }
+ long nameHash = dataType.nameHashCode64();
+ if (nameHash == Constants.TIME || nameHash == Constants.TIMESTAMP) {
+ this.print0(this.ucase ? " WITHOUT TIME ZONE" : " without time zone");
+ }
+ /* index by 貌似没得翻译 */
+ this.parameterized = parameterized;
+ }
+
+ @Override
+ public boolean visit(SQLDropTableStatement x) {
+ List headHints = x.getHeadHintsDirect();
+ if (headHints != null) {
+ Iterator var3 = headHints.iterator();
+ while (var3.hasNext()) {
+ SQLCommentHint hint = (SQLCommentHint) var3.next();
+ this.visit(hint);
+ this.println();
+ }
+ }
+ if (x.hasBeforeComment()) {
+ this.printlnComments(x.getBeforeCommentsDirect());
+ }
+ this.print0(this.ucase ? "DROP " : "drop ");
+ List hints = x.getHints();
+ if (hints != null) {
+ this.printAndAccept(hints, " ");
+ this.print(' ');
+ }
+ print0(this.ucase ? "TABLE " : "table ");
+ if (x.isTemporary())
+ printUcaseNotSupportWord("temporary");
+ gaussFeatureNotSupportLog("TEMPORARY when it drops table" + getTypeAttribute(x));
+ if (x.isIfExists()) {
+ this.print0(this.ucase ? "IF EXISTS " : "if exists ");
+ }
+ this.printAndAccept(x.getTableSources(), ", ");
+ if (x.isCascade()) {
+ this.printCascade();
+ }
+ if (x.isRestrict()) {
+ this.print0(this.ucase ? " RESTRICT" : " restrict");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCreateTriggerStatement x) {
+ // openGauss has no DEFINER field
+ if (Objects.nonNull(x.getDefiner())) {
+ print("-- "+(ucase?"DEFINER ":"definer ")+x.getDefiner().toString());
+ println();
+ gaussFeatureNotSupportLog("DEFINER when it creates trigger" + getTypeAttribute(x));
+ }
+ // Since openGauss can support up to 64 character function names, UUID can be
+ // used to generate unique function names
+ String id = UUID.randomUUID().toString();
+ String function_name = "createFunction_" + id.replace("-", "");
+ // first convert the execution body into a custom function
+ println("CREATE OR REPLACE FUNCTION " + function_name + "()" + " RETURNS TRIGGER AS");
+ println("$$");
+ println("DECLARE");
+ println("BEGIN");
+ if (x.getBody() instanceof SQLBlockStatement) {
+ SQLBlockStatement body = (SQLBlockStatement) x.getBody();
+ for (SQLStatement sqlStatement : body.getStatementList()) {
+ sqlStatement.accept(this);
+ println();
+ }
+ } else {
+ x.getBody().accept(this);
+ println();
+ }
+ if (x.isUpdate() || x.isInsert()) {
+ println("RETURN NEW;");
+ } else {
+ println("RETURN OLD;");
+ }
+ println("END;");
+ println("$$ LANGUAGE plpgsql;");
+ println();
+ // create a trigger through a custom function
+ print0("CREATE TRIGGER ");
+ x.getName().accept(this);
+ println();
+ String triggerTypeName = x.getTriggerType().name();
+ print0(this.ucase ? triggerTypeName : triggerTypeName.toLowerCase());
+ if (x.isInsert())
+ printUcase(" INSERT ");
+ if (x.isDelete()) {
+ if (x.isInsert())
+ printUcase(" OR");
+ printUcase(" DELETE ");
+ }
+ if (x.isUpdate()) {
+ if (x.isInsert() || x.isDelete())
+ printUcase(" OR");
+ printUcase(" UPDATE ");
+ }
+ println("ON " + x.getOn());
+ println("FOR EACH ROW");
+ println("EXECUTE PROCEDURE " + function_name + "();");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropTriggerStatement x) {
+ logger.error("drop trigger statement is incompatible with OpenGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlDeleteStatement x) {
+ SQLTableSource from = x.getFrom();
+ if (from == null) {
+ print0(ucase ? "DELETE " : "delete ");
+ if(x.isLowPriority()||x.isIgnore()||x.isQuick()){
+ println();
+ print("-- ");
+ if (x.isLowPriority()) {
+ print0(ucase ? "LOW_PRIORITY " : "low_priority ");
+ gaussFeatureNotSupportLog("LOW_PRIORITY when it deletes" + getTypeAttribute(x));
+ }
+ if (x.isIgnore()) {
+ print0(ucase ? "IGNORE " : "ignore ");
+ gaussFeatureNotSupportLog("IGNORE when it deletes" + getTypeAttribute(x));
+ }
+ if (x.isQuick()) {
+ print0(ucase ? "QUICK " : "quick ");
+ gaussFeatureNotSupportLog("QUICK when it deletes" + getTypeAttribute(x));
+ }
+ println();
+ }
+ if (x.getHints() != null && x.getHints().size() > 0) {
+ println();
+ print("-- ");
+ for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
+ SQLCommentHint hint = x.getHints().get(i);
+ hint.accept(this);
+ print(' ');
+ }
+ println();
+ chameFeatureNotSupportLog("optimizer hint" + getTypeAttribute(x));
+ }
+ print0(this.ucase ? "FROM " : "from ");
+ if (x.getTableSource().toString().split(",").length > 1) {
+ logger.error("openGauss does not support multiple-table syntax of delete" + getTypeAttribute(x));
+ errHandle(x);
+ } else {
+ x.getTableSource().accept(this);
+ }
+ SQLExpr where = x.getWhere();
+ if (where != null) {
+ println();
+ this.indentCount++;
+ print0(ucase ? "WHERE " : "where ");
+ printExpr(where, parameterized);
+ this.indentCount--;
+ }
+ SQLOrderBy orderBy = x.getOrderBy();
+ if (Objects.nonNull(orderBy)) {
+ println();
+ print("-- ");
+ x.getOrderBy().accept(this);
+ println();
+ gaussFeatureNotSupportLog("ORDER BY... when it deletes" + getTypeAttribute(x));
+ }
+ SQLLimit limit = x.getLimit();
+ if (Objects.nonNull(limit)) {
+ print("-- ");
+ x.getLimit().accept(this);
+ println();
+ gaussFeatureNotSupportLog("LIMIT when it deletes" + getTypeAttribute(x));
+ }
+ } else {
+ logger.error("openGauss does not support multiple-table syntax of delete" + getTypeAttribute(x));
+ errHandle(x, " Delete Multiple-Table Syntax");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlInsertStatement x) {
+ final List headHints = x.getHeadHintsDirect();
+ if (headHints != null) {
+ for (SQLCommentHint hint : headHints) {
+ hint.accept(this);
+ println();
+ }
+ }
+ if (this.isPrettyFormat() && x.hasBeforeComment()) {
+ this.printlnComments(x.getBeforeCommentsDirect());
+ }
+ print0(ucase ? "INSERT " : "insert ");
+ if (x.getHints() != null && x.getHints().size() > 0) {
+ println();
+ print("-- ");
+ for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
+ SQLCommentHint hint = x.getHints().get(i);
+ hint.accept(this);
+ print(' ');
+ }
+ println();
+ chameFeatureNotSupportLog("optimizer hint" + getTypeAttribute(x));
+ }
+ if (x.isLowPriority()) {
+ println();
+ print("-- ");
+ print0(ucase ? "LOW_PRIORITY " : "low_priority ");
+ gaussFeatureNotSupportLog("LOW_PRIORITY when it inserts" + getTypeAttribute(x));
+ }
+ if (x.isDelayed()) {
+ println();
+ print("-- ");
+ print0(ucase ? "DELAYED " : "delayed ");
+ gaussFeatureNotSupportLog("DELAYED when it inserts" + getTypeAttribute(x));
+ }
+ if (x.isHighPriority()) {
+ println();
+ print("-- ");
+ print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
+ gaussFeatureNotSupportLog("HIGH_PRIORITY when it inserts" + getTypeAttribute(x));
+ }
+ if (x.isIgnore()) {
+ println();
+ print("-- ");
+ print0(ucase ? "IGNORE " : "ignore ");
+ gaussFeatureNotSupportLog("IGNORE when it inserts" + getTypeAttribute(x));
+ }
+ println();
+ boolean outputIntoKeyword = true;
+ if (outputIntoKeyword) {
+ print0(ucase ? "INTO " : "into ");
+ }
+ SQLExprTableSource tableSource = x.getTableSource();
+ if (tableSource != null) {
+ if (tableSource.getClass() == SQLExprTableSource.class) {
+ visit(tableSource);
+ } else {
+ tableSource.accept(this);
+ }
+ }
+ List partitions = x.getPartitions();
+ if (partitions != null) {
+ if (partitions.size() > 0) {
+ if (partitions.size() > 1) {
+ logger.error("openGauss does not support more than one partition_name" + getTypeAttribute(x));
+ errHandle(x);
+ } else {
+ print0(ucase ? " PARTITION (" : " partition (");
+ for (int i = 0; i < partitions.size(); ++i) {
+ if (i != 0) {
+ print0(", ");
+ }
+ SQLAssignItem assign = partitions.get(i);
+ assign.getTarget().accept(this);
+
+ if (assign.getValue() != null) {
+ print('=');
+ assign.getValue().accept(this);
+ }
+ }
+ print(')');
+ }
+ }
+ }
+ List columns = x.getColumns();
+ if (columns.size() > 0) {
+ this.indentCount++;
+ print0(" (");
+ for (int i = 0, size = columns.size(); i < size; ++i) {
+ if (i != 0) {
+ print0(", ");
+ }
+ SQLExpr column = columns.get(i);
+ if (column instanceof SQLIdentifierExpr) {
+ // opengauss is incompatible with ` and '
+ // printName0(((SQLIdentifierExpr) column).getName());
+ visit((SQLIdentifierExpr) column);
+ } else {
+ printExpr(column, parameterized);
+ }
+ }
+ print(')');
+ this.indentCount--;
+ }
+ List valuesList = x.getValuesList();
+ if (!valuesList.isEmpty()) {
+ println();
+ printValuesList(valuesList);
+ }
+ if (x.getQuery() != null) {
+ println();
+ x.getQuery().accept(this);
+ }
+ List duplicateKeyUpdate = x.getDuplicateKeyUpdate();
+ if (duplicateKeyUpdate.size() != 0) {
+ println();
+ print0(ucase ? "ON DUPLICATE KEY UPDATE " : "on duplicate key update ");
+ for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) {
+ if (i != 0) {
+ if (i % 5 == 0) {
+ println();
+ }
+ print0(", ");
+ }
+ duplicateKeyUpdate.get(i).accept(this);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLIdentifierExpr x) {
+ SQLObject root = x;
+ while (root.getParent() != null) {
+ root = root.getParent();
+ }
+ if (root instanceof MySqlInsertStatement || root instanceof MySqlCreateTableStatement) {
+ // opengauss is incompatible with ` and '
+ // printName0(((SQLIdentifierExpr) column).getName());
+ try {
+ String text = x.getName();
+ char c0 = text.charAt(0);
+ if (c0 == '`' && text.charAt(text.length() - 1) == '`' ||
+ c0 == "'".charAt(0) && text.charAt(text.length() - 1) == "'".charAt(0)) {
+ this.appender.append(text.substring(1, text.length() - 1));
+ } else {
+ this.appender.append(text);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("println error", e);
+ }
+ return false;
+ } else {
+ return super.visit(x);
+ }
+ }
+
+ // 13.2.8 REPLACE Statement
+ @Override
+ public boolean visit(SQLReplaceStatement x) {
+ logger.error("replace statement is incompatible with OpenGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCreateViewStatement x) {
+ print0(ucase ? "CREATE " : "create ");
+ if (x.isOrReplace()) {
+ print0(ucase ? "OR REPLACE " : "or replace ");
+ }
+ this.indentCount++;
+ if(x.getAlgorithm()!=null&&x.getAlgorithm().length()>0
+ ||x.getDefiner()!=null
+ ||x.getSqlSecurity()!=null&&x.getSqlSecurity().length()>0){
+ println();
+ String algorithm = x.getAlgorithm();
+ if (algorithm != null && algorithm.length() > 0) {
+ print("-- ");
+ print0(ucase ? "ALGORITHM = " : "algorithm = ");
+ print0(algorithm);
+ println();
+ gaussFeatureNotSupportLog("ALGORITHM when it creates view" + getTypeAttribute(x));
+ }
+ SQLName definer = x.getDefiner();
+ if (definer != null) {
+ print("-- ");
+ print0(ucase ? "DEFINER = " : "definer = ");
+ definer.accept(this);
+ println();
+ gaussFeatureNotSupportLog("DEFINER when it creates view" + getTypeAttribute(x));
+ }
+ String sqlSecurity = x.getSqlSecurity();
+ if (sqlSecurity != null && sqlSecurity.length() > 0) {
+ print("-- ");
+ print0(ucase ? "SQL SECURITY = " : "sql security = ");
+ print0(sqlSecurity);
+ println();
+ gaussFeatureNotSupportLog("SQL SECURITY when it creates view" + getTypeAttribute(x));
+ }
+ }
+ this.indentCount--;
+ print0(ucase ? "VIEW " : "view ");
+ x.getTableSource().accept(this);
+ List columns = x.getColumns();
+ if (columns.size() > 0) {
+ print0(" (");
+ this.indentCount++;
+ println();
+ for (int i = 0; i < columns.size(); ++i) {
+ if (i != 0) {
+ print0(", ");
+ println();
+ }
+ columns.get(i).accept(this);
+ }
+ this.indentCount--;
+ println();
+ print(')');
+ }
+ println();
+ print0(ucase ? "AS" : "as");
+ println();
+ SQLSelect subQuery = x.getSubQuery();
+ if (subQuery != null) {
+ subQuery.accept(this);
+ }
+ SQLBlockStatement script = x.getScript();
+ if (script != null) {
+ script.accept(this);
+ }
+ if(x.isWithCheckOption()
+ ||x.isWithCascaded()
+ ||x.isWithLocal()){
+ println();
+ if (x.isWithCheckOption()) {
+ print("-- ");
+ print0(ucase ? "WITH CHECK OPTION" : "with check option");
+ println();
+ gaussFeatureNotSupportLog("WITH CHECK OPTION when it creates view" + getTypeAttribute(x));
+ }
+ if (x.isWithCascaded()) {
+ print("-- ");
+ print(ucase?"CASCADED ":"cascaded ");
+ println();
+ gaussFeatureNotSupportLog("CASCADED when it creates view" + getTypeAttribute(x));
+ }
+ if (x.isWithLocal()) {
+ print("-- ");
+ print(ucase?"LOCAL ":"local ");
+ println();
+ gaussFeatureNotSupportLog("LOCAL when it creates view"+getTypeAttribute(x));
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterViewStatement x) {
+ print0(ucase ? "CREATE OR REPLACE " : "create or replace ");
+ this.indentCount++;
+ String algorithm = x.getAlgorithm();
+ if (algorithm != null && algorithm.length() > 0) {
+ println();
+ print("-- ");
+ print0(ucase ? "ALGORITHM = " : "algorithm = ");
+ print0(algorithm);
+ println();
+ gaussFeatureNotSupportLog("ALGORITHM when it alters view" + getTypeAttribute(x));
+ }
+ // ignore definer
+ SQLName definer = x.getDefiner();
+ if (definer != null) {
+ println();
+ print("-- ");
+ print0(ucase ? "DEFINER = " : "definer = ");
+ definer.accept(this);
+ println();
+ gaussFeatureNotSupportLog("DEFINER when it alters view" + getTypeAttribute(x));
+ }
+ String sqlSecurity = x.getSqlSecurity();
+ if (sqlSecurity != null && sqlSecurity.length() > 0) {
+ println();
+ print("-- ");
+ print0(ucase ? "SQL SECURITY " : "sql security ");
+ print0(sqlSecurity);
+ println();
+ gaussFeatureNotSupportLog("SQL SECURITY when it alters view" + getTypeAttribute(x));
+ }
+ this.indentCount--;
+ print0(ucase ? "VIEW " : "view ");
+ x.getTableSource().accept(this);
+ List columns = x.getColumns();
+ if (columns.size() > 0) {
+ print0(" (");
+ this.indentCount++;
+ println();
+ for (int i = 0; i < columns.size(); ++i) {
+ if (i != 0) {
+ print0(", ");
+ println();
+ }
+ columns.get(i).accept(this);
+ }
+ this.indentCount--;
+ println();
+ print(')');
+ }
+ println();
+ print0(ucase ? "AS" : "as");
+ println();
+ SQLSelect subQuery = x.getSubQuery();
+ if (subQuery != null) {
+ subQuery.accept(this);
+ }
+ // opengauss does not support with check option
+ if (x.isWithCheckOption()) {
+ println();
+ print("-- ");
+ print0(ucase ? "WITH CHECK OPTION" : "with check option");
+ println();
+ gaussFeatureNotSupportLog("WITH CHECK OPTION when it alters view" + getTypeAttribute(x));
+ }
+ if (x.isWithCascaded()) {
+ println();
+ print("-- ");
+ print(ucase?"CASCADED ":"cascaded ");
+ println();
+ gaussFeatureNotSupportLog("CASCADED when it alters view" + getTypeAttribute(x));
+ }
+ if (x.isWithLocal()) {
+ println();
+ print("-- ");
+ print(ucase?"LOCAL ":"local ");
+ println();
+ gaussFeatureNotSupportLog("LOCAL when it alters view" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropViewStatement x) {
+ print0(this.ucase ? "DROP VIEW " : "drop view ");
+ if (x.isIfExists())
+ print0(this.ucase ? "IF EXISTS " : "if exists ");
+ printAndAccept(x.getTableSources(), ", ");
+ if (x.isCascade())
+ printCascade();
+ if (x.isRestrict())
+ this.print0(this.ucase ? " RESTRICT" : " restrict");
+ return false;
+ }
+
+ // 13.1.33 RENAME TABLE Statement
+ @Override
+ public boolean visit(MySqlRenameTableStatement x) {
+ print0(this.ucase ? "ALTER TABLE " : "alter table ");
+ if (x.getItems().size() > 1)
+ printAndAccept(x.getItems(), ";ALTER TABLE ");
+ else
+ printAndAccept(x.getItems(), " ");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlRenameTableStatement.Item x) {
+ x.getName().accept(this);
+ print0(this.ucase ? " RENAME TO " : " rename to ");
+ x.getTo().accept(this);
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLTruncateStatement x) {
+ List headHints = x.getHeadHintsDirect();
+ if (headHints != null)
+ for (SQLCommentHint hint : headHints) {
+ visit(hint);
+ println();
+ }
+ print0(this.ucase ? "TRUNCATE TABLE " : "truncate table ");
+ printAndAccept(x.getTableSources(), ", ");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCreateIndexStatement x) {
+ this.print0(this.ucase ? "CREATE " : "create ");
+ String type = x.getType();
+ if (type != null) {
+ if (type.toLowerCase().equals("unique")) {
+ printUcase("unique");
+ } else if (type.toLowerCase().equals("spatial")) {
+ printUcaseNotSupportWord("spatial");
+ gaussFeatureNotSupportLog("spatial index" + getTypeAttribute(x));
+ } else if (type.toLowerCase().equals("fulltext")) {
+ printUcaseNotSupportWord("fulltext");
+ gaussFeatureNotSupportLog("fulltext index" + getTypeAttribute(x));
+ } else {
+ printUcaseNotSupportWord(type);
+ logger.warn("unrecognized keyword " + type + getTypeAttribute(x));
+ }
+ this.print(' ');
+ }
+ this.print0(this.ucase ? "INDEX " : "index ");
+ if (x.getIndexDefinition().hasOptions()) {
+ String algorithm = x.getIndexDefinition().getOptions().getAlgorithm();
+ String lock = x.getIndexDefinition().getOptions().getLock();
+ if (lock != null) {
+ lock = lock.toLowerCase();
+ if (lock.equals("none")) {
+ printUcase("concurrently ");
+ } else if (!(algorithm != null && algorithm.equals("inplace") && lock.equals("default")))
+ printUcaseNotSupportWord("lock " + lock);
+ gaussFeatureNotSupportLog("specifying lock " + lock + " on index" + getTypeAttribute(x));
+ }
+ else
+ lock = "default";
+ if (algorithm != null) {
+ algorithm = algorithm.toLowerCase();
+ if (algorithm.equals("inplace") && lock.equals("default")) {
+ printUcase("concurrently ");
+ } else
+ printUcaseNotSupportWord("algorithm " + algorithm);
+ gaussFeatureNotSupportLog(
+ "specifying algorithm " + algorithm + " on index" + getTypeAttribute(x));
+ }
+ }
+ x.getName().accept(this);
+ this.print0(this.ucase ? " ON " : " on ");
+ x.getTable().accept(this);
+ if (x.getIndexDefinition().hasOptions()) {
+ String using = x.getIndexDefinition().getOptions().getIndexType();
+ if (using != null) {
+ this.print0(this.ucase ? " USING " : " using ");
+ this.print0(this.ucase ? using.toUpperCase() : using.toLowerCase());
+ }
+ x.getIndexDefinition().getOptions().accept(this);
+ }
+ this.print0(" (");
+ this.printAndAccept(x.getItems(), ", ");
+ this.print(')');
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLIndexOptions x) {
+ SQLExpr keyBlockSize = x.getKeyBlockSize();
+ if (keyBlockSize != null) {
+ printUcaseNotSupportWord(" KEY_BLOCK_SIZE = " + keyBlockSize);
+ gaussFeatureNotSupportLog("specifying keyBlockSize on index" + getTypeAttribute(x));
+ }
+ String parserName = x.getParserName();
+ if (parserName != null) {
+ printUcaseNotSupportWord(" WITH PARSER " + parserName);
+ gaussFeatureNotSupportLog("specifying parserName on index" + getTypeAttribute(x));
+ }
+ SQLExpr comment = x.getComment();
+ if (comment != null) {
+ printUcaseNotSupportWord(" COMMENT " + comment);
+ gaussFeatureNotSupportLog("specifying comment on index" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLSelectOrderByItem x) {
+ SQLExpr expr = x.getExpr();
+ SQLObject parent = x.getParent();
+ boolean isParentCreateIndex = (parent != null && parent instanceof SQLCreateIndexStatement);
+ if (isParentCreateIndex && expr instanceof SQLMethodInvokeExpr) {
+ gaussFeatureNotSupportLog("prefix length of columnName on index" + getTypeAttribute(x));
+ print0(((SQLMethodInvokeExpr) expr).getMethodName());
+ } else if (expr instanceof SQLIntegerExpr) {
+ this.print(((SQLIntegerExpr) expr).getNumber().longValue());
+ } else {
+ this.printExpr(expr, this.parameterized);
+ }
+ SQLOrderingSpecification type = x.getType();
+ if (type != null) {
+ if (isParentCreateIndex) {
+ SQLIndexOptions options = ((SQLCreateIndexStatement) parent).getIndexDefinition().getOptions();
+ String using = options.getIndexType();
+ if (using != null && using.toLowerCase().equals("hash")) {
+ logger.error(
+ "method hash does not support ASC/DESC options in openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ }
+ this.print(' ');
+ this.print0(this.ucase ? type.name : type.name_lcase);
+ }
+ SQLCommentHint hint = x.getHint();
+ if (hint != null) {
+ this.visit(hint);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropIndexStatement x) {
+ this.print0(this.ucase ? "DROP INDEX " : "drop index ");
+ gaussFeatureNotSupportLog("specifying table name" + " ," + getTypeAttribute(x));
+ SQLExpr algorithm = x.getAlgorithm();
+ String algorithmName = null;
+ if (algorithm != null) {
+ if (algorithm instanceof SQLIdentifierExpr) {
+ algorithmName = ((SQLIdentifierExpr) algorithm).getName().toLowerCase();
+ }
+ }
+ SQLExpr lockOption = x.getLockOption();
+ String lockName;
+ if (lockOption != null) {
+ if (lockOption instanceof SQLDefaultExpr) {
+ lockName = "default";
+ } else {
+ lockName = ((SQLIdentifierExpr) lockOption).getName().toLowerCase();
+ }
+ } else {
+ lockName = "default";
+ }
+ if (lockName.equals("none")
+ || (algorithmName != null && algorithmName.equals("inplace") && lockName.equals("default"))) {
+ printUcase(" concurrently ");
+ }else if(algorithm != null){
+ printUcaseNotSupportWord("algorithm " + algorithmName);
+ gaussFeatureNotSupportLog("specifying algorithm keyword" + ", " + getTypeAttribute(x));
+ } else if (x.getLockOption() != null) {
+ printUcaseNotSupportWord("lock = " + lockName);
+ gaussFeatureNotSupportLog("specifying lock keyword" + ", " + getTypeAttribute(x));
+ }
+ if (x.getIndexName().getSimpleName().equals("`PRIMARY`")) {
+ print0(x.getTableName().getTableName() + "_pkey");
+ } else {
+ x.getIndexName().accept(this);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableStatement x) {
+ List headHints = x.getHeadHintsDirect();
+ if (headHints != null) {
+ Iterator var3 = headHints.iterator();
+ while (var3.hasNext()) {
+ SQLCommentHint hint = (SQLCommentHint) var3.next();
+ hint.accept(this);
+ this.println();
+ }
+ }
+ this.print0(this.ucase ? "ALTER " : "alter ");
+ this.print0(this.ucase ? "TABLE " : "table ");
+ this.printTableSourceExpr(x.getName());
+ ++this.indentCount;
+ int i;
+ for (i = 0; i < x.getItems().size(); ++i) {
+ SQLAlterTableItem item = (SQLAlterTableItem) x.getItems().get(i);
+ if (item instanceof SQLAlterTableRename) {
+ if (i != 0) {
+ printUcase(";\nalter table ");
+ this.printTableSourceExpr(x.getName());
+ print(' ');
+ }
+ item.accept(this);
+ if (i != x.getItems().size() - 1) {
+ printUcase(";\nalter table ");
+ this.printTableSourceExpr(((SQLAlterTableRename) item).getToName());
+ }
+ continue;
+ }
+ if (i != 0 && !(x.getItems().get(i - 1) instanceof SQLAlterTableRename)) {
+ this.print(',');
+ }
+ this.println();
+ if (item instanceof SQLAlterTableAnalyzePartition || item instanceof SQLAlterTableCheckPartition
+ || item instanceof SQLAlterTableReOrganizePartition || item instanceof SQLAlterTableRebuildPartition
+ || item instanceof SQLAlterTableRepairPartition || item instanceof SQLAlterTableOptimizePartition
+ || item instanceof SQLAlterTableCoalescePartition || item instanceof SQLAlterTableDiscardPartition
+ || item instanceof SQLAlterTableImportPartition) {
+ logger.error("unknown keyword about alter table partition" + getTypeAttribute(x));
+ errHandle(x, "unknown partition keyword");
+ }
+ item.accept(this);
+ }
+ if (x.isRemovePatiting()) {
+ logger.error("openGauss does not support removing partition" + getTypeAttribute(x));
+ errHandle(x, "unsupported removing partition");
+ }
+ if (x.isUpgradePatiting()) {
+ logger.error("openGauss does not support upgrading partition" + getTypeAttribute(x));
+ errHandle(x, "unsupported upgrading partition");
+ }
+ if (x.getTableOptions().size() > 0) {
+ if (x.getItems().size() > 0) {
+ this.print(',');
+ }
+ this.println();
+ }
+ --this.indentCount;
+ i = 0;
+ Iterator var9 = x.getTableOptions().iterator();
+ while (var9.hasNext()) {
+ SQLAssignItem item = (SQLAssignItem) var9.next();
+ SQLExpr key = item.getTarget();
+ if (i != 0) {
+ this.print(' ');
+ }
+ if ("TABLESPACE".equals(key.toString().toUpperCase())) {
+ printUcase("set tablespace ");
+ item.getValue().accept(this);
+ } else {
+ logger.error("openGauss does not support tableOption " + key.toString() + " when it alters table"
+ + getTypeAttribute(x));
+ errHandle(x, key.toString());
+ }
+ }
+ SQLPartitionBy partitionBy = x.getPartition();
+ if (partitionBy != null) {
+ logger.error("openGauss does not support partition by when it alters table" + getTypeAttribute(x));
+ errHandle(x, "partition by");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableRename x) {
+ printUcase(" rename to ");
+ x.getTo().accept(this);
+ return false;
+ }
+
+ /* primary key and unique */
+ @Override
+ public boolean visit(SQLIndexDefinition x) {
+ if (x.getParent() instanceof SQLAlterTableAddIndex) {
+ printUcase("index ");
+ if (x.getType() != null) {
+ printUcaseNotSupportWord(x.getType());
+ gaussFeatureNotSupportLog(x.getType() + " index" + getTypeAttribute(x));
+ }
+ SQLName name = x.getName();
+ if (name != null) {
+ name.accept(this);
+ } else {
+ logger.error("openGauss needs index name to add index" + getTypeAttribute(x));
+ errHandle(x, "lack of index name");
+ }
+ if (x.getColumns().size() > 0) {
+ if (x.getColumns().size() > 1) {
+ logger.error("openGauss alters table add index on only one column" + getTypeAttribute(x));
+ errHandle(x, "too much Column");
+ }
+ this.print('(');
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ }
+ if (x.getOptions().getIndexType() != null) {
+ printUcaseNotSupportWord("using " + x.getOptions().getIndexType());
+ gaussFeatureNotSupportLog("specifying index type when it adds index" + getTypeAttribute(x));
+ }
+ if (x.getOptions().getComment() != null) {
+ printUcaseNotSupportWord(" COMMENT " + x.getOptions().getComment());
+ gaussFeatureNotSupportLog("specifying comment when it adds index" + getTypeAttribute(x));
+ }
+ if (x.getOptions().getKeyBlockSize() != null) {
+ printUcaseNotSupportWord(" KEY_BLOCK_SIZE = " + x.getOptions().getKeyBlockSize());
+ gaussFeatureNotSupportLog("specifying keyBlockSize when it adds index" + getTypeAttribute(x));
+ }
+ if (x.getOptions().getParserName() != null) {
+ printUcaseNotSupportWord(" WITH PARSER " + x.getOptions().getParserName());
+ gaussFeatureNotSupportLog("specifying parser name when it adds index" + getTypeAttribute(x));
+ }
+ } else {
+ String type = x.getType();
+ boolean typeNotNull = type != null;
+ boolean isPrimary = typeNotNull && type.toLowerCase().equals("primary");
+ if (typeNotNull) {
+ if ((isPrimary) && x.getName() != null && x.hasConstraint()) {
+ printUcase("constraint ");
+ x.getName().accept(this);
+ this.print(' ');
+ }
+ this.print0(this.ucase ? type.toUpperCase() : type.toLowerCase());
+ this.print(' ');
+ }
+ if (x.isKey() && isPrimary) {
+ this.print0(this.ucase ? "KEY " : "key ");
+ }
+ if (x.getName() != null && (type == null || !type.equalsIgnoreCase("primary"))) {
+ printUcaseNotSupportWord(x.getName().toString());
+ gaussFeatureNotSupportLog("specifying index name" + getTypeAttribute(x));
+ }
+ if (x.getColumns().size() > 0) {
+ this.print('(');
+ this.printAndAccept(x.getColumns(), ", ");
+ this.print(')');
+ }
+ if (x.getOptions().getIndexType() != null)
+ printUcaseNotSupportWord("using " + x.getOptions().getIndexType());
+ gaussFeatureNotSupportLog("specifying index type" + getTypeAttribute(x));
+ if (x.getOptions() != null && !x.getOptions().toString().equals(""))
+ gaussFeatureNotSupportLog("specifying index option" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTableOption x) {
+ if (x.getName().toLowerCase().equals("algorithm")) {
+ logger.error("openGauss does not support ALGORITHM when it alters table" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+ this.print0(x.getName());
+ this.print0(" = ");
+ this.print0(x.getValue().toString());
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableAddColumn x) {
+ this.print0(this.ucase ? "ADD " : "add ");
+ if (x.getColumns().size() > 1) {
+ this.print('(');
+ }
+ this.printAndAccept(x.getColumns(), ", ");
+ if (x.getFirstColumn() != null) {
+ gaussFeatureNotSupportLog("first " + getTypeAttribute(x));
+ printUcaseNotSupportWord("first " + x.getFirstColumn());
+ } else if (x.getAfterColumn() != null) {
+ gaussFeatureNotSupportLog("alter" + getTypeAttribute(x));
+ printUcaseNotSupportWord("alter " + x.getAfterColumn());
+ } else if (x.isFirst()) {
+ printUcaseNotSupportWord("first");
+ gaussFeatureNotSupportLog("first" + getTypeAttribute(x));
+ }
+ if (x.getColumns().size() > 1) {
+ this.print(')');
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTableChangeColumn x) {
+ printUcase("drop ");
+ x.getColumnName().accept(this);
+ printUcase(" , add ");
+ x.getNewColumnDefinition().accept(this);
+ if (x.getFirstColumn() != null) {
+ gaussFeatureNotSupportLog("first " + getTypeAttribute(x));
+ printUcaseNotSupportWord("first " + x.getFirstColumn());
+ } else if (x.getAfterColumn() != null) {
+ gaussFeatureNotSupportLog("alter" + getTypeAttribute(x));
+ printUcaseNotSupportWord("alter " + x.getAfterColumn());
+ } else if (x.isFirst()) {
+ printUcaseNotSupportWord("first");
+ gaussFeatureNotSupportLog("first" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTableModifyColumn x) {
+ printUcase("drop ");
+ x.getNewColumnDefinition().getName().accept(this);
+ printUcase(" ,add ");
+ x.getNewColumnDefinition().accept(this);
+ if (x.getFirstColumn() != null) {
+ gaussFeatureNotSupportLog("first " + getTypeAttribute(x));
+ printUcaseNotSupportWord("first " + x.getFirstColumn());
+ } else if (x.getAfterColumn() != null) {
+ gaussFeatureNotSupportLog("alter" + getTypeAttribute(x));
+ printUcaseNotSupportWord("alter " + x.getAfterColumn());
+ } else if (x.isFirst()) {
+ printUcaseNotSupportWord("first");
+ gaussFeatureNotSupportLog("first" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableConvertCharSet x) {
+ logger.error("openGauss does not support converting to character set when it alters table"
+ + getTypeAttribute(x));
+ errHandle(x, "convert to character set");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableEnableKeys x) {
+ logger.error("openGauss does not support enabling keys when it alters table" + getTypeAttribute(x));
+ errHandle(x, "enable keys");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableDisableKeys x) {
+ logger.error("openGauss does not support disabling keys when it alters table" + getTypeAttribute(x));
+ errHandle(x, "disable keys");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTableDiscardTablespace x) {
+ logger.error("openGauss does not support discard tablespace when it alters table" + getTypeAttribute(x));
+ errHandle(x, "discard tablespace");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTableImportTablespace x) {
+ logger.error(
+ "openGauss does not support importing tablespace when it alters table" + getTypeAttribute(x));
+ errHandle(x, "import tablespace");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableDropIndex x) {
+ logger.error("openGauss does not support dropping index when it alters table" + getTypeAttribute(x));
+ errHandle(x, "drop index");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableDropPrimaryKey x) {
+ logger.error(
+ "openGauss does not support dropping primary key when it alters table" + getTypeAttribute(x));
+ errHandle(x, "drop primary key");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableDropForeignKey x) {
+ logger.error(
+ "openGauss does not support dropping foreign key when it alters table" + getTypeAttribute(x));
+ errHandle(x, "drop foreign key");
+ return false;
+ }
+
+ public boolean visit(MySqlAlterTableForce x) {
+ logger.error("openGauss does not support force when it alters table" + getTypeAttribute(x));
+ errHandle(x, "force");
+ return false;
+ }
+
+ public boolean visit(MySqlAlterTableLock x) {
+ logger.error("openGauss does not support lock when it alters table" + getTypeAttribute(x));
+ errHandle(x, "lock");
+ return false;
+ }
+
+ public boolean visit(MySqlAlterTableOrderBy x) {
+ logger.error("openGauss does not support order by when it alters table" + getTypeAttribute(x));
+ errHandle(x, "order by");
+ return false;
+ }
+
+ public boolean visit(MySqlAlterTableValidation x) {
+ logger.error("openGauss does not support validation when it alters table" + getTypeAttribute(x));
+ errHandle(x, "validation");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableAddPartition x) {
+ this.print0(this.ucase ? "ADD " : "add ");
+ if (x.getPartitions().size() > 0) {
+ this.printAndAccept(x.getPartitions(), ", ");
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableDropPartition x) {
+ for (int i = 0; i < x.getPartitions().size(); i++) {
+ this.print0(this.ucase ? "DROP " : "drop ");
+ this.print0(this.ucase ? "PARTITION " : "partition ");
+ x.getPartitions().get(i).accept(this);
+ if (i != x.getPartitions().size() - 1) {
+ print(',');
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableExchangePartition x) {
+ this.print0(this.ucase ? "EXCHANGE PARTITION " : "exchange partition ");
+ this.print('(');
+ this.printAndAccept(x.getPartitions(), ", ");
+ this.print(')');
+ this.print0(this.ucase ? " WITH TABLE " : " with table ");
+ x.getTable().accept(this);
+ Boolean validation = x.getValidation();
+ if (validation != null) {
+ if (validation) {
+ this.print0(this.ucase ? " WITH VALIDATION" : " with validation");
+ } else {
+ this.print0(this.ucase ? " WITHOUT VALIDATION" : " without validation");
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLAlterTableTruncatePartition x) {
+ if (x.getPartitions().size() == 1
+ && "ALL".equalsIgnoreCase(((SQLName) x.getPartitions().get(0)).getSimpleName())) {
+ logger.error("openGauss does not support truncate all partition when it alters table"
+ + getTypeAttribute(x));
+ errHandle(x, "unsupported keyword all");
+ return false;
+ }
+ for (int i = 0; i < x.getPartitions().size(); i++) {
+ printUcase("truncate partition ");
+ x.getPartitions().get(i).accept(this);
+ if (i != x.getPartitions().size() - 1) {
+ print(',');
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterLogFileGroupStatement x) {
+ logger.error("openGauss does not support alter logfile group statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateAddLogFileGroupStatement x) {
+ logger.error("openGauss does not support create logfile group statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropLogFileGroupStatement x) {
+ logger.error("openGauss does not support drop logfile group statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterEventStatement x) {
+ logger.error("openGauss does not support alter event statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateEventStatement x) {
+ logger.error("openGauss does not support alter event statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropEventStatement x) {
+ logger.error("openGauss does not support drop event statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateUserStatement x) {
+ print0(this.ucase ? "CREATE USER " : "create user ");
+ if (x.getUsers().size() > 1)
+ printAndAccept(x.getUsers(), ";CREATE USER ");
+ else
+ printAndAccept(x.getUsers(), " ");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateUserStatement.UserSpecification x) {
+ x.getUser().accept(this);
+ if (x.getAuthPlugin() != null) {
+ println();
+ print("-- ");
+ print0(ucase ? " IDENTIFIED WITH " : " identified with ");
+ x.getAuthPlugin().accept(this);
+ println();
+ gaussFeatureNotSupportLog("auth_plugin when it creates user" + getTypeAttribute(x));
+ }
+ if (x.getPassword() != null) {
+ printUcase(" PASSWORD ");
+ x.getPassword().accept(this);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlUserName x) {
+ String userName = x.getUserName();
+ print0(userName);
+ if (x.getHost() != null) {
+ println();
+ print("-- ");
+ print('@');
+ String host = x.getHost();
+ if (host.length() > 0 && host.charAt(0) == '\'') {
+ print0(host);
+ } else {
+ print('\'');
+ print0(host);
+ print('\'');
+ }
+ println();
+ gaussFeatureNotSupportLog("host_name when it creates user" + getTypeAttribute(x));
+ }
+ // related to ALTER USER
+ String identifiedBy = x.getIdentifiedBy();
+ if (identifiedBy != null) {
+ print0(this.ucase ? " IDENTIFIED BY '" : " identified by '");
+ print0(identifiedBy);
+ print('\'');
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterUserStatement x) {
+ for (int i = 0; i < x.getAlterUsers().size(); i++) {
+ MySqlAlterUserStatement.AlterUser alterUser = x.getAlterUsers().get(i);
+ if (!alterUser.getUser().toString().equals("user()")) {
+ if (i != 0) {
+ print(';');
+ }
+ print0(this.ucase ? "ALTER USER " : "alter user ");
+ alterUser.getUser().accept(this);
+ } else {
+ println();
+ print("-- ");
+ print(ucase?"USER()":"user()");
+ println();
+ gaussFeatureNotSupportLog("user() when it alters user" + getTypeAttribute(x));
+ return false;
+ }
+ if (alterUser.getAuthOption() != null) {
+ print(" IDENTIFIED BY ");
+ SQLCharExpr authString = alterUser.getAuthOption().getAuthString();
+ authString.accept(this);
+ }
+ }
+ MySqlAlterUserStatement.PasswordOption passwordOption = x.getPasswordOption();
+ if (passwordOption != null) {
+ switch (passwordOption.getExpire()) {
+ case PASSWORD_EXPIRE:
+ print0(this.ucase ? " PASSWORD EXPIRE" : " password expire");
+ return false;
+ case PASSWORD_EXPIRE_DEFAULT:
+ println();
+ print("-- ");
+ print0(ucase ? " PASSWORD EXPIRE DEFAULT" : " password expire default");
+ println();
+ gaussFeatureNotSupportLog(
+ "PASSWORD EXPIRE DEFAULT when it alters user" + getTypeAttribute(x));
+ return false;
+ case PASSWORD_EXPIRE_NEVER:
+ println();
+ print("-- ");
+ print0(ucase ? " PASSWORD EXPIRE NEVER" : " password expire never");
+ println();
+ gaussFeatureNotSupportLog("PASSWORD EXPIRE NEVER when it alters user" + getTypeAttribute(x));
+ return false;
+ case PASSWORD_EXPIRE_INTERVAL:
+ println();
+ print("-- ");
+ print0(ucase ? " PASSWORD EXPIRE INTERVAL " : " password expire interval ");
+ passwordOption.getIntervalDays().accept(this);
+ print0(ucase ? " DAY" : " day");
+ println();
+ gaussFeatureNotSupportLog(
+ "PASSWORD_EXPIRE_INTERVAL N DAY when it alters user" + getTypeAttribute(x));
+ return false;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLRenameUserStatement x) {
+ print0(this.ucase ? "ALTER USER " : "alter user ");
+ x.getName().accept(this);
+ print0(this.ucase ? " RENAME TO " : " rename to ");
+ x.getTo().accept(this);
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLRollbackStatement x) {
+ print0(this.ucase ? "ROLLBACK" : "rollback");
+ if (x.getChain() != null)
+ if (x.getChain().booleanValue()) {
+ println();
+ print("-- ");
+ print0(ucase ? " AND CHAIN" : " and chain");
+ println();
+ gaussFeatureNotSupportLog("AND CHAIN when it rollbacks" + getTypeAttribute(x));
+ } else {
+ println();
+ print("-- ");
+ print0(ucase ? " AND NO CHAIN" : " and no chain");
+ println();
+ gaussFeatureNotSupportLog("AND NO CHAIN when it rollbacks" + getTypeAttribute(x));
+ }
+ if (x.getRelease() != null)
+ if (x.getRelease().booleanValue()) {
+ println();
+ print("-- ");
+ print0(this.ucase ? " AND RELEASE" : " and release");
+ println();
+ gaussFeatureNotSupportLog("RELEASE when it rollbacks" + getTypeAttribute(x));
+ } else {
+ println();
+ print("-- ");
+ print0(ucase ? " AND NO RELEASE" : " and no release");
+ println();
+ gaussFeatureNotSupportLog("NO RELEASE when it rollbacks" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLCommitStatement x) {
+ print0(this.ucase ? "COMMIT" : "commit");
+ if (x.isWork())
+ print0(this.ucase ? " WORK" : " work");
+ if (x.getChain() != null)
+ if (x.getChain().booleanValue()) {
+ println();
+ print("-- ");
+ print0(ucase ? " AND CHAIN" : " and chain");
+ println();
+ gaussFeatureNotSupportLog("AND CHAIN when it commits" + getTypeAttribute(x));
+ } else {
+ println();
+ print("-- ");
+ print0(ucase ? " AND NO CHAIN" : " and no chain");
+ println();
+ gaussFeatureNotSupportLog("AND NO CHAIN when it commits" + getTypeAttribute(x));
+ }
+ if (x.getRelease() != null)
+ if (x.getRelease().booleanValue()) {
+ println();
+ print("-- ");
+ print0(this.ucase ? " AND RELEASE" : " and release");
+ println();
+ gaussFeatureNotSupportLog("RELEASE when it commits" + getTypeAttribute(x));
+ } else {
+ println();
+ print("-- ");
+ print0(ucase ? " AND NO RELEASE" : " and no release");
+ println();
+ gaussFeatureNotSupportLog("NO RELEASE when it commits" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLStartTransactionStatement x) {
+ print0(this.ucase ? "START TRANSACTION" : "start transaction");
+ if (x.isConsistentSnapshot()) {
+ println();
+ print("-- ");
+ print0(ucase ? " WITH CONSISTENT SNAPSHOT" : " with consistent snapshot");
+ println();
+ gaussFeatureNotSupportLog(
+ "WITH CONSISTENT SNAPSHOT when it starts transaction" + getTypeAttribute(x));
+ }
+ if (x.isReadOnly())
+ print0(this.ucase ? " READ ONLY" : " read only");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlSetTransactionStatement x) {
+ print0(this.ucase ? "SET " : "set ");
+ if (x.getGlobal() != null && x.getGlobal().booleanValue()) {
+ println();
+ print("-- ");
+ print0(ucase ? "GLOBAL " : "global ");
+ println();
+ gaussFeatureNotSupportLog("GLOBAL when it sets transaction" + getTypeAttribute(x));
+ }
+ if (x.getSession() != null && x.getSession().booleanValue()) {
+ printUcase("SET SESSION CHARACTERISTICS AS TRANSACTION");
+ } else
+ printUcase("LOCAL TRANSACTION ");
+ if (x.getIsolationLevel() != null) {
+ print0(this.ucase ? "ISOLATION LEVEL " : "isolation level ");
+ if ("read uncommitted".equalsIgnoreCase(x.getIsolationLevel())) {
+ println();
+ print("-- ");
+ print0(ucase ? "READ UNCOMMITTED " : "read committed ");
+ println();
+ gaussFeatureNotSupportLog("READ UNCOMMITTED when it sets transaction" + getTypeAttribute(x));
+ }
+ else
+ print0(x.getIsolationLevel());
+ }
+ String accessModel = x.getAccessModel();
+ if (accessModel != null) {
+ print0(this.ucase ? "READ " : "read ");
+ print0(accessModel);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLPurgeLogsStatement x) {
+ logger.error("openGauss does not support purge binary log statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCursorDeclareStatement x) {
+ printUcase("cursor ");
+ printExpr((SQLExpr) x.getCursorName(), this.parameterized);
+ this.indentCount++;
+ println();
+ x.getSelect().accept(this);
+ this.indentCount--;
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLFetchStatement x) {
+ logger.error("the cursor fetch statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x, "FETCH");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLOpenStatement x) {
+ logger.error("openGauss does not support cursor open statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlDeclareConditionStatement x) {
+ logger.error("openGauss does not support declare ... condition Statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlDeclareHandlerStatement x) {
+ logger.error("openGauss does not support declare ... handler statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCheckTableStatement x) {
+ logger.error("openGauss does not support check table statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlChecksumTableStatement x) {
+ logger.error("openGauss does not support checksum table statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlOptimizeStatement x) {
+ logger.error("openGauss does not support optimize table statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateServerStatement x) {
+ logger.error("the create server statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterServerStatement x) {
+ logger.error("the alter server statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlBinlogStatement x) {
+ logger.error("openGauss does not support binlog statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlFlushStatement x) {
+ logger.error("openGauss does not support flush statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlKillStatement x) {
+ logger.error("openGauss does not support kill statement" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlResetStatement x) {
+ logger.error("the reset statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlCreateTableSpaceStatement x) {
+ logger.error("the create tablespace statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x,"createTableSpace");
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlAlterTablespaceStatement x){
+ logger.error("the alter tablespace statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x,"alterTableSpace");
+ return false;
+ }
+
+ @Override
+ public boolean visit(SQLDropTableSpaceStatement x) {
+ this.print0(this.ucase ? "DROP TABLESPACE " : "drop tablespace ");
+ if (x.isIfExists()) {
+ this.print0(this.ucase ? "IF EXISTS " : "if exists ");
+ }
+ x.getName().accept(this);
+ SQLExpr engine = x.getEngine();
+ if (engine != null) {
+ printUcaseNotSupportWord("engine " + engine);
+ gaussFeatureNotSupportLog("specifying engine" + getTypeAttribute(x));
+ }
+ return false;
+ }
+
+ //1->schema 2->table 3->function 4->procedure
+ private static final ThreadLocal threadLocalForResourceState = new ThreadLocal();
+ @Override
+ public boolean visit(SQLGrantStatement x){
+ List rawPrivileges = x.getPrivileges();
+ try {
+ List commonSchemaPrivilegeList=Collections.emptyList();
+ List executePrivilegeList=Collections.emptyList();
+ List tablePrivilegeList=Collections.emptyList();
+ List unsupportedPrivilegeList = Collections.emptyList();
+ // db_name.* , Consider case by case
+ SQLObject resource = x.getResource();
+ if(resource instanceof SQLPropertyExpr){
+ logger.error("\"db_name.routine_name\" privilege level in grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x,"single routine");
+ return false;
+ }
+ SQLExpr expr = ((SQLExprTableSource) resource).getExpr();
+ if(expr instanceof SQLPropertyExpr) {
+ SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
+ SQLExpr owner = propertyExpr.getOwner();
+ if (owner instanceof SQLIdentifierExpr
+ &&propertyExpr.getName().trim().equals("*")) {
+ List privileges = x.getPrivileges();
+ // db_name.*->on Schema schema_name syntax
+ commonSchemaPrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return commonSchemaPrivilegeSet.contains(privilegeName)&&!privilegeName.equals("EXECUTE");
+ })
+ .collect(Collectors.toList());
+ // db_name.*->all tables in schema schema_name syntax
+ tablePrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return tablePrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ // db_name.*->all function
+ // db_name.*->all procedure
+ executePrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return routinePrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ unsupportedPrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return !commonSchemaPrivilegeSet.contains(privilegeName)&&!tablePrivilegeSet.contains(privilegeName)&&!routinePrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ }
+ }
+ if(!commonSchemaPrivilegeList.isEmpty()||!tablePrivilegeList.isEmpty()||!executePrivilegeList.isEmpty()||!unsupportedPrivilegeList.isEmpty()){
+ Field privilegeField = x.getClass().getSuperclass().getDeclaredField("privileges");
+ privilegeField.setAccessible(true);
+ if(!commonSchemaPrivilegeList.isEmpty()) {
+ privilegeField.set(x, commonSchemaPrivilegeList);
+ threadLocalForResourceState.set(1);
+ visitGrant(x);
+ if(!tablePrivilegeList.isEmpty()||!executePrivilegeList.isEmpty()) {
+ println(";");
+ }
+ }
+ if(!tablePrivilegeList.isEmpty()){
+ privilegeField.set(x,tablePrivilegeList);
+ threadLocalForResourceState.set(2);
+ visitGrant(x);
+ if(!executePrivilegeList.isEmpty()){
+ println(";");
+ }
+ }
+ if(!executePrivilegeList.isEmpty()) {
+ privilegeField.set(x, executePrivilegeList);
+ //make use of threadlocal flag: visit twice,all function and all procedure
+ threadLocalForResourceState.set(3);
+ visitGrant(x);
+ println(";");
+ threadLocalForResourceState.set(4);
+ //postVisit will add the semicolon
+ visitGrant(x);
+ }
+ if(!unsupportedPrivilegeList.isEmpty()){
+ //not supported
+ threadLocalForResourceState.set(5);
+ privilegeField.set(x, unsupportedPrivilegeList);
+ visitGrant(x);
+ }
+ }else{
+ visitGrant(x);
+ }
+ } catch (NoSuchFieldException | IllegalAccessException ignore) {
+ } finally {
+ threadLocalForResourceState.remove();
+ try {
+ Field privileges = x.getClass().getSuperclass().getDeclaredField("privileges");
+ privileges.set(x,rawPrivileges);
+ privileges.setAccessible(false);
+ } catch (NoSuchFieldException | IllegalAccessException ignore) {
+ }
+ }
+ return false;
+ }
+
+ private void visitGrant(SQLGrantStatement x){
+ print0(ucase ? "GRANT " : "grant ");
+ printAndAccept(x.getPrivileges(), ", ");
+ printGrantOn(x);
+ if (x.getUsers() != null) {
+ print0(ucase ? " TO " : " to ");
+ printAndAccept(x.getUsers(), ",");
+ }
+ if (x.getWithGrantOption()) {
+ print0(ucase ? " WITH GRANT OPTION" : " with grant option");
+ }
+ if(x.getMaxConnectionsPerHour()!=null ||
+ x.getMaxQueriesPerHour()!=null||
+ x.getMaxUpdatesPerHour()!=null||
+ x.getMaxUserConnections()!=null){
+ println();
+ print("-- ");
+ }
+ boolean with = false;
+ SQLExpr maxQueriesPerHour = x.getMaxQueriesPerHour();
+ if (maxQueriesPerHour != null) {
+ if (!with) {
+ print0(ucase ? " WITH" : " with");
+ with = true;
+ }
+ print0(ucase ? " MAX_QUERIES_PER_HOUR " : " max_queries_per_hour ");
+ maxQueriesPerHour.accept(this);
+ logger.warn("the maxQueriesPerHour property of grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ }
+ SQLExpr maxUpdatesPerHour = x.getMaxUpdatesPerHour();
+ if (maxUpdatesPerHour != null) {
+ if (!with) {
+ print0(ucase ? " WITH" : " with");
+ with = true;
+ }
+ print0(ucase ? " MAX_UPDATES_PER_HOUR " : " max_updates_per_hour ");
+ maxUpdatesPerHour.accept(this);
+ logger.warn("the maxQueriesPerHour property of grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ }
+ SQLExpr maxConnectionsPerHour = x.getMaxConnectionsPerHour();
+ if (maxConnectionsPerHour != null) {
+ if (!with) {
+ print0(ucase ? " WITH" : " with");
+ with = true;
+ }
+ print0(ucase ? " MAX_CONNECTIONS_PER_HOUR " : " max_connections_per_hour ");
+ maxConnectionsPerHour.accept(this);
+ logger.warn("the maxQueriesPerHour property of grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ }
+ SQLExpr maxUserConnections = x.getMaxUserConnections();
+ if (maxUserConnections != null) {
+ if (!with) {
+ print0(ucase ? " WITH" : " with");
+ with = true;
+ }
+ print0(ucase ? " MAX_USER_CONNECTIONS " : " max_user_connections ");
+ logger.warn("the maxQueriesPerHour property of grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ }
+ if (x.getIdentifiedBy() != null) {
+ logger.error("the 'identified by' in grant is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ }
+
+ @Override
+ public boolean visit(SQLPrivilegeItem x) {
+ SQLExpr action = x.getAction();
+ String name = ((SQLIdentifierExpr) action).getName().toUpperCase().trim();
+ if(incompatiblePrivilegeSet.contains(name)){
+ logger.error(
+ String.format("Privilege %s is incompatible with OpenGauss", name) + getTypeAttribute(x));
+ errHandle(x,"incompatible privilege");
+ }
+ printExpr(action);
+ if(!x.getColumns().isEmpty()) {
+ print0("(");
+ printAndAccept(x.getColumns(), ", ");
+ print0(")");
+ }
+ return false;
+ }
+
+ @Override
+ public void printGrantOn(SQLGrantStatement x) {
+ if (x.getResource() != null) {
+ print0(ucase ? " ON " : " on ");
+ SQLObjectType resourceType = x.getResourceType();
+ if (resourceType != null) {
+ print0(ucase ? resourceType.name : resourceType.name_lcase);
+ print(' ');
+ }
+ SQLObject resource = x.getResource();
+ SQLExpr expr = ((SQLExprTableSource) resource).getExpr();
+ if (expr instanceof SQLPropertyExpr) {
+ SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
+ SQLExpr owner = propertyExpr.getOwner();
+ if (owner instanceof SQLAllColumnExpr && propertyExpr.getName().equals("*")) {
+ //*.*
+ logger.error(
+ "privilege level *.* in grant is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x,"*.*");
+ } else {
+ if(propertyExpr.getName().equals("*")) {
+ //db_name.*
+ SQLIdentifierExpr identOwner = (SQLIdentifierExpr) owner;
+ List privileges = x.getPrivileges();
+ String firstPrivilege = ((SQLIdentifierExpr) privileges.get(0).getAction()).getName().toUpperCase().trim();
+ switch (threadLocalForResourceState.get()!=null?
+ threadLocalForResourceState.get():Integer.MAX_VALUE) {
+ case 1:
+ printUcase("SCHEMA ");
+ break;
+ case 2:
+ printUcase("ALL TABLES IN SCHEMA ");
+ break;
+ case 3:
+ printUcase("ALL FUNCTIONS IN SCHEMA ");
+ break;
+ case 4:
+ printUcase("ALL PROCEDURE IN SCHEMA ");
+ break;
+ case 5:
+ break;
+ default:
+ {
+ logger.error("unkown threadLocalForResourceState" + getTypeAttribute(x));
+ errHandle(x);
+ }
+ }
+ printName0(identOwner.getName());
+ }else{
+ if(resourceType==null
+ ||resourceType.name.toUpperCase().trim().equals("TABLE")){
+ //db_name.tbl_name
+ List privileges = x.getPrivileges();
+ Set privilegeSet = privileges
+ .stream()
+ .map(e -> ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim())
+ .collect(Collectors.toSet());
+ if(privileges.contains("USAGE")||privileges.contains("CREATE")){
+ // when usage and create appear with db_name.tb_name,they cannot be translated into opengauss syntax
+ logger.error(
+ "\"Usage\" and \"create\" with privilege level \"db_name.*\" in grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x,"incompatible privilege");
+ }
+ // db_name.routine_name
+ if(resourceType!=null&&resourceType.name.toUpperCase().trim().equals("TABLE")){
+ logger.error("grant single function or procedure is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x,"single routine");
+ }
+ printName0(propertyExpr.getName());
+ }else{
+ //db_name.routine_name
+ logger.error(
+ "\"db_name.routine_name\" privilege level in grant is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x,"single routine");
+ }
+ }
+ }
+ } else if(expr instanceof SQLAllColumnExpr){
+ // *
+ logger.error("privilege level * in grant is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x,"*");
+ }else{
+ // table_name
+ expr.accept(this);
+ }
+ }
+ }
+
+ @Override
+ public boolean visit(SQLRevokeStatement x) {
+ List rawPrivileges = x.getPrivileges();
+ try {
+ List SchemaPrivilegeList=Collections.emptyList();
+ List routinePrivilegeList=Collections.emptyList();
+ List tablePrivilegeList=Collections.emptyList();
+ // db_name.* consider case by case
+ SQLObject resource = x.getResource();
+ if(resource == null) {
+ visitRevoke(x);
+ return false;
+ }
+ if(resource instanceof SQLPropertyExpr){
+ logger.error("\"db_name.routine_name\" privilege level in revoke is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x,"single rountine");
+ return false;
+ }
+ SQLExpr expr = ((SQLExprTableSource) resource).getExpr();
+ if(expr instanceof SQLPropertyExpr) {
+ SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr;
+ SQLExpr owner = propertyExpr.getOwner();
+ if (owner instanceof SQLIdentifierExpr
+ &&propertyExpr.getName().trim().equals("*")) {
+ List privileges = x.getPrivileges();
+ // db_name.*->on Schema schema_name syntax
+ SchemaPrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return commonSchemaPrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ // db_name.*->all tables in schema schema_name syntax
+ tablePrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return tablePrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ // db_name.*->all function
+ // db_name.*->all procedure
+ routinePrivilegeList = privileges
+ .stream()
+ .filter(e -> {
+ String privilegeName = ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim();
+ return routinePrivilegeSet.contains(privilegeName);
+ })
+ .collect(Collectors.toList());
+ }
+ }
+ if(!SchemaPrivilegeList.isEmpty()||! routinePrivilegeList.isEmpty()||!tablePrivilegeList.isEmpty()){
+ Field privilegeField = x.getClass().getSuperclass().getDeclaredField("privileges");
+ privilegeField.setAccessible(true);
+ if(!SchemaPrivilegeList.isEmpty()) {
+ privilegeField.set(x, SchemaPrivilegeList);
+ threadLocalForResourceState.set(1);
+ visitRevoke(x);
+ if(! routinePrivilegeList.isEmpty() || !tablePrivilegeList.isEmpty()) {
+ println(";");
+ }
+ }
+ if(! routinePrivilegeList.isEmpty()) {
+ privilegeField.set(x, routinePrivilegeList);
+ threadLocalForResourceState.set(3);
+ // access twice using threadlocal flag, all function and all procedure
+ visitRevoke(x);
+ println(";");
+ // postVisit add semicolon
+ threadLocalForResourceState.set(4);
+ visitRevoke(x);
+ if(!tablePrivilegeList.isEmpty()){
+ println(";");
+ }
+ }
+ if(!tablePrivilegeList.isEmpty()){
+ privilegeField.set(x, tablePrivilegeList);
+ threadLocalForResourceState.set(2);
+ visitRevoke(x);
+ }
+ }else{
+ visitRevoke(x);
+ }
+ } catch (NoSuchFieldException | IllegalAccessException ignore) {
+ } finally {
+ try {
+ Field privileges = x.getClass().getSuperclass().getDeclaredField("privileges");
+ privileges.set(x,rawPrivileges);
+ privileges.setAccessible(false);
+ } catch (NoSuchFieldException | IllegalAccessException ignore) {
+ }
+ }
+ return false;
+ }
+
+ private void visitRevoke(SQLRevokeStatement x){
+ this.print0(this.ucase ? "REVOKE " : "revoke ");
+ if(x.getResource() != null){
+ for (int i = 0; i privileges = x.getPrivileges();
+ Set privilegeSet = privileges
+ .stream()
+ .map(e -> ((SQLIdentifierExpr) e.getAction()).getName().toUpperCase().trim())
+ .collect(Collectors.toSet());
+ if (privilegeSet.contains("USAGE") || privilegeSet.contains("CREATE")) {
+ // usage, create cannot be converted to opengauss syntax when db_name.tb_name
+ logger.error(
+ "\"Usage\" and \"create\" with privilege level \"db_name.*\" in revoke is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ // db_name.routine_name
+ if (resourceType != null && resourceType.name.toUpperCase().trim().equals("TABLE")) {
+ logger.error("revoke single function or procedure is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ printName0(propertyExpr.getName());
+ } else {
+ //db_name.routine_name
+ logger.error(
+ "\"db_name.routine_name\" privilege level in revoke is incompatible with openGauss"
+ + getTypeAttribute(x));
+ errHandle(x);
+ }
+ }
+
+ }
+ } else if (expr instanceof SQLAllColumnExpr) {
+ // *
+ logger.error("privilege level * in revoke is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ } else {
+ // table_name
+ expr.accept(this);
+ }
+ }
+ }
+
+ @Override
+ public boolean visit(MySqlPrepareStatement x) {
+ logger.error("the prepare statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+
+ @Override
+ public boolean visit(MySqlExecuteStatement x) {
+ logger.error("the execute statement is incompatible with openGauss" + getTypeAttribute(x));
+ errHandle(x);
+ return false;
+ }
+}
diff --git a/src/main/java/org/opengauss/sqltranslator/dialect/mysql/util/OpenGaussDataTypeTransformUtil.java b/src/main/java/org/opengauss/sqltranslator/dialect/mysql/util/OpenGaussDataTypeTransformUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..42919212e00807bf17616ca9cf3bd83dcc60ff9c
--- /dev/null
+++ b/src/main/java/org/opengauss/sqltranslator/dialect/mysql/util/OpenGaussDataTypeTransformUtil.java
@@ -0,0 +1,115 @@
+package org.opengauss.sqltranslator.dialect.mysql.util;
+
+import com.alibaba.druid.sql.SQLTransformUtils;
+import com.alibaba.druid.sql.ast.*;
+import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
+import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
+import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
+import com.alibaba.druid.util.FnvHash.Constants;
+import org.apache.commons.math3.util.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class OpenGaussDataTypeTransformUtil extends SQLTransformUtils {
+ private static final Logger logger= LoggerFactory.getLogger(OpenGaussDataTypeTransformUtil.class);
+ enum T {
+ NEW,CLONE, NONSUPPORT;
+ }
+ private static final Map> typeMap = new HashMap>(){
+ {
+ put("TINYINT",new Pair(T.NEW,"SMALLINT"));
+ put("MEDIUMINT",new Pair(T.NEW,"INTEGER"));
+ put("SMALLINT",new Pair(T.NEW,"SMALLINT"));
+ put("INT",new Pair(T.NEW,"INTEGER"));
+ put("BIGINT",new Pair(T.NEW,"BIGINT"));
+ put("INTEGER",new Pair(T.NEW,"INTEGER"));
+ put("YEAR",new Pair(T.CLONE,"INTEGER"));
+ put("DECIMAL",new Pair(T.CLONE,"DECIMAL"));
+ put("FLOAT",new Pair(T.CLONE,"FLOAT"));
+ put("REAL",new Pair(T.CLONE,"REAL"));
+ put("DOUBLE",new Pair(T.NEW,"DOUBLE PRECISION"));
+ put("DATETIME",new Pair(T.CLONE,"TIMESTAMP"));
+ put("TINYTEXT",new Pair(T.NEW,"TEXT"));
+ put("MEDIUMTEXT",new Pair(T.NEW,"TEXT"));
+ put("LONGTEXT",new Pair(T.NEW,"TEXT"));
+ put("TEXT",new Pair(T.NEW,"TEXT"));
+ put("BINARY",new Pair(T.NEW,"BYTEA"));
+ put("VARBINARY",new Pair(T.NEW,"BYTEA"));
+ put("MULTIPOINT",new Pair(T.NEW,"BYTEA"));
+ put("GEOMETRYCOLLECTION",new Pair(T.NEW,"BYTEA"));
+ put("MULTILINESTRING",new Pair(T.NEW,"BYTEA"));
+ put("MULTIPOLYGON",new Pair(T.NEW,"BYTEA"));
+ put("TINYBLOB",new Pair(T.NEW,"BLOB"));
+ put("BLOB",new Pair(T.NEW,"BLOB"));
+ put("LONGBLOB",new Pair(T.NEW,"BLOB"));
+ put("MEDIUMBLOB",new Pair(T.NEW,"BLOB"));
+ put("BIT",new Pair(T.CLONE,"INTEGER"));
+ put("BOOLEAN",new Pair(T.NEW,"BOOLEAN"));
+ put("BOOL",new Pair(T.NEW,"BOOLEAN"));
+ put("GEOMETRY",new Pair(T.NEW,"POINT"));
+ put("LINESTRING",new Pair(T.NEW,"PATH"));
+ put("VARCHAR",new Pair(T.CLONE,"VARCHAR"));
+ put("CHAR",new Pair(T.CLONE,"CHAR"));
+ put("TIME",new Pair(T.CLONE,"TIME"));
+ put("DATE",new Pair(T.NEW,"DATE"));
+ put("TIMESTAMP",new Pair(T.CLONE,"TIMESTAMP"));
+ put("POINT",new Pair(T.NEW,"POINT"));
+ put("POLYGON",new Pair(T.NEW,"POLYGON"));
+ put("JSON",new Pair(T.NEW,"JSON"));
+ put("ENUM",new Pair(T.NONSUPPORT,""));
+ put("SET",new Pair(T.NONSUPPORT,""));
+ }
+ };
+
+ public static SQLDataType transformOpenGaussToMysql(SQLDataType type) {
+ String uName = type.getName().toUpperCase();
+ long nameHash = type.nameHashCode64();
+ List arguments = type.getArguments();
+ SQLDataType dataType;
+ SQLExpr arg0;
+ int precision = -1;
+ SQLObject parent = type.getParent();
+ boolean isAutoIncrement = parent instanceof SQLColumnDefinition && ((SQLColumnDefinition) parent).isAutoIncrement();
+ if(typeMap.containsKey(uName)) {
+ if ((type.isInt() || uName.equals("MEDIUMINT")) && isAutoIncrement) {
+ dataType = new SQLDataTypeImpl("BIGSERIAL");
+ }
+ else if(isFloatPoint(nameHash) && arguments.size() > 0){
+ arg0 = arguments.get(0);
+ precision = ((SQLIntegerExpr)arg0).getNumber().intValue();
+ dataType = new SQLCharacterDataType("FLOAT", precision);
+ }
+ else{
+ Pair p = typeMap.get(uName);
+ if(p.getKey() == T.NEW){
+ dataType = new SQLDataTypeImpl(p.getValue());
+ } else if(p.getKey() == T.CLONE){
+ dataType = type.clone(); //Clone is to retain the content of parentheses
+ dataType.setName(p.getValue());
+ }else {
+ logger.error("NOT SUPPORT TYPE " + type.getName());
+ dataType = type.clone();
+ }
+ }
+ if (isAutoIncrement && isFloatPoint(nameHash)) {
+ logger.warn("openGauss only support int autoincrement");
+ }
+ }
+ else{
+ logger.error("UNKNOWN TYPE:"+uName);
+ dataType = type.clone();
+ }
+ dataType.setParent(type.getParent());
+ return dataType;
+
+ }
+
+ private static boolean isFloatPoint(long nameHash){
+ return nameHash == Constants.FLOAT || nameHash == Constants.DOUBLE || nameHash == Constants.DOUBLE_PRECISION ||
+ nameHash == Constants.REAL;
+ }
+}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de264ace3bd3dc3c50e100549788907a557babdb
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ System.err
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{100} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/org/opengauss/sqltranslator/SqlTranslateTest.java b/src/test/java/org/opengauss/sqltranslator/SqlTranslateTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5fe126f7428c2adef7eab72db2490cfc9c50b094
--- /dev/null
+++ b/src/test/java/org/opengauss/sqltranslator/SqlTranslateTest.java
@@ -0,0 +1,238 @@
+package org.opengauss.sqltranslator;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class SqlTranslateTest {
+
+ final static String inputDir = "/dialect/mysql/input/";
+ final static String expectDir = "/dialect/mysql/expect/";
+
+ /**
+ * @param fileName File name
+ * @return input, expect, translared SQL content
+ * @throws IOException
+ */
+ private String[] execFile(String fileName) throws IOException {
+ // URL of input file
+ URL inputFileURL = Objects.requireNonNull(this.getClass().getResource(inputDir + fileName));
+ // URL of expect file, which can not exist
+ URL expectFileURL = this.getClass().getResource(expectDir + fileName);
+
+ // input SQL content
+ String inputSQLContent = IOUtils.toString(inputFileURL, StandardCharsets.UTF_8);
+
+ // delete annotate
+ inputSQLContent = inputSQLContent.replaceAll("--.*", "");
+ inputSQLContent = inputSQLContent.replaceAll("#.*", "");
+
+ // expect SQL content. null if expect file does not exist.
+ String expectSQLContent = expectFileURL == null ? "" : IOUtils.toString(expectFileURL, StandardCharsets.UTF_8);
+ // translated SQL content
+ String tranSQLContent = ExecuteTranslate.translateMysql2openGauss(inputSQLContent, false);
+ // String tranSQLContent = exectranslate(inputSQLContent);
+
+ expectSQLContent = expectSQLContent.trim().replaceAll("[ \t\r]+\n", "\n");
+ tranSQLContent = tranSQLContent.trim().replaceAll("[ \t\r]+\n", "\n");
+
+ return new String[] { inputSQLContent, expectSQLContent, tranSQLContent };
+ }
+
+ private void execFileDebug(String fileName) throws IOException {
+ // URL of input file
+ URL inputFileURL = Objects.requireNonNull(this.getClass().getResource(inputDir + fileName));
+
+ // content of input file
+ String inputSQLContent = IOUtils.toString(inputFileURL, StandardCharsets.UTF_8);
+
+ // delete annotate
+ inputSQLContent = inputSQLContent.replaceAll("--.*", "");
+ inputSQLContent = inputSQLContent.replaceAll("#.*", "");
+ // translated SQL content
+ ExecuteTranslate.translateMysql2openGauss(inputSQLContent, true);
+ }
+
+ @Test
+ public void test_if() throws IOException {
+ String[] sqlContents = execFile("if_statement.sql");
+ // output to screen
+ System.out.println(sqlContents[2]);
+ }
+
+ @Test
+ public void test_while() throws IOException {
+ String[] sqlContents = execFile("while_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_repeat() throws IOException {
+ String[] sqlContents = execFile("repeat_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_compound_statement() throws IOException {
+ String[] sqlContents = execFile("compound_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_alterTable() throws IOException {
+ String[] sqlContents = execFile("alterTable_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createDatabase() throws IOException {
+ String[] sqlContents = execFile("createDatabase_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createFunction() throws IOException {
+ String[] sqlContents = execFile("createFunction_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createTrigger() throws IOException {
+ String[] sqlContents = execFile("createTrigger_statement.sql");
+ System.out.println(sqlContents[2]);
+ // assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_dataType() throws IOException {
+ String[] sqlContents = execFile("dataType_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_delete() throws IOException {
+ String[] sqlContents = execFile("delete_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_limit() throws IOException {
+ String[] sqlContents = execFile("limit_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ /**
+ * test select statements
+ */
+ @Test
+ public void test_selectQuery() throws IOException {
+ String[] sqlContents = execFile("select_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+
+ sqlContents = execFile("select_query_statement_01.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+
+ sqlContents = execFile("select_query_statement_02.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+
+ sqlContents = execFile("select_query_statement_03.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+
+ sqlContents = execFile("select_query_statement_04.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_update() throws IOException {
+ String[] sqlContents = execFile("update_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ /**
+ * test create view statements
+ */
+ @Test
+ public void test_createView() throws IOException {
+ String[] sqlContents = execFile("createView_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createServer() throws IOException {
+ String[] sqlContents = execFile("createServer_statement.sql");
+ System.out.println(sqlContents[2]);
+ }
+
+ // druid will failed when alter server content over one parameter
+ @Test
+ public void test_alterServer() throws IOException {
+ String[] sqlContents = execFile("alterServer_statement.sql");
+ System.out.println(sqlContents[2]);
+ }
+
+ @Test
+ public void test_dropServer() throws IOException {
+ String[] sqlContents = execFile("dropServer_statement.sql");
+ System.out.println(sqlContents[2]);
+ }
+
+ @Test
+ public void test_createProcedure() throws IOException {
+ String[] sqlContents = execFile("createProcedure_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createTable() throws IOException {
+ String[] sqlContents = execFile("createTable_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_dropTable() throws IOException {
+ String[] sqlContents = execFile("dropTable_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_createIndex() throws IOException {
+ String[] sqlContents = execFile("createIndex_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_dropIndex() throws IOException {
+ String[] sqlContents = execFile("dropIndex_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_ColumnDefinition() throws IOException {
+ String[] sqlContents = execFile("columnDefinition_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_TableSpace() throws IOException {
+ String[] sqlContents = execFile("tableSpace_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_grant() throws IOException {
+ String[] sqlContents = execFile("grant_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+
+ @Test
+ public void test_revoke() throws IOException {
+ String[] sqlContents = execFile("revoke_statement.sql");
+ assertEquals(sqlContents[1], sqlContents[2]);
+ }
+}
diff --git a/src/test/resources/dialect/mysql/expect/alterTable_statement.sql b/src/test/resources/dialect/mysql/expect/alterTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..96d520d3e1166059ea127e13ad1f8d0f6a3f3037
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/alterTable_statement.sql
@@ -0,0 +1,72 @@
+ALTER TABLE testAlterTable1
+ ADD col0 DECIMAL(4, 2)
+-- FIRST
+;
+ALTER TABLE testAlterTable2
+ ADD (col4 DECIMAL(4, 2), col5 FLOAT);
+-- lack of index name
+-- too much Column
+ALTER TABLE testAlterTable5
+ ADD INDEX
+-- FULLTEXT
+i4(col4);
+ALTER TABLE testAlterTable6
+ ADD CONSTRAINT pk_index PRIMARY KEY (col1)
+-- USING BTREE
+;
+ALTER TABLE testAlterTable7
+ ADD UNIQUE (col2);
+ALTER TABLE testAlterTable8
+ ADD CONSTRAINT fk_pid2 FOREIGN KEY (col5) REFERENCES parent (id) MATCH SIMPLE ON DELETE CASCADE;
+-- err
+ALTER TABLE testAlterTable10
+ ALTER COLUMN col5 SET DEFAULT 4;
+ALTER TABLE testAlterTable11
+ DROP col5 , ADD col6 INTEGER NOT NULL
+-- FIRST
+;
+ALTER TABLE testAlterTable12
+ DROP col6 ,ADD col6 INTEGER NULL DEFAULT 0;
+-- CHARACTER SET
+-- convert to character set
+-- enable keys
+-- disable keys
+-- discard tablespace
+-- import tablespace
+-- drop index
+-- drop primary key
+-- drop foreign key
+-- force
+ALTER TABLE testAlterTable RENAME TO testAlterTable2;
+ALTER TABLE testAlterTable23
+ DROP col5 ,ADD col5 INTEGER NULL,
+ DROP col3 ,ADD col3 INTEGER NULL;
+ALTER TABLE testAlterTable23 RENAME TO testAlterTable2;
+ALTER TABLE testAlterTable2
+ DROP col2 ,ADD col2 DOUBLE PRECISION;
+ALTER TABLE testAlterTable24 RENAME TO testAlterTable;
+ALTER TABLE testAlterTable
+ DROP col2 ,ADD col2 INTEGER;
+-- AUTO_INCREMENT
+ALTER TABLE testAlterTable26
+ SET TABLESPACE ts1
+-- STORAGE DISK
+;
+ALTER TABLE t27
+ ADD PARTITION p3 VALUES LESS THAN (2002);
+ALTER TABLE t28
+ ADD PARTITION p3 VALUES (7, 8, 9);
+ALTER TABLE t29
+ DROP PARTITION p2,DROP PARTITION p3;
+-- unknown partition keyword
+-- unknown partition keyword
+ALTER TABLE testAlterTableHash32
+ TRUNCATE PARTITION p1,TRUNCATE PARTITION p2;
+-- unsupported keyword all
+-- unknown partition keyword
+-- unknown partition keyword
+ALTER TABLE e
+ EXCHANGE PARTITION (p0) WITH TABLE e2;
+-- unsupported removing partition
+-- unsupported upgrading partition
+-- partition by
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/columnDefinition_statement.sql b/src/test/resources/dialect/mysql/expect/columnDefinition_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f64f9318921775234a0769bec9eacb3743538dbe
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/columnDefinition_statement.sql
@@ -0,0 +1,54 @@
+CREATE TABLE test1 (
+ id BIGSERIAL PRIMARY KEY,
+ name CHAR(2) NOT NULL UNIQUE DEFAULT 'GA'
+-- COMMENT 'char'
+-- COLUMN_FORMAT fixed
+-- STORAGE DISK
+
+);
+CREATE TABLE testIndexKey (
+ id INTEGER,
+ name CHAR(2)
+-- INDEX idIndex USING BTREE()
+
+-- KEY nameIndex USING HASH (name)
+
+);
+CREATE TABLE testIndexKey (
+ id INTEGER,
+
+-- INDEX idIndex USING BTREE()
+name CHAR(2)
+-- KEY nameIndex USING HASH (name)
+
+);
+CREATE TABLE testPrimaryUniqueKey (
+ id INTEGER,
+ name CHAR(2),
+ parent_id INTEGER,
+ CONSTRAINT pk_id PRIMARY KEY (id)
+-- USING BTREE
+,
+ col3 INTEGER,
+ UNIQUE
+-- UNIQUE_CONSTRAINT
+(name),
+ col4 INTEGER,
+ CONSTRAINT fk_pid FOREIGN KEY (parent_id) REFERENCES parent (id) MATCH SIMPLE ON DELETE CASCADE,
+ col5 INTEGER,
+ CONSTRAINT ck_con CHECK (id > 0)
+-- NOT ENFORCED
+
+);
+CREATE TABLE testIndexKey (
+ id INTEGER,
+ name CHAR(2),
+ t TEXT,
+
+-- INDEX id_index USING btree()
+
+-- KEY name_key USING hash (name)
+col4 INTEGER
+-- FULLTEXT INDEX test_index()
+
+);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/compound_statement.sql b/src/test/resources/dialect/mysql/expect/compound_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..7d36a18e16b646784531d7178cbb442753dd1cb5
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/compound_statement.sql
@@ -0,0 +1 @@
+-- FETCH
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createDatabase_statement.sql b/src/test/resources/dialect/mysql/expect/createDatabase_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c75a07ce5f7235da3829fe2b2a68fb94957adfbb
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createDatabase_statement.sql
@@ -0,0 +1,4 @@
+CREATE SCHEMA test_db_char
+-- utf8
+-- utf8_chinese_ci
+;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createFunction_statement.sql b/src/test/resources/dialect/mysql/expect/createFunction_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a9e551c93254f8f6682fc506e531deba959ec9a3
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createFunction_statement.sql
@@ -0,0 +1,39 @@
+CREATE
+-- DEFINER 'root'@'%'
+FUNCTION doIterate(
+ p INTEGER,
+ q INTEGER
+ )
+ RETURNS INTEGER IMMUTABLE
+ AS $$
+ DECLARE x INTEGER DEFAULT 5;
+ BEGIN
+ <>LOOP
+ p := p - 1;
+ INSERT
+ INTO testFunction
+ VALUES (DEFAULT, concat('a', p));
+ IF p < 10 THEN
+ EXIT label1;
+ END IF;
+ END LOOP label1;
+ WHILE x > 0 LOOP
+ x := x - 1;
+ END LOOP;
+ LOOP
+ x := x - 1;
+ IF x > 10 THEN
+ EXIT;
+ END IF;
+ END LOOP;
+ CASE x
+ WHEN 10 THEN
+ x := 100;
+ WHEN 11 THEN
+ x := 110;
+ ELSE
+ x := 120;
+ END CASE;
+ RETURN x;
+END;
+$$language plpgsql;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createIndex_statement.sql b/src/test/resources/dialect/mysql/expect/createIndex_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..289ece1e5b3dc0703c833ac93ea08c6237583e06
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createIndex_statement.sql
@@ -0,0 +1,4 @@
+CREATE UNIQUE INDEX i1 ON t9 USING BTREE (col1, col2, col3);
+-- err
+CREATE INDEX CONCURRENTLY i3 ON t10 USING BTREE (col2 DESC);
+CREATE INDEX CONCURRENTLY i4 ON t10 (col2);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createProcedure_statement.sql b/src/test/resources/dialect/mysql/expect/createProcedure_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0f79bde6c0f194bc897c141f0f2ea6a81f58f56a
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createProcedure_statement.sql
@@ -0,0 +1,68 @@
+CREATE PROCEDURE
+-- DEFINER = root
+p1 (
+ IN id INTEGER,
+ OUT res INTEGER,
+ INOUT a INTEGER
+)
+-- LANGUAGE SQL
+
+IMMUTABLE
+-- CONTAINS SQL
+
+SECURITY INVOKER
+AS
+BEGIN
+ SELECT count(id)
+ INTO res
+ FROM data
+ WHERE data.id > id;
+END;
+/
+CREATE PROCEDURE
+-- DEFINER = root
+p2 ()
+-- LANGUAGE SQL
+-- CONTAINS SQL
+
+SECURITY DEFINER
+AS
+BEGIN
+ CREATE TABLE data2 (
+ id INTEGER
+ );
+END;
+/
+CREATE PROCEDURE p3 ()
+-- LANGUAGE SQL
+
+VOLATILE
+-- CONTAINS SQL
+
+AS
+BEGIN
+ DROP TABLE IF EXISTS data1 RESTRICT;
+END;
+/
+CREATE PROCEDURE p4 ()
+-- LANGUAGE SQL
+
+VOLATILE
+-- CONTAINS SQL
+
+AS
+BEGIN
+ ALTER TABLE testAlterTable1
+ ADD col0 DECIMAL(4, 2);
+END;
+/
+CREATE PROCEDURE p5 ()
+-- COMMENT 'good'
+
+VOLATILE
+AS
+BEGIN
+ UPDATE data
+ SET data.id = data.id * 1.2;
+END;
+/
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createTable_statement.sql b/src/test/resources/dialect/mysql/expect/createTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c45b40fabf473a51c992fd22b10a144b78c7be45
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createTable_statement.sql
@@ -0,0 +1,174 @@
+CREATE TABLE testlike10 (LIKE testlike2 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE);
+CREATE TABLE t1 (
+ col1 INTEGER,
+ col2 CHAR(5)
+)
+PARTITION BY HASH (col1) (
+ PARTITION p1,
+ PARTITION p2
+);
+-- err
+-- err
+CREATE TABLE t4 (
+ col1 INTEGER,
+ col2 CHAR(5),
+ col3 DATE
+)
+PARTITION BY HASH
+-- ALGORITHM=2
+(col3)
+-- PARTITIONS 2
+ (
+ PARTITION p1
+ TABLESPACE ts1,
+ PARTITION p2
+ TABLESPACE ts1
+);
+-- err
+CREATE TABLE t6 (
+ a INTEGER NOT NULL,
+ b INTEGER NOT NULL
+)
+PARTITION BY RANGE (a, b) (
+ PARTITION p0 VALUES LESS THAN (10, 5),
+ PARTITION p1 VALUES LESS THAN (20, 10),
+ PARTITION p2 VALUES LESS THAN (50, MAXVALUE),
+ PARTITION p3 VALUES LESS THAN (65, MAXVALUE),
+ PARTITION p4 VALUES LESS THAN (MAXVALUE, MAXVALUE)
+);
+-- err
+-- err
+CREATE TABLE client_firms (
+ id INTEGER,
+ name VARCHAR(35)
+)
+PARTITION BY LIST (id) (
+ PARTITION r0 VALUES (1, 5, 9, 13, 17, 21),
+ PARTITION r1 VALUES (2, 6, 10, 14, 18, 22),
+ PARTITION r2 VALUES (3, 7, 11, 15, 19, 23),
+ PARTITION r3 VALUES (4, 8, 12, 16, 20, 24)
+);
+CREATE TABLE t9 (
+ col1 INTEGER,
+ col2 CHAR(5),
+ col3 DATE
+)
+PARTITION BY HASH
+-- ALGORITHM=2
+(col3) (
+ PARTITION p1
+ TABLESPACE ts1
+-- COMMENT 'p1'
+,
+ PARTITION p2
+ TABLESPACE ts1
+-- COMMENT 'p2'
+
+);
+CREATE TABLE testTableOptions (
+ id INTEGER,
+ name CHAR(2)
+) TABLESPACE ts1
+-- PASSWORD = 'STRING'
+-- AUTO_INCREMENT = 1
+-- AVG_ROW_LENGTH = 1
+-- CHARACTER SET = 'UTF8'
+-- CHECKSUM = 0
+-- COMPRESSION = 'NONE'
+-- CONNECTION = 'CONNECT_STRING'
+-- DATA DIRECTORY = 'ABSOLUTE PATH TO DIRECTORY'
+-- DELAY_KEY_WRITE = 0
+-- ENCRYPTION = 'Y'
+-- ENGINE = 'ENGINE_NAME'
+-- INSERT_METHOD = NO
+-- KEY_BLOCK_SIZE = 1
+-- MAX_ROWS = 1
+-- MIN_ROWS = VALUE
+-- PACK_KEYS = 0
+-- ROW_FORMAT = DEFAULT
+-- STATS_AUTO_RECALC = DEFAULT
+-- STATS_PERSISTENT = DEFAULT
+-- STATS_SAMPLE_PAGES = 1
+-- COMMENT 'STRING'
+;
+CREATE TABLE t10 (
+ col1 INTEGER PRIMARY KEY,
+ CONSTRAINT constraint_name FOREIGN KEY (col1) REFERENCES table2 (col1) MATCH PARTIAL ON UPDATE SET NULL,
+ CONSTRAINT constraint_name1 PRIMARY KEY (col1),
+ UNIQUE
+-- INDEXNAME2
+(col1)
+-- USING BTREE
+,
+
+-- FULLTEXT INDEX()
+CONSTRAINT W_CONSTR_KEY2 CHECK (col1 > 0
+ AND col2 IS NOT NULL),
+ col3 CHAR(1)
+) TABLESPACE h1
+-- COMPRESSION = 'NONE'
+;
+CREATE TABLE t11 (
+ col1 INTEGER PRIMARY KEY NOT NULL DEFAULT 1,
+ col2 BIGSERIAL
+-- COLLATE UTF8_BIN
+ UNIQUE
+-- COMMENT 'string'
+-- COLUMN_FORMAT fixed
+-- STORAGE DISK
+,
+ col3 INTEGER
+-- GENERATED ALWAYS AS (CONCAT(FIRST_NAME, ' ', LAST_NAME))
+-- VIRTUAL
+
+);
+-- hash(methodInvoke)
+-- subPartition name
+-- improper number of columns
+CREATE TABLE t15 (
+ id INTEGER,
+ purchased INTEGER
+)
+-- ENGINE = MYISAM
+
+PARTITION BY RANGE (purchased)
+SUBPARTITION BY HASH (purchased) (
+ PARTITION p0 VALUES LESS THAN (1990) (
+ SUBPARTITION s0
+-- DATA DIRECTORY '/disk0/data'
+-- INDEX DIRECTORY '/disk0/idx'
+
+ TABLESPACE ts1
+-- COMMENT 'ts1'
+ TABLESPACE ts1,
+ SUBPARTITION s1
+-- DATA DIRECTORY '/disk1/data'
+-- INDEX DIRECTORY '/disk1/idx'
+
+ TABLESPACE ts1 TABLESPACE ts1
+ ),
+ PARTITION p1 VALUES LESS THAN (2000) (
+ SUBPARTITION s2
+-- DATA DIRECTORY '/disk2/data'
+-- INDEX DIRECTORY '/disk2/idx'
+
+ TABLESPACE ts1 TABLESPACE ts1,
+ SUBPARTITION s3
+-- DATA DIRECTORY '/disk3/data'
+-- INDEX DIRECTORY '/disk3/idx'
+
+ TABLESPACE ts1 TABLESPACE ts1
+ ),
+ PARTITION p2 VALUES LESS THAN MAXVALUE (
+ SUBPARTITION s4
+-- DATA DIRECTORY '/disk4/data'
+-- INDEX DIRECTORY '/disk4/idx'
+
+ TABLESPACE ts1 TABLESPACE ts1,
+ SUBPARTITION s5
+-- DATA DIRECTORY '/disk5/data'
+-- INDEX DIRECTORY '/disk5/idx'
+
+ TABLESPACE ts1 TABLESPACE ts1
+ )
+);
diff --git a/src/test/resources/dialect/mysql/expect/createTrigger_statement.sql b/src/test/resources/dialect/mysql/expect/createTrigger_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d3ec123ff6f7c6ed14cb2c2151e9132218683d3f
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createTrigger_statement.sql
@@ -0,0 +1,23 @@
+-- DEFINER 'root'
+CREATE OR REPLACE FUNCTION createFunction_1692ab45b3a540ca863d5612ed34a1b0() RETURNS TRIGGER AS
+$$
+DECLARE
+BEGIN
+new.work_year := 0;
+new.work_year := 1;
+WHILE new.work_year > 0 LOOP
+ new.work_year := new.work_year - 1;
+END LOOP;
+LOOP
+ new.work_year := new.work_year + 1;
+ IF new.work_year > 10 THEN
+ EXIT;
+ END IF;
+END LOOP;
+RETURN NEW;
+END;
+$$ LANGUAGE plpgsql;
+CREATE TRIGGER tr_before_insert_employee
+BEFORE UPDATE ON t_employee
+FOR EACH ROW
+EXECUTE PROCEDURE createFunction_1692ab45b3a540ca863d5612ed34a1b0();
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/createView_statement.sql b/src/test/resources/dialect/mysql/expect/createView_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..b681d1120bccc76a204ede3def090b13befcd5f1
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/createView_statement.sql
@@ -0,0 +1,13 @@
+CREATE OR REPLACE
+ -- ALGORITHM = merge
+ -- DEFINER = current_user
+ -- SQL SECURITY = definer
+ VIEW vwEmployeesByDepartment
+AS
+SELECT emp.ID, emp.Name, emp.Salary, CAST(emp.DOB AS DATE) AS DOB, emp.Gender
+ , dept.Name AS DepartmentName
+FROM Employee emp
+ INNER JOIN Department dept ON emp.DeptID = dept.ID
+-- WITH CHECK OPTION
+-- CASCADED
+;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/dataType_statement.sql b/src/test/resources/dialect/mysql/expect/dataType_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..95fb74c55fbbd96669f43293ce60288b7b21115b
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/dataType_statement.sql
@@ -0,0 +1,50 @@
+CREATE TABLE testDataType (
+ id1 BIGSERIAL PRIMARY KEY,
+ id2 SMALLINT,
+ id3 INTEGER,
+ id4 INTEGER,
+ id5 BIGINT,
+ id6 INTEGER,
+ id7 FLOAT,
+ id8 DOUBLE PRECISION,
+ id9 FLOAT(4),
+ id10 FLOAT(4),
+ id11 FLOAT(4),
+ id12 TIME WITHOUT TIME ZONE,
+ id13 TIME(4) WITHOUT TIME ZONE,
+ id14 DATE,
+ id15 TIMESTAMP WITHOUT TIME ZONE,
+ id16 TIMESTAMP(4) WITHOUT TIME ZONE,
+ id17 TIMESTAMP WITHOUT TIME ZONE,
+ id18 CHAR(20)
+-- CHARACTER SET utf8
+-- CHARACTER SET utf8_bin
+,
+ id19 VARCHAR(5),
+ id20 BYTEA,
+ id21 BYTEA,
+ id22 TEXT,
+ id23 TEXT,
+ id24 TEXT,
+ id25 TEXT,
+ id26 BLOB,
+ id27 BLOB,
+ id28 BLOB,
+ id29 BLOB,
+ id30 INTEGER(4),
+ id31 INTEGER(4),
+ id32 BOOLEAN,
+ id33 BOOLEAN,
+ id34 POINT,
+ id35 POINT,
+ id36 PATH,
+ id37 POLYGON,
+ id38 BYTEA,
+ id39 BYTEA,
+ id40 BYTEA,
+ id41 BYTEA,
+ id42 JSON
+);
+CREATE TABLE testDataType2 (
+ id1 FLOAT(4) PRIMARY KEY
+);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/delete_statement.sql b/src/test/resources/dialect/mysql/expect/delete_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4230ac54a40180dafd4bbfa2699a6e24029b454c
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/delete_statement.sql
@@ -0,0 +1,10 @@
+DELETE
+-- LOW_PRIORITY IGNORE QUICK
+FROM testFunction PARTITION (p1)
+WHERE id > 1
+-- ORDER BY id
+-- LIMIT 1
+;
+-- Delete Multiple-Table Syntax
+-- Delete Multiple-Table Syntax
+-- err
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/dropIndex_statement.sql b/src/test/resources/dialect/mysql/expect/dropIndex_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..91a871348df77277a3b0bd076f40da127636ff63
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/dropIndex_statement.sql
@@ -0,0 +1,9 @@
+DROP INDEX CONCURRENTLY i5;
+DROP INDEX CONCURRENTLY i5;
+DROP INDEX testDropIndex_pkey;
+DROP INDEX
+-- ALGORITHM NULL
+i5;
+DROP INDEX
+-- ALGORITHM COPY
+i5;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/dropTable_statement.sql b/src/test/resources/dialect/mysql/expect/dropTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ece62cd073d1da133e9563b04089be43777a74ba
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/dropTable_statement.sql
@@ -0,0 +1,3 @@
+DROP TABLE
+-- TEMPORARY
+IF EXISTS testTableOptions RESTRICT;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/grant_statement.sql b/src/test/resources/dialect/mysql/expect/grant_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..eb4bb6014306296dca557bd6241312c88371ab5b
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/grant_statement.sql
@@ -0,0 +1,48 @@
+-- *
+-- *.*
+GRANT ALL ON SCHEMA delphis TO usr_replica
+-- @'%'
+;
+GRANT ALL ON ALL TABLES IN SCHEMA delphis TO usr_replica
+-- @'%'
+;
+GRANT ALL ON ALL FUNCTIONS IN SCHEMA delphis TO usr_replica
+-- @'%'
+;
+GRANT ALL ON ALL PROCEDURE IN SCHEMA delphis TO usr_replica
+-- @'%'
+;
+GRANT ALTER, CREATE, DROP, USAGE ON SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+GRANT ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON ALL TABLES IN SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+GRANT ALTER, DROP, EXECUTE ON ALL FUNCTIONS IN SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+GRANT ALTER, DROP, EXECUTE ON ALL PROCEDURE IN SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+-- incompatible privilege
+GRANT ALL ON waitCopy TO usr_replica
+-- @'%'
+;
+GRANT ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON waitCopy TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+-- incompatible privilege
+GRANT INSERT(id), REFERENCES(id), SELECT(id), UPDATE(id) ON waitCopy TO usr_replica
+-- @'%'
+;
+GRANT ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON waitCopy TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+GRANT EXECUTE ON ALL PROCEDURE IN SCHEMA delphis TO usr_replica
+-- @'%'
+ WITH GRANT OPTION;
+-- single routine
+-- single routine
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/if_statement.sql b/src/test/resources/dialect/mysql/expect/if_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ccc6d56a023fa46c81b902e95ce1a5d188fea4a1
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/if_statement.sql
@@ -0,0 +1,7 @@
+IF c = d THEN
+ a := 10;
+ELSIF c > d THEN
+ a := 11;
+ELSE
+ a := 12;
+END IF;
diff --git a/src/test/resources/dialect/mysql/expect/limit_statement.sql b/src/test/resources/dialect/mysql/expect/limit_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e79597f038cda30256e9e042391e1cd8a1d0c51e
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/limit_statement.sql
@@ -0,0 +1,3 @@
+SELECT *
+FROM hello
+LIMIT 2 OFFSET 4;
diff --git a/src/test/resources/dialect/mysql/expect/repeat_statement.sql b/src/test/resources/dialect/mysql/expect/repeat_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..77848ae523e7e86fa092fcc9e4aac6c2b915ccf4
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/repeat_statement.sql
@@ -0,0 +1,6 @@
+<>LOOP
+ a := a + 13;
+ IF x > a THEN
+ EXIT;
+ END IF;
+END LOOP begin_lable;
diff --git a/src/test/resources/dialect/mysql/expect/revoke_statement.sql b/src/test/resources/dialect/mysql/expect/revoke_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..9dac102c2cdce6b11fd526ea2cbca380b66f92b1
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/revoke_statement.sql
@@ -0,0 +1,50 @@
+-- *.*
+REVOKE ALL ON SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALL ON ALL FUNCTIONS IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALL ON ALL PROCEDURE IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALL ON ALL TABLES IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, CREATE, DROP, USAGE ON SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, DROP, EXECUTE ON ALL FUNCTIONS IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, DROP, EXECUTE ON ALL PROCEDURE IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON ALL TABLES IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+-- incompatible privilege
+-- incompatible privilege
+REVOKE ALL ON testRevoke FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON testRevoke FROM mysql_test
+-- @'%'
+;
+REVOKE INSERT(id), REFERENCES(id), SELECT(id), UPDATE(id) ON testRevoke FROM mysql_test
+-- @'%'
+;
+REVOKE ALTER, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON testRevoke FROM mysql_test
+-- @'%'
+;
+REVOKE EXECUTE ON ALL FUNCTIONS IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+REVOKE EXECUTE ON ALL PROCEDURE IN SCHEMA mysql_database FROM mysql_test
+-- @'%'
+;
+-- single rountine
+-- single rountine
+REVOKE ALL PRIVILEGE FROM mysql_test
+-- @'%'
+;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/select_query_statement_01.sql b/src/test/resources/dialect/mysql/expect/select_query_statement_01.sql
new file mode 100644
index 0000000000000000000000000000000000000000..91e8793f8f73cfb5e15d929a62253d62a3b421ac
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/select_query_statement_01.sql
@@ -0,0 +1,9 @@
+SELECT `c`.`name` AS `category`, sum(`p`.`amount`) AS `total_sales`
+FROM `sakila`.`payment` `p`
+ JOIN `sakila`.`rental` `r` ON `p`.`rental_id` = `r`.`rental_id`
+ JOIN `sakila`.`inventory` `i` ON `r`.`inventory_id` = `i`.`inventory_id`
+ JOIN `sakila`.`film` `f` ON `i`.`film_id` = `f`.`film_id`
+ JOIN `sakila`.`film_category` `fc` ON `f`.`film_id` = `fc`.`film_id`
+ JOIN `sakila`.`category` `c` ON `fc`.`category_id` = `c`.`category_id`
+GROUP BY `c`.`name`
+ORDER BY `total_sales` DESC
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/select_query_statement_02.sql b/src/test/resources/dialect/mysql/expect/select_query_statement_02.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d783664f9f47bc8c4c1e735acb7287eed650b5d6
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/select_query_statement_02.sql
@@ -0,0 +1,24 @@
+SELECT DISTINCT
+-- HIGH_PRIORITY
+-- STRAIGHT_JOIN
+-- SQL_BIG_RESULT
+-- SQL_CACHE
+-- SQL_CALC_FOUND_ROWS
+concat(`c`.`city`, '', '', `cy`.`country`) AS `store`
+ , concat(`m`.`first_name`, '', `m`.`last_name`) AS `manager`
+ , sum(`p`.`amount`) AS `total_sales`
+FROM `sakila`.`payment` `p`
+ JOIN `sakila`.`rental` `r` ON `p`.`rental_id` = `r`.`rental_id`
+ JOIN `sakila`.`inventory` `i` ON `r`.`inventory_id` = `i`.`inventory_id`
+ JOIN `sakila`.`store` `s` ON `i`.`store_id` = `s`.`store_id`
+ JOIN `sakila`.`address` `a` ON `s`.`address_id` = `a`.`address_id`
+ JOIN `sakila`.`city` `c` ON `a`.`city_id` = `c`.`city_id`
+ JOIN `sakila`.`country` `cy` ON `c`.`country_id` = `cy`.`country_id`
+ JOIN `sakila`.`staff` `m` ON `s`.`manager_staff_id` = `m`.`staff_id`
+WHERE `sakila`.`staff`.`staff_id` = 1
+ OR `sakila`.`staff`.`staff_id` = 2
+GROUP BY `sakila`.`store`.`store_id`, `sakila`.`country`.`country`, `sakila`.`city`.`city`
+HAVING `sakila`.`store`.`store_id` = 1
+ORDER BY `sakila`.`country`.`country`, `sakila`.`city`.`city`
+LIMIT 4 OFFSET 3
+FOR SHARE;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/select_query_statement_03.sql b/src/test/resources/dialect/mysql/expect/select_query_statement_03.sql
new file mode 100644
index 0000000000000000000000000000000000000000..eedee1ea33c7eda22d75742ded881890b4e2d6e8
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/select_query_statement_03.sql
@@ -0,0 +1,4 @@
+SELECT a.id, b.id
+FROM hello.tb1 a
+ JOIN hello.tb1_1 b
+FOR UPDATE NOWAIT;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/select_query_statement_04.sql b/src/test/resources/dialect/mysql/expect/select_query_statement_04.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f4f32c9d7c321e9cb7c0879e256392b601a4d563
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/select_query_statement_04.sql
@@ -0,0 +1,3 @@
+SELECT *
+FROM sakila.actor
+FOR SHARE
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/select_statement.sql b/src/test/resources/dialect/mysql/expect/select_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e528fa1ef9898183368fbe7de9fa864cd14db3f8
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/select_statement.sql
@@ -0,0 +1,40 @@
+SELECT `c`.`name` AS `category`, sum(`p`.`amount`) AS `total_sales`
+FROM `sakila`.`payment` `p`
+ JOIN `sakila`.`rental` `r` ON `p`.`rental_id` = `r`.`rental_id`
+ JOIN `sakila`.`inventory` `i` ON `r`.`inventory_id` = `i`.`inventory_id`
+ JOIN `sakila`.`film` `f` ON `i`.`film_id` = `f`.`film_id`
+ JOIN `sakila`.`film_category` `fc` ON `f`.`film_id` = `fc`.`film_id`
+ JOIN `sakila`.`category` `c` ON `fc`.`category_id` = `c`.`category_id`
+GROUP BY `c`.`name`
+ORDER BY `total_sales` DESC;
+SELECT DISTINCT
+-- HIGH_PRIORITY
+-- STRAIGHT_JOIN
+-- SQL_BIG_RESULT
+-- SQL_CACHE
+-- SQL_CALC_FOUND_ROWS
+concat(`c`.`city`, '', '', `cy`.`country`) AS `store`
+ , concat(`m`.`first_name`, '', `m`.`last_name`) AS `manager`
+ , sum(`p`.`amount`) AS `total_sales`
+FROM `sakila`.`payment` `p`
+ JOIN `sakila`.`rental` `r` ON `p`.`rental_id` = `r`.`rental_id`
+ JOIN `sakila`.`inventory` `i` ON `r`.`inventory_id` = `i`.`inventory_id`
+ JOIN `sakila`.`store` `s` ON `i`.`store_id` = `s`.`store_id`
+ JOIN `sakila`.`address` `a` ON `s`.`address_id` = `a`.`address_id`
+ JOIN `sakila`.`city` `c` ON `a`.`city_id` = `c`.`city_id`
+ JOIN `sakila`.`country` `cy` ON `c`.`country_id` = `cy`.`country_id`
+ JOIN `sakila`.`staff` `m` ON `s`.`manager_staff_id` = `m`.`staff_id`
+WHERE `sakila`.`staff`.`staff_id` = 1
+ OR `sakila`.`staff`.`staff_id` = 2
+GROUP BY `sakila`.`store`.`store_id`, `sakila`.`country`.`country`, `sakila`.`city`.`city`
+HAVING `sakila`.`store`.`store_id` = 1
+ORDER BY `sakila`.`country`.`country`, `sakila`.`city`.`city`
+LIMIT 4 OFFSET 3
+FOR SHARE;
+SELECT a.id, b.id
+FROM hello.tb1 a
+ JOIN hello.tb1_1 b
+FOR UPDATE NOWAIT;
+SELECT *
+FROM sakila.actor
+FOR SHARE;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/tableSpace_statement.sql b/src/test/resources/dialect/mysql/expect/tableSpace_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..72a26fedaf11eeeee434ed8252287c254b43bb39
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/tableSpace_statement.sql
@@ -0,0 +1,5 @@
+-- createTableSpace
+-- alterTableSpace
+DROP TABLESPACE ts2
+-- ENGINE INNODB
+;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/update_statement.sql b/src/test/resources/dialect/mysql/expect/update_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0bc7ccdd74426fb8ffeca60e6e0b978e17c07116
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/update_statement.sql
@@ -0,0 +1,8 @@
+-- update multi-table
+UPDATE items
+SET items.retail = items.retail * 0.9
+WHERE items.id > 10
+ AND EXISTS (
+ SELECT 1
+ FROM waitCopy
+ );
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/expect/while_statement.sql b/src/test/resources/dialect/mysql/expect/while_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..747f719b2d91de7bd458bc9c207ac2ec195a4361
--- /dev/null
+++ b/src/test/resources/dialect/mysql/expect/while_statement.sql
@@ -0,0 +1,3 @@
+<>WHILE c = d LOOP
+ a := 13;
+END LOOP begin_lable;
diff --git a/src/test/resources/dialect/mysql/input/alterServer_statement.sql b/src/test/resources/dialect/mysql/input/alterServer_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..77904fbf3caa63bcfb8b9724c6d25d2cbec896fe
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/alterServer_statement.sql
@@ -0,0 +1 @@
+ALTER SERVER s OPTIONS (USER 'sally');
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/alterTable_statement.sql b/src/test/resources/dialect/mysql/input/alterTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4694b77dcd5bc7a3b4f52da90aeca65939aa8b1e
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/alterTable_statement.sql
@@ -0,0 +1,87 @@
+alter table testAlterTable1 ADD COLUMN col0 decimal(4,2) first;
+
+alter table testAlterTable2 ADD COLUMN (col4 decimal(4,2),col5 float);
+
+alter table testAlterTable3 add index (col1) using btree comment 'col1' key_block_size = 128 with parser p;
+
+alter table testAlterTable4 add key index_name (col1,col2);
+
+alter table testAlterTable5 add fulltext index i4 (col4);
+
+alter table testAlterTable6 add constraint pk_id primary key pk_index using btree (col1);
+
+alter table testAlterTable7 add constraint unique_constraint unique index (col2);
+
+alter table testAlterTable8 add constraint fk_pid2 foreign key (col5) references parent(id) match simple on delete cascade;
+
+alter table testAlterTable9 add check(col5 > 0),algorithm = inplace;
+
+alter table testAlterTable10 alter col5 set default 4;
+
+alter table testAlterTable11 change col5 col6 int not null first;
+
+alter table testAlterTable12 modify col6 int null default 0;
+
+alter table testAlterTable13 default CHARACTER SET=latin1;
+
+alter table testAlterTable14 convert to CHARACTER SET latin1;
+
+alter table testAlterTable15 enable KEYS ;
+
+alter table testAlterTable16 disable keys ;
+
+alter table testAlterTable17 discard tablespace ;
+
+alter table testAlterTable18 import tablespace ;
+
+alter table testAlterTable19 drop index index_name;
+
+alter table testAlterTable20 drop primary key;
+
+alter table testAlterTable21 drop foreign key fk_pid2;
+
+alter table testAlterTable22 force ;
+
+alter table testAlterTable rename to testAlterTable2;
+
+alter table testAlterTable23 modify col5 int null,modify col3 int null, rename to testAlterTable2, modify col2 double;
+
+alter table testAlterTable24 rename to testAlterTable, modify col2 int;
+
+alter table testAlterTable25 auto_increment = 1;
+
+alter table testAlterTable26 TABLESPACE ts1 storage disk;
+
+ALTER TABLE t27 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));
+
+alter table t28 add partition (partition p3 values in (7,8,9));
+
+alter table t29 drop partition p2,p3;
+
+alter table t30 discard partition all tablespace ;
+
+alter table t31 import partition all tablespace ;
+
+alter table testAlterTableHash32 truncate partition p1,p2;
+
+alter table testAlterTableHash33 truncate partition all;
+
+ALTER TABLE t34 COALESCE PARTITION 2;
+
+alter table db.table
+ reorganize partition pMax
+ into (partition p20150201 values less than ('2015-03-01'),
+ partition p20150301 values less than ('2015-04-01'),
+ partition pMax values less than (maxvalue));
+
+ALTER TABLE e EXCHANGE PARTITION p0 WITH TABLE e2;
+
+ALTER TABLE e remove partitioning ;
+
+ALTER TABLE e upgrade partitioning ;
+
+alter table p1 PARTITION BY RANGE (year_col) (
+ PARTITION p0 VALUES LESS THAN (1991),
+ PARTITION p1 VALUES LESS THAN (1995),
+ PARTITION p2 VALUES LESS THAN (1999)
+ );
diff --git a/src/test/resources/dialect/mysql/input/columnDefinition_statement.sql b/src/test/resources/dialect/mysql/input/columnDefinition_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..621151c49822172239eb6e51bbbd946a45e20e9a
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/columnDefinition_statement.sql
@@ -0,0 +1,37 @@
+create table test1(
+ `id` int(10) auto_increment primary key ,
+ name char(2) not null default 'GA' unique comment 'char'column_format fixed storage disk
+);
+create table testIndexKey (
+ id int,
+ name char(2),
+ INDEX idIndex USING BTREE (id),
+ KEY nameIndex USING HASH (name)
+);
+create table testIndexKey (
+ id int,
+ INDEX idIndex USING BTREE (id),
+ name char(2),
+ KEY nameIndex USING HASH (name)
+);
+create table testPrimaryUniqueKey(
+ id int,
+ name char(2),
+ parent_id int,
+ constraint pk_id primary key pk_index using btree (id),
+ col3 int,
+ constraint unique_constraint unique index (name) ,
+ col4 int,
+ constraint fk_pid foreign key (parent_id) references parent(id) match simple on delete cascade,
+ col5 int,
+ constraint ck_con check(id>0) Not enforced
+);
+create table testIndexKey(
+ id int,
+ name char(2),
+ t text,
+ index id_index using btree (id),
+ key name_key using hash(name),
+ col4 int,
+ fulltext test_index (t)
+);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/compound_statement.sql b/src/test/resources/dialect/mysql/input/compound_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d8a5e7d817a38ddce665e8feb9b05000b3176624
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/compound_statement.sql
@@ -0,0 +1,27 @@
+BEGIN
+ DECLARE done INT DEFAULT FALSE;
+ DECLARE a CHAR(16);
+ DECLARE b, c INT;
+ DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
+ DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
+
+ OPEN cur1;
+ OPEN cur2;
+
+ read_loop: LOOP
+ FETCH cur1 INTO a, b;
+ FETCH cur2 INTO c;
+ IF done THEN
+ LEAVE read_loop;
+ END IF;
+ IF b < c THEN
+ INSERT INTO test.t3 VALUES (a,b);
+ ELSE
+ INSERT INTO test.t3 VALUES (a,c);
+ END IF;
+ END LOOP;
+
+ CLOSE cur1;
+ CLOSE cur2;
+END;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createDatabase_statement.sql b/src/test/resources/dialect/mysql/input/createDatabase_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..06c98f81bf61161e914f24522a617d296180656c
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createDatabase_statement.sql
@@ -0,0 +1,3 @@
+CREATE SCHEMA IF NOT EXISTS test_db_char
+ DEFAULT CHARACTER SET utf8
+ DEFAULT COLLATE utf8_chinese_ci;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createFunction_statement.sql b/src/test/resources/dialect/mysql/input/createFunction_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..bf0853b0349ede8a07ec1a6b692ff34949051970
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createFunction_statement.sql
@@ -0,0 +1,37 @@
+create
+definer = 'root'@'%'
+FUNCTION doIterate(p int,q int)
+returns int
+deterministic
+begin
+ declare x INT default 5;
+
+ label1: LOOP
+ set p=p-1;
+ insert into testFunction values(
+ default,concat('a',p)
+ );
+
+ if p<10 then
+ leave label1;
+ end if;
+ end loop label1;
+
+
+ while x>0 do
+ set x=x-1;
+ end while;
+
+ repeat
+ set x=x-1;
+ until x>10 end repeat;
+
+ case x
+ when 10 then set x=100;
+ when 11 then set x=110;
+ else
+ set x=120;
+ end case;
+
+ return x;
+end;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createIndex_statement.sql b/src/test/resources/dialect/mysql/input/createIndex_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..5be77236f2550390a36ea07a2c36e6a785f2569f
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createIndex_statement.sql
@@ -0,0 +1,5 @@
+create unique index i1 using btree on t9(col1,col2,col3) ;
+create index i2 on t10(col2(10)ASC) using hash comment 'i2' algorithm = inplace lock = default ;
+
+create index i3 on t10(col2(10)DESC)using btree algorithm = inplace;
+create index i4 on t10(col2) lock = none;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createProcedure_statement.sql b/src/test/resources/dialect/mysql/input/createProcedure_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..52f7f114deb8a6a78cb5716877c70fd30e26fba7
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createProcedure_statement.sql
@@ -0,0 +1,32 @@
+create definer = root procedure p1 (in id int,out res int,inout a int) deterministic
+ language sql contains sql sql security INVOKER
+begin
+ select count(id) into res from data where data.id > id;
+
+end;
+
+create definer = root procedure p2 ()
+ language sql contains sql sql security DEFINER
+begin
+ create table data2(id int);
+end;
+
+create procedure p3 () deterministic
+ language sql contains sql
+begin
+DROP TABLE IF EXISTS data1 RESTRICT;
+end;
+
+create procedure p4 () deterministic
+ language sql contains sql
+begin
+ALTER TABLE testAlterTable1
+ ADD col0 decimal(4, 2);
+end;
+
+create procedure p5 () deterministic
+ comment 'good'
+begin
+update data
+set data.id = data.id*1.2;
+end;
diff --git a/src/test/resources/dialect/mysql/input/createServer_statement.sql b/src/test/resources/dialect/mysql/input/createServer_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..806c5904675c04be32d304dc4ca72c36a653fdbc
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createServer_statement.sql
@@ -0,0 +1,3 @@
+CREATE SERVER s
+FOREIGN DATA WRAPPER mysql
+OPTIONS (USER 'Remote', HOST '198.51.100.106', DATABASE 'test');
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createTable_statement.sql b/src/test/resources/dialect/mysql/input/createTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0e2cc6e79c9eb582eeea59215159049bed7b17f8
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createTable_statement.sql
@@ -0,0 +1,196 @@
+create table testlike10 like testlike2;
+CREATE TABLE t1 (col1 INT, col2 CHAR(5))
+ PARTITION BY HASH(col1)(partition p1,partition p2);
+CREATE TABLE t2 (col1 INT, col2 CHAR(5), col3 DATETIME)
+ PARTITION BY linear HASH ( YEAR(col3) );
+CREATE TABLE t3 (col1 INT, col2 CHAR(5), col3 DATETIME)
+ PARTITION BY KEY ( col3,col2 )
+ PARTITIONS 4;
+CREATE TABLE t4 (col1 INT, col2 CHAR(5), col3 DATE)
+ PARTITION BY KEY(col3)
+ partitions 2(
+ partition p1 tablespace ts1,
+ partition p2 tablespace ts1
+ );
+CREATE TABLE t5 (
+ year_col INT,
+ some_data INT,
+ col3 date
+)
+ PARTITION BY RANGE (year(col3)) (
+ PARTITION p0 VALUES LESS THAN (1991),
+ PARTITION p1 VALUES LESS THAN (1995),
+ PARTITION p2 VALUES LESS THAN (1999),
+ PARTITION p3 VALUES LESS THAN (2002),
+ PARTITION p4 VALUES LESS THAN (2006),
+ PARTITION p5 VALUES LESS THAN MAXVALUE
+ );
+CREATE TABLE t6 (
+ a INT NOT NULL,
+ b INT NOT NULL
+)
+ PARTITION BY RANGE COLUMNS(a,b) (
+ PARTITION p0 VALUES LESS THAN (10,5),
+ PARTITION p1 VALUES LESS THAN (20,10),
+ PARTITION p2 VALUES LESS THAN (50,MAXVALUE),
+ PARTITION p3 VALUES LESS THAN (65,MAXVALUE),
+ PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE)
+ );
+CREATE TABLE t7 (
+ a INT NOT NULL,
+ b INT NOT NULL,
+ c INT NOT NULL,
+ d INT NOT NULL,
+ E INT NOT NULL
+)
+ PARTITION BY RANGE COLUMNS(a,b,c,d,e) (
+ PARTITION p0 VALUES LESS THAN (10,5,MAXVALUE,MAXVALUE,MAXVALUE ),
+ PARTITION p1 VALUES LESS THAN (20,10,MAXVALUE,MAXVALUE,MAXVALUE ),
+ PARTITION p2 VALUES LESS THAN (50,MAXVALUE,MAXVALUE,MAXVALUE,MAXVALUE ),
+ PARTITION p3 VALUES LESS THAN (65,MAXVALUE,MAXVALUE,MAXVALUE,MAXVALUE ),
+ PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE,MAXVALUE,MAXVALUE,MAXVALUE )
+ );
+CREATE TABLE t8 (
+ id INT NOT NULL PRIMARY KEY,
+ name VARCHAR(20)
+)
+ PARTITION BY KEY()
+ PARTITIONS 2;
+CREATE TABLE client_firms (
+ id INT,
+ name VARCHAR(35)
+)
+PARTITION BY LIST (id) (
+ PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
+ PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
+ PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
+ PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
+);
+CREATE TABLE t9 (col1 INT, col2 CHAR(5), col3 DATE)
+ PARTITION BY KEY(col3)
+ (
+ partition p1 tablespace = ts1 comment = 'p1' ,
+ partition p2 tablespace = ts1 comment = 'p2'
+ );
+create table testTableOptions(
+ id int,
+ name char(2)
+)tablespace ts1,
+ password = 'string',
+ AUTO_INCREMENT=1,
+ AVG_ROW_LENGTH=1,
+ CHARACTER SET='utf8',
+ CHECKSUM=0,
+ COMMENT='string',
+ COMPRESSION ='NONE',
+ CONNECTION = 'connect_string',
+ data DIRECTORY = 'absolute path to directory',
+ DELAY_KEY_WRITE = 0,
+ ENCRYPTION ='Y',
+ ENGINE = 'engine_name',
+ INSERT_METHOD = NO ,
+ KEY_BLOCK_SIZE =1,
+ MAX_ROWS = 1,
+ MIN_ROWS = value,
+ PACK_KEYS=0,
+ ROW_FORMAT =DEFAULT ,
+ STATS_AUTO_RECALC =DEFAULT,
+ STATS_PERSISTENT =DEFAULT,
+ STATS_SAMPLE_PAGES =1;
+
+create table t10 (
+ col1 INT primary key,
+ constraint constraint_name foreign key (col1) references table2 (col1) match partial on update set null,
+ constraint constraint_name1 primary key indexname1 (col1) COMMENT 'string',
+ constraint constraint_name2 unique indexname2 using btree(col1),
+ fulltext index(col1),
+ CONSTRAINT W_CONSTR_KEY2 CHECK(col1 > 0 AND col2 IS NOT NULL),
+ col3 char(1))
+ tablespace h1 compression='NONE';
+
+create table t11 (
+ col1 INT primary key not null default 1,
+ col2 int auto_increment unique comment 'string' collate utf8_bin column_format fixed storage disk,
+ col3 int generated always as (CONCAT(first_name,' ',last_name)) virtual);
+
+CREATE TABLE t12 (id INT, purchased DATE)
+ PARTITION BY RANGE(id)
+ SUBPARTITION BY HASH( TO_DAYS(purchased) )
+ SUBPARTITIONS 2 (
+ PARTITION p0 VALUES LESS THAN (1990)(
+ SUBPARTITION s01,
+ SUBPARTITION s02
+ ),
+
+ PARTITION p1 VALUES LESS THAN (2000)(
+ SUBPARTITION s11,
+ SUBPARTITION s12
+ ),
+ PARTITION p2 VALUES LESS THAN MAXVALUE(
+ SUBPARTITION s21,
+ SUBPARTITION s22
+ )
+ );
+
+CREATE TABLE t13 (id INT, purchased int )
+ PARTITION BY RANGE( id )
+ SUBPARTITION BY HASH( purchased )
+ SUBPARTITIONS 2 (
+ PARTITION p0 VALUES LESS THAN (1990),
+ PARTITION p1 VALUES LESS THAN (2000),
+ PARTITION p2 VALUES LESS THAN MAXVALUE
+ );
+
+CREATE TABLE t14 (id INT, purchased int)
+ PARTITION BY RANGE( id )
+ SUBPARTITION BY KEY ( id,purchased) (
+ PARTITION p0 VALUES LESS THAN (1990) (
+ SUBPARTITION s0,
+ SUBPARTITION s1
+ ),
+ PARTITION p1 VALUES LESS THAN (2000) (
+ SUBPARTITION s2,
+ SUBPARTITION s3
+ ),
+ PARTITION p2 VALUES LESS THAN MAXVALUE (
+ SUBPARTITION s4,
+ SUBPARTITION s5
+ )
+ );
+
+CREATE TABLE t15 (id INT, purchased int)
+ ENGINE = MYISAM
+ PARTITION BY RANGE( purchased )
+ SUBPARTITION BY HASH( purchased) (
+ PARTITION p0 VALUES LESS THAN (1990) (
+ SUBPARTITION s0
+ DATA DIRECTORY = '/disk0/data'
+ INDEX DIRECTORY = '/disk0/idx'
+ comment = "ts1"
+ tablespace = ts1,
+ SUBPARTITION s1
+ DATA DIRECTORY = '/disk1/data'
+ INDEX DIRECTORY = '/disk1/idx'
+ tablespace = ts1
+ ),
+ PARTITION p1 VALUES LESS THAN (2000) (
+ SUBPARTITION s2
+ DATA DIRECTORY = '/disk2/data'
+ INDEX DIRECTORY = '/disk2/idx'
+ tablespace = ts1,
+ SUBPARTITION s3
+ DATA DIRECTORY = '/disk3/data'
+ INDEX DIRECTORY = '/disk3/idx'
+ tablespace = ts1
+ ),
+ PARTITION p2 VALUES LESS THAN MAXVALUE (
+ SUBPARTITION s4
+ DATA DIRECTORY = '/disk4/data'
+ INDEX DIRECTORY = '/disk4/idx'
+ tablespace = ts1,
+ SUBPARTITION s5
+ DATA DIRECTORY = '/disk5/data'
+ INDEX DIRECTORY = '/disk5/idx'
+ tablespace = ts1
+ )
+ );
diff --git a/src/test/resources/dialect/mysql/input/createTrigger_statement.sql b/src/test/resources/dialect/mysql/input/createTrigger_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..366d8c6c912a62dd5157e0f402c4bc1094ad52d4
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createTrigger_statement.sql
@@ -0,0 +1,15 @@
+CREATE Definer='root' TRIGGER tr_before_insert_employee
+ BEFORE UPDATE
+ ON t_employee
+ FOR EACH ROW
+ BEGIN
+ SET new.work_year = 0;
+ SET new.work_year = 1;
+ while new.work_year>0 do
+ set new.work_year=new.work_year-1;
+ end while;
+
+ repeat
+ set new.work_year=new.work_year+1;
+ until new.work_year>10 end repeat;
+ END
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/createView_statement.sql b/src/test/resources/dialect/mysql/input/createView_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..94e016aeac38045700e34e6aab478e67aa05b7cb
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/createView_statement.sql
@@ -0,0 +1,6 @@
+create
+or replace algorithm = merge definer=current_user() sql security definer VIEW vwEmployeesByDepartment AS
+SELECT emp.ID, emp.Name, emp.Salary, CAST(emp.DOB AS Date) AS DOB, emp.Gender, dept.Name AS DepartmentName
+FROM Employee emp
+ INNER JOIN Department dept ON emp.DeptID = dept.ID with cascaded check
+option;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/dataType_statement.sql b/src/test/resources/dialect/mysql/input/dataType_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..7e1ce5dbf92ef9c7a5e45c2045f593292bff98ea
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/dataType_statement.sql
@@ -0,0 +1,56 @@
+create table testDataType(
+ id1 TINYINT auto_increment primary key ,
+ id2 SMALLINT,
+ id3 MEDIUMINT,
+ id4 INT,
+ id5 bigint(15),
+ id6 int(15),
+
+ id7 FLOAT,
+ id8 DOUBLE,
+ id9 FLOAT(4,2) ,
+ id10 DOUBLE(4,2),
+ id11 REAL(4,2),
+
+ id12 TIME,
+ id13 TIME(4),
+ id14 DATE,
+ id15 DATETIME,
+ id16 DATETIME(4),
+ id17 TIMESTAMP,
+
+ id18 CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin,
+ id19 varchar(5),
+
+ id20 BINARY(5),
+ id21 VARBINARY(5),
+
+ id22 TINYTEXT,
+ id23 TEXT,
+ id24 MEDIUMTEXT,
+ id25 LONGTEXT,
+
+ id26 TINYBLOB,
+ id27 BLOB,
+ id28 MEDIUMBLOB,
+ id29 LONGBLOB,
+
+ id30 bit(4),
+ id31 year(4),
+ id32 bool,
+ id33 boolean,
+
+ id34 geometry,
+ id35 point,
+ id36 linestring,
+ id37 polygon,
+ id38 multipoint,
+ id39 geometrycollection,
+ id40 multilinestring,
+ id41 multipolygon,
+ id42 json
+ );
+
+create table testDataType2(
+ id1 float(4,2) auto_increment primary key
+);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/delete_statement.sql b/src/test/resources/dialect/mysql/input/delete_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..7f3c2a105c1633b8b5cc685db8a3652f9321ab1b
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/delete_statement.sql
@@ -0,0 +1,16 @@
+delete low_priority quick ignore
+from testFunction partition (p1)
+where id>1
+order by id
+limit 1;
+delete t1,t2
+from t1 left join t2 on t1.id=t2.id
+where t1.id<5;
+
+delete t1,t2
+from t1 join t2 using(`id`)
+where t1.id<5;
+
+delete from t1,t2
+using t1 join t2 using(`id`)
+where t1.id<5;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/dropIndex_statement.sql b/src/test/resources/dialect/mysql/input/dropIndex_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..642ca8696d045807f8efd6dba82a77851b29aca4
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/dropIndex_statement.sql
@@ -0,0 +1,5 @@
+drop index i5 on testDropIndex algorithm = INPLACE lock = default;
+drop index i5 on testDropIndex lock = none;
+drop index `PRIMARY` on testDropIndex;
+drop index i5 on testDropIndex algorithm = default lock = default;
+drop index i5 on testDropIndex algorithm = COPY lock = shared;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/dropServer_statement.sql b/src/test/resources/dialect/mysql/input/dropServer_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..ad0871f947c94198f83f755f74446a0ee3073f94
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/dropServer_statement.sql
@@ -0,0 +1 @@
+DROP SERVER IF EXISTS test_server;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/dropTable_statement.sql b/src/test/resources/dialect/mysql/input/dropTable_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0bcec78b1b1cd6b4aa8f6ba55224d447a00389e2
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/dropTable_statement.sql
@@ -0,0 +1 @@
+drop temporary table if exists testTableOptions restrict ;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/grant_statement.sql b/src/test/resources/dialect/mysql/input/grant_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..98abcc6b3104a581be3040f334ad11b043eef91d
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/grant_statement.sql
@@ -0,0 +1,33 @@
+-- *,不适配
+grant all on * to 'usr_replica'@'%';
+
+-- *.*,不适配
+grant all on *.* to 'usr_replica'@'%';
+
+-- db.*
+-- 与OpenGauss适配的
+grant all on delphis.* to 'usr_replica'@'%';
+grant alter,create,delete,drop,execute,index,insert,references,select,update,usage on delphis.* to 'usr_replica'@'%' with grant option;
+-- 与OpenGauss不适配的
+grant alter routine,create routine,create temporary tables,create view,event,lock tables,show view,trigger on delphis.* to 'usr_replica'@'%';
+
+-- db.table
+-- 与OpenGauss适配的
+grant all on delphis.waitCopy to 'usr_replica'@'%';
+grant alter ,delete,drop,index,insert,references ,select,update on delphis.waitCopy to 'usr_replica'@'%' with grant option;
+-- 与OpenGauss不适配的
+grant create,create view,show view,trigger,usage on delphis.waitCopy to 'usr_replica'@'%';
+
+-- db.table列权限,均适配
+grant insert (id),references (id),select (id),update (id) on delphis.waitCopy to 'usr_replica'@'%';
+
+-- table
+grant alter ,delete,drop,index,insert,references ,select,update on waitCopy to 'usr_replica'@'%' with grant option;
+
+
+-- routine
+-- 支持某库下所有routine(函数和存储过程)
+grant execute on delphis.* to 'usr_replica'@'%' with grant option;
+-- 不支持某一特定函数
+grant execute on function delphis.addfunction to 'usr_replica'@'%' with grant option;
+grant execute on procedure delphis.addprocedure to 'usr_replica'@'%' with grant option;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/if_statement.sql b/src/test/resources/dialect/mysql/input/if_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e30745304106c96cebfc51cf28e46f869f63c407
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/if_statement.sql
@@ -0,0 +1,7 @@
+if c = d then
+ set a = 10;
+else if c > d then
+ set a = 11;
+else
+ set a = 12;
+END IF;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/limit_statement.sql b/src/test/resources/dialect/mysql/input/limit_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..8c6238c9fe062ab2bb1db11b9c3561f177934a2a
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/limit_statement.sql
@@ -0,0 +1 @@
+select * from hello limit 4,2;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/repeat_statement.sql b/src/test/resources/dialect/mysql/input/repeat_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a7c0649b781937213b194cf2eb4faf4668fe06a1
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/repeat_statement.sql
@@ -0,0 +1,4 @@
+begin_lable: repeat
+ set a = a + 13;
+UNTIL x > a
+end repeat begin_lable;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/revoke_statement.sql b/src/test/resources/dialect/mysql/input/revoke_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..6a6c451ee87e0c52757c9eff045b05a1b7ddf5c0
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/revoke_statement.sql
@@ -0,0 +1,24 @@
+revoke all on *.* from 'mysql_test'@'%';
+
+revoke all on mysql_database.* from 'mysql_test'@'%';
+
+revoke alter,create,delete,drop,execute,index,insert,references,select,update,usage on mysql_database.* from 'mysql_test'@'%';
+
+revoke alter routine,create routine,create temporary tables,create view,event,lock tables,show view,trigger on mysql_database.* from 'mysql_test'@'%';
+
+revoke alter routine,create routine,create temporary tables,create view,event,lock tables,show view,trigger on mysql_database.* from 'mysql_test'@'%';
+
+revoke all on mysql_database.testRevoke from 'mysql_test'@'%';
+
+revoke alter ,delete,drop,index,insert,references ,select,update on mysql_database.testRevoke from 'mysql_test'@'%';
+
+revoke insert (id),references (id),select (id),update (id) on mysql_database.testRevoke from 'mysql_test'@'%';
+
+revoke alter ,delete,drop,index,insert,references ,select,update on testRevoke from 'mysql_test'@'%';
+
+revoke execute on mysql_database.* from 'mysql_test'@'%' ;
+
+revoke execute on function mysql_database.hello from 'mysql_test'@'%';
+revoke execute on procedure mysql_database.hello from 'mysql_test'@'%';
+
+REVOKE ALL , GRANT OPTION FROM 'mysql_test'@'%';
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/select_query_statement_01.sql b/src/test/resources/dialect/mysql/input/select_query_statement_01.sql
new file mode 100644
index 0000000000000000000000000000000000000000..bd830e5600e7a1b52498d0c1a8dc8f34323ee347
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/select_query_statement_01.sql
@@ -0,0 +1,9 @@
+select `c`.`name` AS `category`, sum(`p`.`amount`) AS `total_sales`
+from (((((`sakila`.`payment` `p`
+ join `sakila`.`rental` `r` on ((`p`.`rental_id` = `r`.`rental_id`)))
+ join `sakila`.`inventory` `i` on ((`r`.`inventory_id` = `i`.`inventory_id`)))
+ join `sakila`.`film` `f` on ((`i`.`film_id` = `f`.`film_id`)))
+ join `sakila`.`film_category` `fc` on ((`f`.`film_id` = `fc`.`film_id`)))
+ join `sakila`.`category` `c` on ((`fc`.`category_id` = `c`.`category_id`)))
+group by `c`.`name`
+order by `total_sales` desc
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/select_query_statement_02.sql b/src/test/resources/dialect/mysql/input/select_query_statement_02.sql
new file mode 100644
index 0000000000000000000000000000000000000000..9d00193e1023328ed1b7a291d2db3a9e5a0d7f89
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/select_query_statement_02.sql
@@ -0,0 +1,16 @@
+select distinct high_priority straight_join sql_big_result sql_cache sql_calc_found_rows concat(`c`.`city`, '','', `cy`.`country`) AS `store`, concat(`m`.`first_name`, '' '', `m`.`last_name`) AS `manager`,
+ sum(`p`.`amount`) AS `total_sales`
+from (((((((`sakila`.`payment` `p`
+ join `sakila`.`rental` `r` on ((`p`.`rental_id` = `r`.`rental_id`)))
+ join `sakila`.`inventory` `i` on ((`r`.`inventory_id` = `i`.`inventory_id`)))
+ join `sakila`.`store` `s` on ((`i`.`store_id` = `s`.`store_id`)))
+ join `sakila`.`address` `a` on ((`s`.`address_id` = `a`.`address_id`)))
+ join `sakila`.`city` `c` on ((`a`.`city_id` = `c`.`city_id`)))
+ join `sakila`.`country` `cy` on ((`c`.`country_id` = `cy`.`country_id`)))
+ join `sakila`.`staff` `m` on ((`s`.`manager_staff_id` = `m`.`staff_id`)))
+where `sakila`.`staff`.`staff_id` = 1
+ or `sakila`.`staff`.`staff_id` = 2
+group by `sakila`.`store`.`store_id`, `sakila`.`country`.`country`, `sakila`.`city`.`city`
+having `sakila`.`store`.`store_id` = 1
+order by `sakila`.`country`.`country`, `sakila`.`city`.`city` limit 4
+offset 3 LOCK IN SHARE MODE;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/select_query_statement_03.sql b/src/test/resources/dialect/mysql/input/select_query_statement_03.sql
new file mode 100644
index 0000000000000000000000000000000000000000..2dca287509c373ea5a4d12f1f0c74aece702f46b
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/select_query_statement_03.sql
@@ -0,0 +1,4 @@
+-- hello
+select a.id, b.id
+from hello.tb1 as a straight_join hello.tb1_1 as b for
+update nowait;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/select_query_statement_04.sql b/src/test/resources/dialect/mysql/input/select_query_statement_04.sql
new file mode 100644
index 0000000000000000000000000000000000000000..b7a5f84b796d4c5cd3278b2ea1b49f4e46b589fe
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/select_query_statement_04.sql
@@ -0,0 +1,2 @@
+select *
+from sakila.actor lock in share mode
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/select_statement.sql b/src/test/resources/dialect/mysql/input/select_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..677b887182a96baecd551da4e149a1bf8042217e
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/select_statement.sql
@@ -0,0 +1,39 @@
+select `c`.`name` AS `category`, sum(`p`.`amount`) AS `total_sales`
+from (((((`sakila`.`payment` `p`
+ join `sakila`.`rental` `r` on ((`p`.`rental_id` = `r`.`rental_id`)))
+ join `sakila`.`inventory` `i` on ((`r`.`inventory_id` = `i`.`inventory_id`)))
+ join `sakila`.`film` `f` on ((`i`.`film_id` = `f`.`film_id`)))
+ join `sakila`.`film_category` `fc` on ((`f`.`film_id` = `fc`.`film_id`)))
+ join `sakila`.`category` `c` on ((`fc`.`category_id` = `c`.`category_id`)))
+group by `c`.`name`
+order by `total_sales` desc;
+
+select distinct high_priority straight_join sql_big_result sql_cache sql_calc_found_rows concat(`c`.`city`, '','', `cy`.`country`) AS `store`,
+ concat(`m`.`first_name`, '' '', `m`.`last_name`) AS `manager`,
+ sum(`p`.`amount`) AS `total_sales`
+from (((((((`sakila`.`payment` `p`
+ join `sakila`.`rental` `r` on ((`p`.`rental_id` = `r`.`rental_id`)))
+ join `sakila`.`inventory` `i` on ((`r`.`inventory_id` = `i`.`inventory_id`)))
+ join `sakila`.`store` `s` on ((`i`.`store_id` = `s`.`store_id`)))
+ join `sakila`.`address` `a` on ((`s`.`address_id` = `a`.`address_id`)))
+ join `sakila`.`city` `c` on ((`a`.`city_id` = `c`.`city_id`)))
+ join `sakila`.`country` `cy` on ((`c`.`country_id` = `cy`.`country_id`)))
+ join `sakila`.`staff` `m` on ((`s`.`manager_staff_id` = `m`.`staff_id`)))
+where `sakila`.`staff`.`staff_id` = 1
+ or `sakila`.`staff`.`staff_id` = 2
+group by `sakila`.`store`.`store_id`, `sakila`.`country`.`country`, `sakila`.`city`.`city`
+having `sakila`.`store`.`store_id` = 1
+order by `sakila`.`country`.`country`, `sakila`.`city`.`city`
+limit 4 offset 3
+ LOCK IN SHARE MODE;
+
+-- hello
+select a.id, b.id
+from hello.tb1 as a
+ straight_join hello.tb1_1 as b
+for
+update nowait;
+
+
+select *
+from sakila.actor lock in share mode;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/tableSpace_statement.sql b/src/test/resources/dialect/mysql/input/tableSpace_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..f1668b7aea1e138137b218496734af33d6859ac8
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/tableSpace_statement.sql
@@ -0,0 +1,5 @@
+CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
+
+ALTER TABLESPACE ts1 ADD DATAFILE 'file_name';
+
+DROP TABLESPACE ts2 Engine=InnoDB;
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/update_statement.sql b/src/test/resources/dialect/mysql/input/update_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0b2231169f925e98558a741d3bfaacc4f27eb753
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/update_statement.sql
@@ -0,0 +1,16 @@
+ UPDATE low_priority ignore
+ /* NO_MERGE(discounted) */ items use index for order by (idx_name) partition (p0),
+
+ (SELECT id FROM items
+ WHERE retail / wholesale >= 1.3 AND quantity < 100)
+ AS discounted
+ SET items.retail = items.retail * 0.9
+ WHERE items.id = discounted.id
+ and exists (select 1 from waitCopy)
+ order by item.id
+ limit 6;
+
+ UPDATE items
+ SET items.retail = items.retail * 0.9
+ WHERE items.id > 10
+ and exists (select 1 from waitCopy);
\ No newline at end of file
diff --git a/src/test/resources/dialect/mysql/input/while_statement.sql b/src/test/resources/dialect/mysql/input/while_statement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d463e87253e6a18c5356bb4b32f5d7ec874e201f
--- /dev/null
+++ b/src/test/resources/dialect/mysql/input/while_statement.sql
@@ -0,0 +1,3 @@
+begin_lable: WHILE c = d DO
+ set a = 13;
+end while begin_lable;
\ No newline at end of file