From a29eb6e0d2ef52f79699ee04a3faf112ef16a005 Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 28 May 2017 17:39:53 +0800 Subject: [PATCH] improved sql parser. --- .../alibaba/druid/pool/DruidDataSource.java | 17 + .../proxy/jdbc/DatabaseMetaDataProxyImpl.java | 907 ++++++++++++++++++ .../com/alibaba/druid/sql/ast/SQLLimit.java | 5 + .../druid/sql/ast/expr/SQLBinaryOpExpr.java | 4 + .../druid/sql/ast/expr/SQLIntegerExpr.java | 4 + .../druid/sql/ast/expr/SQLVariantRefExpr.java | 3 + .../ast/statement/SQLAlterTableRename.java | 22 +- .../ast/statement/SQLAlterTableStatement.java | 21 + .../ast/statement/SQLColumnDefinition.java | 22 + .../statement/SQLCreateIndexStatement.java | 16 + .../statement/SQLDropSequenceStatement.java | 8 + .../statement/SQLDropTriggerStatement.java | 10 +- .../sql/ast/statement/SQLIfStatement.java | 3 + .../sql/ast/statement/SQLLoopStatement.java | 6 +- .../sql/ast/statement/SQLSelectItem.java | 23 + .../mysql/parser/MySqlStatementParser.java | 19 +- .../mysql/visitor/MySqlOutputVisitor.java | 38 +- ...ment.java => OracleContinueStatement.java} | 12 +- .../stmt/OracleExecuteImmediateStatement.java | 55 ++ .../oracle/ast/stmt/OracleExitStatement.java | 8 + .../ast/stmt/OracleLockTableStatement.java | 15 +- .../oracle/parser/OracleStatementParser.java | 113 ++- .../oracle/visitor/OracleASTVisitor.java | 8 +- .../visitor/OracleASTVisitorAdapter.java | 14 +- .../oracle/visitor/OracleOutputVisitor.java | 60 +- .../visitor/OracleSchemaStatVisitor.java | 23 +- .../druid/sql/parser/SQLExprParser.java | 7 +- .../druid/sql/parser/SQLStatementParser.java | 19 +- .../sql/visitor/SQLASTOutputVisitor.java | 41 +- .../com/alibaba/druid/stat/JdbcSqlStat.java | 10 +- .../com/alibaba/druid/util/DruidWebUtils.java | 10 + .../java/com/alibaba/druid/util/Utils.java | 10 - .../filter/wall/mysql/MySqlWallTest146.java | 26 + .../mysql/alter/MySqlAlterTableTest28.java | 41 + .../mysql/alter/MySqlAlterTableTest29.java | 51 + .../oracle/alter/OracleAlterTableTest24.java | 63 ++ .../sql/oracle/block/OracleBlockTest16.java | 99 ++ .../sql/oracle/block/OracleBlockTest17.java | 89 ++ .../sql/oracle/block/OracleBlockTest18.java | 98 ++ .../sql/oracle/block/OracleBlockTest19.java | 76 ++ .../create/OracleCreatePackageTest0.java | 4 +- .../create/OracleCreateTableTest67.java | 73 ++ .../create/OracleCreateTriggerTest2.java | 80 ++ .../sql/oracle/demo/OracleResourceTest.java | 82 ++ .../sql/oracle/demo/OracleResourceTest2.java | 77 ++ 45 files changed, 2303 insertions(+), 89 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/proxy/jdbc/DatabaseMetaDataProxyImpl.java rename src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/{OracleConntinueStatement.java => OracleContinueStatement.java} (79%) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExecuteImmediateStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest146.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest28.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest29.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTableTest24.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest16.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest17.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest18.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest19.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest67.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTriggerTest2.java create mode 100644 src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest.java create mode 100644 src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest2.java diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index bcb398c1f8..8d12e61acd 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -367,6 +367,23 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat this.setUseUnfairLock(value); } } + { + String property = properties.getProperty("druid.driverClassName"); + if (property != null) { + this.setDriverClassName(property); + } + } + { + String property = properties.getProperty("druid.initialSize"); + if (property != null && property.length() > 0) { + try { + int value = Integer.parseInt(property); + super.setInitialSize(value); + } catch (NumberFormatException e) { + LOG.error("illegal property 'druid.initialSize'", e); + } + } + } } public boolean isUseGlobalDataSourceStat() { diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/DatabaseMetaDataProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/DatabaseMetaDataProxyImpl.java new file mode 100644 index 0000000000..42710c1b19 --- /dev/null +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/DatabaseMetaDataProxyImpl.java @@ -0,0 +1,907 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.proxy.jdbc; + +import java.sql.*; + +/** + * Created by wenshao on 26/05/2017. + */ +public class DatabaseMetaDataProxyImpl implements DatabaseMetaData { + private DatabaseMetaData metaData; + + public DatabaseMetaDataProxyImpl(DatabaseMetaData metaData) { + this.metaData = metaData; + } + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return metaData.allProceduresAreCallable(); + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return metaData.allTablesAreSelectable(); + } + + @Override + public String getURL() throws SQLException { + return metaData.getURL(); + } + + @Override + public String getUserName() throws SQLException { + return metaData.getUserName(); + } + + @Override + public boolean isReadOnly() throws SQLException { + return metaData.isReadOnly(); + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return metaData.nullsAreSortedHigh(); + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return metaData.nullsAreSortedLow(); + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return metaData.nullsAreSortedAtStart(); + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return metaData.nullsAreSortedAtEnd(); + } + + @Override + public String getDatabaseProductName() throws SQLException { + return metaData.getDatabaseProductName(); + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return metaData.getDatabaseProductVersion(); + } + + @Override + public String getDriverName() throws SQLException { + return metaData.getDriverName(); + } + + @Override + public String getDriverVersion() throws SQLException { + return metaData.getDriverVersion(); + } + + @Override + public int getDriverMajorVersion() { + return metaData.getDriverMajorVersion(); + } + + @Override + public int getDriverMinorVersion() { + return metaData.getDriverMinorVersion(); + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return metaData.usesLocalFiles(); + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return metaData.usesLocalFilePerTable(); + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return metaData.supportsMixedCaseIdentifiers(); + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return metaData.storesUpperCaseIdentifiers(); + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return metaData.storesMixedCaseIdentifiers(); + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return metaData.supportsMixedCaseIdentifiers(); + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return metaData.supportsMixedCaseQuotedIdentifiers(); + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return metaData.storesUpperCaseIdentifiers(); + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return metaData.storesLowerCaseQuotedIdentifiers(); + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return metaData.storesMixedCaseQuotedIdentifiers(); + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return metaData.getIdentifierQuoteString(); + } + + @Override + public String getSQLKeywords() throws SQLException { + return metaData.getSQLKeywords(); + } + + @Override + public String getNumericFunctions() throws SQLException { + return metaData.getNumericFunctions(); + } + + @Override + public String getStringFunctions() throws SQLException { + return metaData.getStringFunctions(); + } + + @Override + public String getSystemFunctions() throws SQLException { + return metaData.getSystemFunctions(); + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return metaData.getTimeDateFunctions(); + } + + @Override + public String getSearchStringEscape() throws SQLException { + return metaData.getSearchStringEscape(); + } + + @Override + public String getExtraNameCharacters() throws SQLException { + return metaData.getExtraNameCharacters(); + } + + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLException { + return metaData.supportsAlterTableWithAddColumn(); + } + + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLException { + return metaData.supportsAlterTableWithDropColumn(); + } + + @Override + public boolean supportsColumnAliasing() throws SQLException { + return metaData.supportsColumnAliasing(); + } + + @Override + public boolean nullPlusNonNullIsNull() throws SQLException { + return metaData.nullPlusNonNullIsNull(); + } + + @Override + public boolean supportsConvert() throws SQLException { + return metaData.supportsConvert(); + } + + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLException { + return metaData.supportsConvert(fromType, toType); + } + + @Override + public boolean supportsTableCorrelationNames() throws SQLException { + return metaData.supportsTableCorrelationNames(); + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return metaData.supportsDifferentTableCorrelationNames(); + } + + @Override + public boolean supportsExpressionsInOrderBy() throws SQLException { + return metaData.supportsExpressionsInOrderBy(); + } + + @Override + public boolean supportsOrderByUnrelated() throws SQLException { + return metaData.supportsOrderByUnrelated(); + } + + @Override + public boolean supportsGroupBy() throws SQLException { + return metaData.supportsGroupBy(); + } + + @Override + public boolean supportsGroupByUnrelated() throws SQLException { + return metaData.supportsGroupByUnrelated(); + } + + @Override + public boolean supportsGroupByBeyondSelect() throws SQLException { + return metaData.supportsGroupByBeyondSelect(); + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return metaData.supportsLikeEscapeClause(); + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return metaData.supportsMultipleResultSets(); + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return metaData.supportsMultipleTransactions(); + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return metaData.supportsNonNullableColumns(); + } + + @Override + public boolean supportsMinimumSQLGrammar() throws SQLException { + return metaData.supportsMinimumSQLGrammar(); + } + + @Override + public boolean supportsCoreSQLGrammar() throws SQLException { + return metaData.supportsCoreSQLGrammar(); + } + + @Override + public boolean supportsExtendedSQLGrammar() throws SQLException { + return metaData.supportsExtendedSQLGrammar(); + } + + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLException { + return metaData.supportsANSI92EntryLevelSQL(); + } + + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLException { + return metaData.supportsANSI92IntermediateSQL(); + } + + @Override + public boolean supportsANSI92FullSQL() throws SQLException { + return metaData.supportsANSI92FullSQL(); + } + + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLException { + return metaData.supportsIntegrityEnhancementFacility(); + } + + @Override + public boolean supportsOuterJoins() throws SQLException { + return metaData.supportsOuterJoins(); + } + + @Override + public boolean supportsFullOuterJoins() throws SQLException { + return metaData.supportsFullOuterJoins(); + } + + @Override + public boolean supportsLimitedOuterJoins() throws SQLException { + return metaData.supportsLimitedOuterJoins(); + } + + @Override + public String getSchemaTerm() throws SQLException { + return metaData.getSchemaTerm(); + } + + @Override + public String getProcedureTerm() throws SQLException { + return metaData.getProcedureTerm(); + } + + @Override + public String getCatalogTerm() throws SQLException { + return metaData.getCatalogTerm(); + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return metaData.isCatalogAtStart(); + } + + @Override + public String getCatalogSeparator() throws SQLException { + return metaData.getCatalogSeparator(); + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return metaData.supportsSchemasInDataManipulation(); + } + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return metaData.supportsSchemasInProcedureCalls(); + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return metaData.supportsSchemasInTableDefinitions(); + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return metaData.supportsSchemasInIndexDefinitions(); + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return metaData.supportsSchemasInPrivilegeDefinitions(); + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return metaData.supportsCatalogsInDataManipulation(); + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return metaData.supportsCatalogsInProcedureCalls(); + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return metaData.supportsCatalogsInTableDefinitions(); + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return metaData.supportsCatalogsInIndexDefinitions(); + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return metaData.supportsCatalogsInPrivilegeDefinitions(); + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return metaData.supportsPositionedDelete(); + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return metaData.supportsPositionedUpdate(); + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return metaData.supportsSelectForUpdate(); + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return metaData.supportsStoredProcedures(); + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return metaData.supportsSubqueriesInComparisons(); + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return metaData.supportsSubqueriesInExists(); + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return metaData.supportsSubqueriesInIns(); + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return metaData.supportsSubqueriesInQuantifieds(); + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return metaData.supportsCorrelatedSubqueries(); + } + + @Override + public boolean supportsUnion() throws SQLException { + return metaData.supportsUnion(); + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return metaData.supportsUnionAll(); + } + + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + return metaData.supportsOpenCursorsAcrossCommit(); + } + + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + return metaData.supportsOpenCursorsAcrossRollback(); + } + + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + return metaData.supportsOpenStatementsAcrossCommit(); + } + + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + return metaData.supportsOpenStatementsAcrossRollback(); + } + + @Override + public int getMaxBinaryLiteralLength() throws SQLException { + return metaData.getMaxBinaryLiteralLength(); + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return metaData.getMaxCharLiteralLength(); + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return metaData.getMaxColumnNameLength(); + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return metaData.getMaxColumnsInGroupBy(); + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return metaData.getMaxColumnsInIndex(); + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return metaData.getMaxColumnsInOrderBy(); + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return metaData.getMaxColumnsInSelect(); + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return metaData.getMaxColumnsInTable(); + } + + @Override + public int getMaxConnections() throws SQLException { + return metaData.getMaxConnections(); + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return metaData.getMaxCursorNameLength(); + } + + @Override + public int getMaxIndexLength() throws SQLException { + return metaData.getMaxIndexLength(); + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return metaData.getMaxSchemaNameLength(); + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return metaData.getMaxProcedureNameLength(); + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return metaData.getMaxCatalogNameLength(); + } + + @Override + public int getMaxRowSize() throws SQLException { + return metaData.getMaxRowSize(); + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return metaData.doesMaxRowSizeIncludeBlobs(); + } + + @Override + public int getMaxStatementLength() throws SQLException { + return metaData.getMaxStatementLength(); + } + + @Override + public int getMaxStatements() throws SQLException { + return metaData.getMaxStatements(); + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return metaData.getMaxTableNameLength(); + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return metaData.getMaxTablesInSelect(); + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return metaData.getMaxUserNameLength(); + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return metaData.getDefaultTransactionIsolation(); + } + + @Override + public boolean supportsTransactions() throws SQLException { + return metaData.supportsTransactions(); + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return metaData.supportsTransactionIsolationLevel(level); + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return metaData.supportsDataDefinitionAndDataManipulationTransactions(); + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return metaData.supportsDataManipulationTransactionsOnly(); + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return metaData.dataDefinitionCausesTransactionCommit(); + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return metaData.dataDefinitionIgnoredInTransactions(); + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { + return metaData.getProcedures(catalog, schemaPattern, procedureNamePattern); + } + + @Override + public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { + return metaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern); + } + + @Override + public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { + return metaData.getTables(catalog, schemaPattern, tableNamePattern, types); + } + + @Override + public ResultSet getSchemas() throws SQLException { + return metaData.getSchemas(); + } + + @Override + public ResultSet getCatalogs() throws SQLException { + return metaData.getCatalogs(); + } + + @Override + public ResultSet getTableTypes() throws SQLException { + return metaData.getTableTypes(); + } + + @Override + public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return metaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + } + + @Override + public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { + return metaData.getColumnPrivileges(catalog, schema, table, columnNamePattern); + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return metaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern); + } + + @Override + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { + return metaData.getBestRowIdentifier(catalog, schema, table, scope, nullable); + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + return metaData.getVersionColumns(catalog, schema, table); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getPrimaryKeys(catalog, schema, table); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getImportedKeys(catalog, schema, table); + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getExportedKeys(catalog, schema, table); + } + + @Override + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { + return metaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable); + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + return metaData.getTypeInfo(); + } + + @Override + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { + return metaData.getIndexInfo(catalog, schema, table, unique, approximate); + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return metaData.supportsResultSetType(type); + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return metaData.supportsResultSetConcurrency(type, concurrency); + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return metaData.ownUpdatesAreVisible(type); + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return metaData.ownDeletesAreVisible(type); + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return metaData.ownInsertsAreVisible(type); + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return metaData.othersUpdatesAreVisible(type); + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return metaData.othersDeletesAreVisible(type); + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return metaData.othersInsertsAreVisible(type); + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return metaData.updatesAreDetected(type); + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return metaData.deletesAreDetected(type); + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return metaData.insertsAreDetected(type); + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return metaData.supportsBatchUpdates(); + } + + @Override + public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { + return metaData.getUDTs(catalog, schemaPattern, typeNamePattern, types); + } + + @Override + public Connection getConnection() throws SQLException { + return metaData.getConnection(); + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return metaData.supportsSavepoints(); + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return metaData.supportsNamedParameters(); + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return metaData.supportsMultipleOpenResults(); + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return metaData.supportsGetGeneratedKeys(); + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { + return metaData.getSuperTypes(catalog, schemaPattern, typeNamePattern); + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return metaData.getSuperTypes(catalog, schemaPattern, tableNamePattern); + } + + @Override + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { + return metaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern); + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return metaData.supportsResultSetHoldability(holdability); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return metaData.getResultSetHoldability(); + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + return metaData.getDatabaseMajorVersion(); + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + return metaData.getDatabaseMinorVersion(); + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return metaData.getJDBCMajorVersion(); + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return metaData.getJDBCMinorVersion(); + } + + @Override + public int getSQLStateType() throws SQLException { + return metaData.getSQLStateType(); + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return metaData.locatorsUpdateCopy(); + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return metaData.supportsStatementPooling(); + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return metaData.getRowIdLifetime(); + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + return metaData.getSchemas(catalog, schemaPattern); + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return metaData.supportsStoredFunctionsUsingCallSyntax(); + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return metaData.autoCommitFailureClosesAllResultSets(); + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return metaData.getClientInfoProperties(); + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { + return metaData.getFunctions(catalog, schemaPattern, functionNamePattern); + } + + @Override + public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { + return metaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern); + } + + public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return metaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + } + + public boolean generatedKeyAlwaysReturned() throws SQLException { + return metaData.generatedKeyAlwaysReturned(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return metaData.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return metaData.isWrapperFor(iface); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLLimit.java b/src/main/java/com/alibaba/druid/sql/ast/SQLLimit.java index 9e25c8fce1..a63cbdba92 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLLimit.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLLimit.java @@ -31,6 +31,11 @@ public class SQLLimit extends SQLObjectImpl { this.setRowCount(rowCount); } + public SQLLimit(SQLExpr offset, SQLExpr rowCount) { + this.setOffset(offset); + this.setRowCount(rowCount); + } + private SQLExpr rowCount; private SQLExpr offset; diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java index 99109e7394..04cdd0ecf8 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOpExpr.java @@ -145,6 +145,10 @@ public class SQLBinaryOpExpr extends SQLExprImpl implements Serializable { return true; } + public SQLBinaryOpExpr clone() { + return new SQLBinaryOpExpr(left, operator, right, dbType); + } + public String toString() { return SQLUtils.toSQLString(this, getDbType()); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntegerExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntegerExpr.java index 0453126318..e78fc793dc 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntegerExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIntegerExpr.java @@ -82,4 +82,8 @@ public class SQLIntegerExpr extends SQLNumericLiteralExpr implements SQLValuable public Object getValue() { return this.number; } + + public SQLIntegerExpr clone() { + return new SQLIntegerExpr(this.number); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLVariantRefExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLVariantRefExpr.java index a31a91ad37..262d5dbbeb 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLVariantRefExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLVariantRefExpr.java @@ -104,4 +104,7 @@ public class SQLVariantRefExpr extends SQLExprImpl { this.global = global; } + public SQLVariantRefExpr clone() { + return new SQLVariantRefExpr(name, global); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRename.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRename.java index 320530a60f..80aa7ae0b8 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRename.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableRename.java @@ -21,15 +21,29 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLAlterTableRename extends SQLObjectImpl implements SQLAlterTableItem { - protected SQLExpr to; + protected SQLExprTableSource to; - public SQLExpr getTo() { + public SQLAlterTableRename() { + + } + + public SQLAlterTableRename(SQLExpr to) { + this.setTo(to); + } + + public SQLExprTableSource getTo() { return to; } - public void setTo(SQLExpr to) { + public void setTo(SQLExprTableSource to) { + if (to != null) { + to.setParent(this); + } this.to = to; - to.setParent(this); + } + + public void setTo(SQLExpr to) { + this.setTo(new SQLExprTableSource(to)); } @Override diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java index dd678cf981..b7071e4981 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableStatement.java @@ -20,9 +20,12 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLStatement { @@ -118,6 +121,10 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt this.tableSource = tableSource; } + public void setTableSource(SQLExpr table) { + this.setTableSource(new SQLExprTableSource(table)); + } + public SQLName getName() { if (getTableSource() == null) { return null; @@ -141,4 +148,18 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt } visitor.endVisit(this); } + + public String getTableName() { + if (tableSource == null) { + return null; + } + SQLExpr expr = ((SQLExprTableSource) tableSource).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + return ((SQLIdentifierExpr) expr).getName(); + } else if (expr instanceof SQLPropertyExpr) { + return ((SQLPropertyExpr) expr).getName(); + } + + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java index a9aeea79de..e57fc5c923 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java @@ -22,6 +22,8 @@ import com.alibaba.druid.sql.ast.SQLDataType; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement { @@ -259,4 +261,24 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen } } + + public String computeAlias() { + String alias = null; + + if (name instanceof SQLIdentifierExpr) { + alias = ((SQLIdentifierExpr) name).getName(); + } else if (name instanceof SQLPropertyExpr) { + alias = ((SQLPropertyExpr) name).getName(); + } + + if (alias.length() > 2) { + char c0 = alias.charAt(0); + char x0 = alias.charAt(alias.length() - 1); + if ((c0 == '"' && x0 == '"') || (c0 == '`' && x0 == '`')) { + alias = alias.substring(1, alias.length() - 1); + } + } + + return alias; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java index e0d7f0835b..cdcad4d1d6 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java @@ -18,8 +18,11 @@ package com.alibaba.druid.sql.ast.statement; import java.util.ArrayList; import java.util.List; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLStatement { @@ -55,6 +58,19 @@ public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLS this.table = table; } + public String getTableName() { + if (table instanceof SQLExprTableSource) { + SQLExpr expr = ((SQLExprTableSource) table).getExpr(); + if (expr instanceof SQLIdentifierExpr) { + return ((SQLIdentifierExpr) expr).getName(); + } else if (expr instanceof SQLPropertyExpr) { + return ((SQLPropertyExpr) expr).getName(); + } + } + + return null; + } + public List getItems() { return items; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSequenceStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSequenceStatement.java index 4c0b8e7854..e0167db33d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSequenceStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropSequenceStatement.java @@ -22,6 +22,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLDropSequenceStatement extends SQLStatementImpl implements SQLDDLStatement { private SQLName name; + private boolean ifExists; public SQLDropSequenceStatement() { @@ -47,4 +48,11 @@ public class SQLDropSequenceStatement extends SQLStatementImpl implements SQLDDL this.name = name; } + public boolean isIfExists() { + return ifExists; + } + + public void setIfExists(boolean ifExists) { + this.ifExists = ifExists; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTriggerStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTriggerStatement.java index 9a4996c348..ef0468cf20 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTriggerStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDropTriggerStatement.java @@ -22,7 +22,8 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLDropTriggerStatement extends SQLStatementImpl implements SQLDDLStatement { private SQLName name; - + private boolean ifExists; + public SQLDropTriggerStatement() { } @@ -47,4 +48,11 @@ public class SQLDropTriggerStatement extends SQLStatementImpl implements SQLDDLS visitor.endVisit(this); } + public boolean isIfExists() { + return ifExists; + } + + public void setIfExists(boolean ifExists) { + this.ifExists = ifExists; + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java index 32ebb65616..de29dce6ad 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLIfStatement.java @@ -47,6 +47,9 @@ public class SQLIfStatement extends SQLStatementImpl { } public void setCondition(SQLExpr condition) { + if (condition != null) { + condition.setParent(this); + } this.condition = condition; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java index ccc9a118e4..14e84958df 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLLoopStatement.java @@ -26,7 +26,7 @@ public class SQLLoopStatement extends SQLStatementImpl { private String labelName; - private List statements = new ArrayList(); + private final List statements = new ArrayList(); @Override public void accept0(SQLASTVisitor visitor) { @@ -40,10 +40,6 @@ public class SQLLoopStatement extends SQLStatementImpl { return statements; } - public void setStatements(List statements) { - this.statements = statements; - } - public String getLabelName() { return labelName; } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java index 4529c92336..8ff987b673 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectItem.java @@ -17,6 +17,8 @@ package com.alibaba.druid.sql.ast.statement; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLObjectImpl; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLSelectItem extends SQLObjectImpl { @@ -63,6 +65,27 @@ public class SQLSelectItem extends SQLObjectImpl { } } + public String computeAlias() { + String alias = this.getAlias(); + if (alias == null) { + if (expr instanceof SQLIdentifierExpr) { + alias = ((SQLIdentifierExpr) expr).getName(); + } else if (expr instanceof SQLPropertyExpr) { + alias = ((SQLPropertyExpr) expr).getName(); + } + } + + if (alias.length() > 2) { + char c0 = alias.charAt(0); + char x0 = alias.charAt(alias.length() - 1); + if ((c0 == '"' && x0 == '"') || (c0 == '`' && x0 == '`')) { + alias = alias.substring(1, alias.length() - 1); + } + } + + return alias; + } + public String getAlias() { return this.alias; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index a731a7a8e6..3e38491c76 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -395,9 +395,7 @@ public class MySqlStatementParser extends SQLStatementParser { } if (lexer.token() == Token.TRIGGER) { - if (replace) { - lexer.reset(markBp, markChar, Token.CREATE); - } + lexer.reset(markBp, markChar, Token.CREATE); return parseCreateTrigger(); } // parse create procedure @@ -3011,18 +3009,24 @@ public class MySqlStatementParser extends SQLStatementParser { item.addColumn(name); while (lexer.token() == Token.COMMA) { - lexer.mark(); + char markChar = lexer.current(); + int markBp = lexer.bp(); + lexer.nextToken(); if (identifierEquals("CHANGE")) { - lexer.reset(); + lexer.reset(markBp, markChar, Token.COMMA); break; } if (lexer.token() == Token.IDENTIFIER) { + if ("ADD".equalsIgnoreCase(lexer.stringVal())) { + lexer.reset(markBp, markChar, Token.COMMA); + break; + } name = exprParser.name(); name.setParent(item); } else { - lexer.reset(); + lexer.reset(markBp, markChar, Token.COMMA); break; } } @@ -3561,6 +3565,7 @@ public class MySqlStatementParser extends SQLStatementParser { accept(Token.END); accept(Token.IF); accept(Token.SEMI); + stmt.setAfterSemi(true); return stmt; } @@ -3770,6 +3775,7 @@ public class MySqlStatementParser extends SQLStatementParser { accept(Token.END); accept(Token.LOOP); accept(Token.SEMI); + loopStmt.setAfterSemi(true); return loopStmt; } @@ -3787,6 +3793,7 @@ public class MySqlStatementParser extends SQLStatementParser { acceptIdentifier(label); } accept(Token.SEMI); + loopStmt.setAfterSemi(true); return loopStmt; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 0551d8074d..99077d4079 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -15,14 +15,7 @@ */ package com.alibaba.druid.sql.dialect.mysql.visitor; -import com.alibaba.druid.sql.ast.SQLCommentHint; -import com.alibaba.druid.sql.ast.SQLDataType; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLObject; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLParameter; -import com.alibaba.druid.sql.ast.SQLSetQuantifier; -import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -380,12 +373,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } public boolean visit(SQLDataType x) { - print0(x.getName()); - if (!x.getArguments().isEmpty()) { - print('('); - printAndAccept(x.getArguments(), ", "); - print(')'); - } + printDataType(x); if (Boolean.TRUE == x.getAttribute("UNSIGNED")) { print0(ucase ? " UNSIGNED" : " unsigned"); @@ -3284,6 +3272,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public boolean visit(SQLIfStatement.Else x) { print0(ucase ? "ELSE " : "else "); + incrementIndent(); println(); for (int i = 0, size = x.getStatements().size(); i < size; ++i) { SQLStatement item = x.getStatements().get(i); @@ -3293,6 +3282,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV println(); } } + decrementIndent(); println(); return false; } @@ -3617,4 +3607,24 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public void endVisit(MySqlDeclareConditionStatement x) { } + + @Override + public boolean visit(SQLAlterTableDropColumnItem x) { + + for (int i = 0; i < x.getColumns().size(); ++i) { + if (i != 0) { + print0(", "); + } + + SQLName columnn = x.getColumns().get(i); + + print0(ucase ? "DROP COLUMN " : "drop column "); + columnn.accept(this); + + if (x.isCascade()) { + print0(ucase ? " CASCADE" : " cascade"); + } + } + return false; + } } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConntinueStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleContinueStatement.java similarity index 79% rename from src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConntinueStatement.java rename to src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleContinueStatement.java index f37a92b2a0..cadcf58085 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleConntinueStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleContinueStatement.java @@ -19,10 +19,10 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; -public class OracleConntinueStatement extends OracleStatementImpl { +public class OracleContinueStatement extends OracleStatementImpl { private SQLExpr when; - private SQLName label; + private String label; public SQLExpr getWhen() { return when; @@ -35,21 +35,17 @@ public class OracleConntinueStatement extends OracleStatementImpl { this.when = when; } - public SQLName getLabel() { + public String getLabel() { return label; } - public void setLabel(SQLName label) { - if (label != null) { - label.setParent(this); - } + public void setLabel(String label) { this.label = label; } @Override public void accept0(OracleASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, label); acceptChild(visitor, when); } visitor.endVisit(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExecuteImmediateStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExecuteImmediateStatement.java new file mode 100644 index 0000000000..cad9ae40a9 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExecuteImmediateStatement.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.dialect.oracle.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; + +public class OracleExecuteImmediateStatement extends OracleStatementImpl { + + private SQLCharExpr dynamicSql; + + public OracleExecuteImmediateStatement(){ + } + + public OracleExecuteImmediateStatement(String dynamicSql){ + this.setDynamicSql(dynamicSql); + } + + @Override + public void accept0(OracleASTVisitor visitor) { + if (visitor.visit(this)) { +// acceptChild(visitor, label); + } + visitor.endVisit(this); + } + + public SQLCharExpr getDynamicSql() { + return dynamicSql; + } + + public void setDynamicSql(SQLCharExpr dynamicSql) { + if (dynamicSql != null) { + dynamicSql.setParent(this); + } + this.dynamicSql = dynamicSql; + } + + public void setDynamicSql(String dynamicSql) { + this.setDynamicSql(new SQLCharExpr(dynamicSql)); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExitStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExitStatement.java index 683b1cc46d..6671fca1fd 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExitStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleExitStatement.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; public class OracleExitStatement extends OracleStatementImpl { + private String label; private SQLExpr when; @@ -41,4 +42,11 @@ public class OracleExitStatement extends OracleStatementImpl { visitor.endVisit(this); } + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java index 5309103c87..0ea6a24094 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OracleLockTableStatement.java @@ -17,11 +17,12 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; public class OracleLockTableStatement extends OracleStatementImpl { - private SQLName table; + private SQLExprTableSource table; private LockMode lockMode; private boolean noWait = false; private SQLExpr wait; @@ -42,14 +43,22 @@ public class OracleLockTableStatement extends OracleStatementImpl { this.wait = wait; } - public SQLName getTable() { + public SQLExprTableSource getTable() { return table; } - public void setTable(SQLName table) { + public void setTable(SQLExprTableSource table) { + if (table != null) { + table.setParent(this); + } this.table = table; } + public void setTable(SQLName table) { + this.setTable(new SQLExprTableSource(table)); + this.table.setParent(this); + } + public LockMode getLockMode() { return lockMode; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index b8e7027f33..1a091551a3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -217,11 +217,7 @@ public class OracleStatementParser extends SQLStatementParser { if (identifierEquals("EXIT")) { lexer.nextToken(); - OracleExitStatement stmt = new OracleExitStatement(); - if (lexer.token() == Token.WHEN) { - lexer.nextToken(); - stmt.setWhen(this.exprParser.expr()); - } + OracleExitStatement stmt = parseExit(); stmt.setParent(parent); statementList.add(stmt); continue; @@ -229,10 +225,11 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.CONTINUE) { lexer.nextToken(); - OracleConntinueStatement stmt = new OracleConntinueStatement(); + OracleContinueStatement stmt = new OracleContinueStatement(); if (lexer.token() == Token.IDENTIFIER) { - SQLName label = this.exprParser.name(); + String label = lexer.stringVal(); + lexer.nextToken(); stmt.setLabel(label); } if (lexer.token() == Token.WHEN) { @@ -268,17 +265,52 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.IDENTIFIER) { String strVal = lexer.stringVal(); if (strVal.equalsIgnoreCase("RAISE")) { - statementList.add(this.parseRaise()); + SQLStatement stmt = this.parseRaise(); + stmt.setParent(parent); + statementList.add(stmt); continue; } if (strVal.equalsIgnoreCase("FORALL")) { - SQLStatement forAll = this.parseFor(); - statementList.add(forAll); + SQLStatement stmt = this.parseFor(); + stmt.setParent(parent); + statementList.add(stmt); + continue; + } + + if (strVal.equalsIgnoreCase("RENAME")) { + SQLStatement stmt = this.parseRename(); + stmt.setParent(parent); + statementList.add(stmt); + continue; + } + + if (strVal.equalsIgnoreCase("EXECUTE")) { + SQLStatement stmt = this.parseExecute(); + stmt.setParent(parent); + statementList.add(stmt); continue; } SQLExpr expr = exprParser.expr(); + + if (expr instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) expr; + if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) { + SQLSetStatement stmt = new SQLSetStatement(); + stmt.setDbType(JdbcConstants.ORACLE); + stmt.setParent(parent); + + SQLAssignItem assignItem = new SQLAssignItem(binaryOpExpr.getLeft(), binaryOpExpr.getRight()); + assignItem.setParent(stmt); + stmt.getItems().add(assignItem); + + statementList.add(stmt); + + continue; + } + } + OracleExprStatement stmt = new OracleExprStatement(expr); stmt.setParent(parent); statementList.add(stmt); @@ -584,6 +616,53 @@ public class OracleStatementParser extends SQLStatementParser { } } + public SQLStatement parseExecute() { + acceptIdentifier("EXECUTE"); + + if (lexer.token() == Token.IMMEDIATE) { + lexer.nextToken(); + + OracleExecuteImmediateStatement stmt = new OracleExecuteImmediateStatement(); + String dyanmiacSql = lexer.stringVal(); + accept(Token.LITERAL_CHARS); + stmt.setDynamicSql(dyanmiacSql); + return stmt; + } + throw new ParserException("TODO : " + lexer.info()); + } + + public SQLStatement parseRename() { + lexer.nextToken(); + SQLName from = this.exprParser.name(); + accept(Token.TO); + SQLName to = this.exprParser.name(); + + SQLAlterTableStatement stmt = new SQLAlterTableStatement(); + stmt.setTableSource(from); + SQLAlterTableRename toItem = new SQLAlterTableRename(to); + stmt.addItem(toItem); + + return stmt; + } + + private OracleExitStatement parseExit() { + OracleExitStatement stmt = new OracleExitStatement(); + + if (lexer.token() == Token.IDENTIFIER) { + String label = lexer.stringVal(); + stmt.setLabel(label); + lexer.nextToken(); + } + + if (lexer.token() == Token.WHEN) { + lexer.nextToken(); + stmt.setWhen(this.exprParser.expr()); + } + accept(Token.SEMI); + stmt.setAfterSemi(true); + return stmt; + } + public SQLStatement parseReturn() { accept(Token.RETURN); SQLReturnStatement stmt = new SQLReturnStatement(); @@ -790,6 +869,7 @@ public class OracleStatementParser extends SQLStatementParser { // lexer.nextToken(); // } accept(Token.SEMI); + stmt.setAfterSemi(true); return stmt; } @@ -838,6 +918,15 @@ public class OracleStatementParser extends SQLStatementParser { this.parseStatementList(stmt.getStatements(), -1, stmt); accept(Token.END); accept(Token.LOOP); + + if (lexer.token() == Token.IDENTIFIER) { + String label = lexer.stringVal(); + stmt.setLabelName(label); + lexer.nextToken(); + } + + accept(Token.SEMI); + stmt.setAfterSemi(true); return stmt; } @@ -2034,8 +2123,10 @@ public class OracleStatementParser extends SQLStatementParser { varDecl.getItems().add(varItem); - stmt.getStatements().add(varDecl); accept(Token.SEMI); + varDecl.setAfterSemi(true); + + stmt.getStatements().add(varDecl); } else if (lexer.token() == Token.FUNCTION) { SQLStatement function = this.parseFunction(); function.setParent(stmt); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index 153a6e5e98..8fee04aec7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -389,9 +389,9 @@ public interface OracleASTVisitor extends SQLASTVisitor { void endVisit(OracleExitStatement x); - boolean visit(OracleConntinueStatement x); + boolean visit(OracleContinueStatement x); - void endVisit(OracleConntinueStatement x); + void endVisit(OracleContinueStatement x); boolean visit(OracleRaiseStatement x); @@ -460,4 +460,8 @@ public interface OracleASTVisitor extends SQLASTVisitor { boolean visit(OracleCreatePackageStatement x); void endVisit(OracleCreatePackageStatement x); + + boolean visit(OracleExecuteImmediateStatement x); + + void endVisit(OracleExecuteImmediateStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index db8cc11abb..fcf9116498 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -938,12 +938,12 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } @Override - public boolean visit(OracleConntinueStatement x) { + public boolean visit(OracleContinueStatement x) { return true; } @Override - public void endVisit(OracleConntinueStatement x) { + public void endVisit(OracleContinueStatement x) { } @@ -1109,4 +1109,14 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora public void endVisit(OracleCreatePackageStatement x) { } + + @Override + public boolean visit(OracleExecuteImmediateStatement x) { + return true; + } + + @Override + public void endVisit(OracleExecuteImmediateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 0a5bd7e152..a87837e2f2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -28,7 +28,6 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; -import com.alibaba.druid.sql.dialect.oracle.ast.OracleSegmentAttributes; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfFlashbackQueryClause; import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause.AsOfSnapshotClause; @@ -1469,7 +1468,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS if (x.getStatements().size() > 1) { println(); } else { - print(' '); + if (x.getStatements().size() == 1 + && x.getStatements().get(0) instanceof SQLIfStatement) { + println(); + } else { + print(' '); + } } for (int i = 0, size = x.getStatements().size(); i < size; ++i) { @@ -1594,6 +1598,19 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(SQLAlterTableStatement x) { + if (x.getItems().size() == 1) { + SQLAlterTableItem item = x.getItems().get(0); + if (item instanceof SQLAlterTableRename) { + SQLExpr to = ((SQLAlterTableRename) item).getTo().getExpr(); + + print0(ucase ? "RENAME " : "rename "); + x.getName().accept(this); + print0(ucase ? " TO " : "to "); + to.accept(this); + return false; + } + } + print0(ucase ? "ALTER TABLE " : "alter table "); printTableSourceExpr(x.getName()); incrementIndent(); @@ -1958,7 +1975,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS x.getElseItem().accept(this); } println(); - print0(ucase ? "END IF;" : "end if;"); + print0(ucase ? "END IF" : "end if"); return false; } @@ -2043,7 +2060,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleCreateTableStatement x) { - this.visit((SQLCreateTableStatement) x); + printCreateTable(x); if (x.getOf() != null) { println(); @@ -2431,6 +2448,12 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override public boolean visit(OracleExitStatement x) { print0(ucase ? "EXIT" : "exit"); + + if (x.getLabel() != null) { + print(' '); + print0(x.getLabel()); + } + if (x.getWhen() != null) { print0(ucase ? " WHEN " : " when "); x.getWhen().accept(this); @@ -2445,13 +2468,13 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS @Override - public boolean visit(OracleConntinueStatement x) { + public boolean visit(OracleContinueStatement x) { print0(ucase ? "CONTINUE" : "continue"); - SQLName label = x.getLabel(); + String label = x.getLabel(); if (label != null) { print(' '); - label.accept(this); + print0(label); } if (x.getWhen() != null) { @@ -2462,7 +2485,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } @Override - public void endVisit(OracleConntinueStatement x) { + public void endVisit(OracleContinueStatement x) { } @@ -3189,4 +3212,25 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OracleCreatePackageStatement x) { } + + @Override + public boolean visit(SQLAssignItem x) { + x.getTarget().accept(this); + print0(" := "); + x.getValue().accept(this); + return false; + } + + + @Override + public boolean visit(OracleExecuteImmediateStatement x) { + print0(ucase ? "EXECUTE IMMEDIATE " : "execute immediate "); + x.getDynamicSql().accept(this); + return false; + } + + @Override + public void endVisit(OracleExecuteImmediateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 703227a564..3b11d1befc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -19,9 +19,11 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObject; +import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; @@ -84,6 +86,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement. import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot.Item; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.CheckOption; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction.ReadOnly; +import com.alibaba.druid.sql.parser.SQLParserUtils; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; @@ -1271,12 +1274,12 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } @Override - public boolean visit(OracleConntinueStatement x) { + public boolean visit(OracleContinueStatement x) { return false; } @Override - public void endVisit(OracleConntinueStatement x) { + public void endVisit(OracleContinueStatement x) { } @@ -1447,4 +1450,20 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public void endVisit(OracleCreatePackageStatement x) { } + + @Override + public boolean visit(OracleExecuteImmediateStatement x) { + String sql = x.getDynamicSql().getText(); + + List stmtList = SQLUtils.parseStatements(sql, getDbType()); + for (SQLStatement stmt : stmtList) { + stmt.accept(this); + } + return false; + } + + @Override + public void endVisit(OracleExecuteImmediateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 21c888731b..540aff4328 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1904,8 +1904,11 @@ public class SQLExprParser extends SQLParser { SQLColumnDefinition column = createColumnDefinition(); column.setName(name()); - if (lexer.token() != Token.SET // - && lexer.token() != Token.DROP) { + final Token token = lexer.token(); + if (token != Token.SET // + && token != Token.DROP + && token != Token.PRIMARY + && token != Token.RPAREN) { column.setDataType(parseDataType()); } return parseColumnRest(column); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 20fd6d9566..dc58530f8c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -1700,6 +1700,11 @@ public class SQLStatementParser extends SQLParser { return parseCreateView(); } + if (lexer.token() == Token.TRIGGER) { + lexer.reset(markBp, markChar, Token.CREATE); + return parseCreateTrigger(); + } + if (identifierEquals("PACKAGE")) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreatePackage(); @@ -1722,6 +1727,7 @@ public class SQLStatementParser extends SQLParser { } else if (token == Token.VIEW) { return parseCreateView(); } else if (token == Token.TRIGGER) { + lexer.reset(markBp, markChar, Token.CREATE); return parseCreateTrigger(); } else if (token == Token.PROCEDURE) { SQLCreateProcedureStatement stmt = parseCreateProcedure(); @@ -1737,9 +1743,20 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseCreateTrigger() { - accept(Token.TRIGGER); + accept(Token.CREATE); SQLCreateTriggerStatement stmt = new SQLCreateTriggerStatement(getDbType()); + + if (lexer.token() == Token.OR) { + lexer.nextToken(); + accept(Token.REPLACE); + + stmt.setOrReplace(true); + } + + accept(Token.TRIGGER); + + stmt.setName(this.exprParser.name()); if (identifierEquals("BEFORE")) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 31a1422848..1064a0f3dc 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1159,6 +1159,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet printSelectList(x.getSelectList()); + if (x.getInto() != null) { + println(); + print0(ucase ? "INTO " : "into "); + x.getInto().accept(this); + } + if (x.getFrom() != null) { println(); print0(ucase ? "FROM " : "from "); @@ -1751,6 +1757,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } public boolean visit(SQLCreateTableStatement x) { + printCreateTable(x); + + return false; + } + + protected void printCreateTable(SQLCreateTableStatement x) { print0(ucase ? "CREATE TABLE " : "create table "); if (SQLCreateTableStatement.Type.GLOBAL_TEMPORARY.equals(x.getType())) { print0(ucase ? "GLOBAL TEMPORARY " : "global temporary "); @@ -1767,8 +1779,6 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet x.getInherits().accept(this); print(')'); } - - return false; } public boolean visit(SQLUniqueConstraint x) { @@ -1912,7 +1922,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLSetStatement x) { - print0(ucase ? "SET " : "set "); + if (!JdbcConstants.ORACLE.equals(dbType)) { + print0(ucase ? "SET " : "set "); + } printAndAccept(x.getItems(), ", "); if (x.getHints() != null && x.getHints().size() > 0) { @@ -2749,6 +2761,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLDropSequenceStatement x) { print0(ucase ? "DROP SEQUENCE " : "drop sequence "); + if (x.isIfExists()) { + print0(ucase ? "IF EXISTS " : "if exists "); + } x.getName().accept(this); return false; } @@ -2761,6 +2776,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet @Override public boolean visit(SQLDropTriggerStatement x) { print0(ucase ? "DROP TRIGGER " : "drop trigger "); + if (x.isIfExists()) { + print0(ucase ? "IF EXISTS " : "if exists "); + } + x.getName().accept(this); return false; } @@ -3406,6 +3425,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet decrementIndent(); println(); print0(ucase ? "END LOOP" : "end loop"); + if (x.getLabelName() != null) { + print(' '); + print0(x.getLabelName()); + } return false; } @@ -3469,15 +3492,19 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet dataType.accept(this); - if (x.getDefaultValue() != null) { - print0(" := "); - x.getDefaultValue().accept(this); - } + printParamDefaultValue(x); } return false; } + protected void printParamDefaultValue(SQLParameter x) { + if (x.getDefaultValue() != null) { + print0(" := "); + x.getDefaultValue().accept(this); + } + } + @Override public boolean visit(SQLDeclareItem x) { x.getName().accept(this); diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index 4727fe6a5f..b8bf03820f 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -34,7 +34,7 @@ import com.alibaba.druid.proxy.jdbc.StatementExecuteType; import com.alibaba.druid.util.JMXUtils; import com.alibaba.druid.util.Utils; -public final class JdbcSqlStat implements JdbcSqlStatMBean { +public final class JdbcSqlStat implements JdbcSqlStatMBean, Comparable { private final String sql; private long sqlHash; @@ -1074,4 +1074,12 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { this.removed = removed; } + @Override + public int compareTo(JdbcSqlStat o) { + if (o.sqlHash == this.sqlHash) { + return 0; + } + + return this.id < o.id ? -1 : 1; + } } diff --git a/src/main/java/com/alibaba/druid/util/DruidWebUtils.java b/src/main/java/com/alibaba/druid/util/DruidWebUtils.java index 53f28266e9..76481a438c 100644 --- a/src/main/java/com/alibaba/druid/util/DruidWebUtils.java +++ b/src/main/java/com/alibaba/druid/util/DruidWebUtils.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.util; +import javax.servlet.GenericServlet; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -57,4 +58,13 @@ public class DruidWebUtils { } } + public static Boolean getBoolean(GenericServlet servlet, String key) { + String property = servlet.getInitParameter(key); + if ("true".equals(property)) { + return Boolean.TRUE; + } else if ("false".equals(property)) { + return Boolean.FALSE; + } + return null; + } } diff --git a/src/main/java/com/alibaba/druid/util/Utils.java b/src/main/java/com/alibaba/druid/util/Utils.java index bf313eaf48..ac77fd45e7 100644 --- a/src/main/java/com/alibaba/druid/util/Utils.java +++ b/src/main/java/com/alibaba/druid/util/Utils.java @@ -173,16 +173,6 @@ public class Utils { return null; } - public static Boolean getBoolean(GenericServlet servlet, String key) { - String property = servlet.getInitParameter(key); - if ("true".equals(property)) { - return Boolean.TRUE; - } else if ("false".equals(property)) { - return Boolean.FALSE; - } - return null; - } - public static Integer getInteger(Properties properties, String key) { String property = properties.getProperty(key); diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest146.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest146.java new file mode 100644 index 0000000000..69d610c537 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/mysql/MySqlWallTest146.java @@ -0,0 +1,26 @@ +package com.alibaba.druid.bvt.filter.wall.mysql; + +import com.alibaba.druid.wall.WallProvider; +import com.alibaba.druid.wall.spi.MySqlWallProvider; +import junit.framework.TestCase; +import org.junit.Assert; + +public class MySqlWallTest146 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + + String sql = "ALTER TABLE project_measures\n" + + " DROP COLUMN diff_value_1,\n" + + " DROP COLUMN diff_value_2,\n" + + " DROP COLUMN diff_value_3,\n" + + " ADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL"; + Assert.assertTrue( + provider.checkValid(sql) + ); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest28.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest28.java new file mode 100644 index 0000000000..12252c6e0a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest28.java @@ -0,0 +1,41 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql.alter; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.parser.Token; +import junit.framework.TestCase; +import org.junit.Assert; + +public class MySqlAlterTableTest28 extends TestCase { + + public void test_alter_add_key() throws Exception { + String sql = "ALTER TABLE project_measures MODIFY COLUMN value DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_1 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_2 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_3 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_4 DECIMAL (38,20) NULL, MODIFY COLUMN variation_value_5 DECIMAL (38,20) NULL"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE project_measures\n" + + "\tMODIFY COLUMN value DECIMAL(38, 20) NULL,\n" + + "\tMODIFY COLUMN variation_value_1 DECIMAL(38, 20) NULL,\n" + + "\tMODIFY COLUMN variation_value_2 DECIMAL(38, 20) NULL,\n" + + "\tMODIFY COLUMN variation_value_3 DECIMAL(38, 20) NULL,\n" + + "\tMODIFY COLUMN variation_value_4 DECIMAL(38, 20) NULL,\n" + + "\tMODIFY COLUMN variation_value_5 DECIMAL(38, 20) NULL", output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest29.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest29.java new file mode 100644 index 0000000000..ca1f19c296 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/alter/MySqlAlterTableTest29.java @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql.alter; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.parser.Token; +import junit.framework.TestCase; +import org.junit.Assert; + +public class MySqlAlterTableTest29 extends TestCase { + + public void test_alter_add_key() throws Exception { + String sql = "alter TABLE project_measures\n" + + " DROP COLUMN diff_value_1,\n" + + " DROP COLUMN diff_value_2,\n" + + " DROP COLUMN diff_value_3,\n" + + " ADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + " ADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE project_measures\n" + + "\tDROP COLUMN diff_value_1,\n" + + "\tDROP COLUMN diff_value_2,\n" + + "\tDROP COLUMN diff_value_3,\n" + + "\tADD COLUMN variation_value_1 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + "\tADD COLUMN variation_value_2 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + "\tADD COLUMN variation_value_3 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + "\tADD COLUMN variation_value_4 DECIMAL(30, 20) NULL DEFAULT NULL,\n" + + "\tADD COLUMN variation_value_5 DECIMAL(30, 20) NULL DEFAULT NULL", output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTableTest24.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTableTest24.java new file mode 100644 index 0000000000..3c8bcd1b64 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/alter/OracleAlterTableTest24.java @@ -0,0 +1,63 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.alter; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleAlterTableTest24 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "RENAME new_duplications_index TO duplications_index"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals("RENAME new_duplications_index TO duplications_index", // + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + Assert.assertEquals(1, visitor.getTables().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("new_duplications_index"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); +// Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "commission_pct"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest16.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest16.java new file mode 100644 index 0000000000..d5b653d33e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest16.java @@ -0,0 +1,99 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.block; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleBlockTest16 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DECLARE\n" + + " s PLS_INTEGER := 0;\n" + + " i PLS_INTEGER := 0;\n" + + " j PLS_INTEGER;\n" + + "BEGIN\n" + + " <>\n" + + " LOOP\n" + + " i := i + 1;\n" + + " j := 0;\n" + + " <>\n" + + " LOOP\n" + + " j := j + 1;\n" + + " s := s + i * j; -- Sum several products\n" + + " EXIT inner_loop WHEN (j > 5);\n" + + " EXIT outer_loop WHEN ((i * j) > 15);\n" + + " END LOOP inner_loop;\n" + + " END LOOP outer_loop;\n" + + " DBMS_OUTPUT.PUT_LINE\n" + + " ('The sum of products equals: ' || TO_CHAR(s));\n" + + "END;"; // + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, stmtList.size()); + + String result = SQLUtils.toOracleString(stmtList.get(0)); + System.out.println(result); + assertEquals("DECLARE\n" + + "\ts PLS_INTEGER := 0;\n" + + "\ti PLS_INTEGER := 0;\n" + + "\tj PLS_INTEGER;\n" + + "BEGIN\n" + + "\t<>\n" + + "\tLOOP\n" + + "\t\ti := i + 1;\n" + + "\t\tj := 0;\n" + + "\t\t<>\n" + + "\t\tLOOP\n" + + "\t\t\tj := j + 1;\n" + + "\t\t\ts := s + i * j;\n" + + "\t\t\tEXIT inner_loop WHEN j > 5;\n" + + "\t\t\tEXIT outer_loop WHEN i * j > 15;\n" + + "\t\tEND LOOP inner_loop;\n" + + "\tEND LOOP outer_loop;\n" + + "\tDBMS_OUTPUT.PUT_LINE('The sum of products equals: ' || TO_CHAR(s));\n" + + "END;", result); + + assertEquals(1, stmtList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + for (SQLStatement statement : stmtList) { + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + + assertEquals(0, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + assertEquals(0, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest17.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest17.java new file mode 100644 index 0000000000..cf9b46bed8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest17.java @@ -0,0 +1,89 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.block; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleBlockTest17 extends OracleTest { + + public void test_0() throws Exception { + String sql = "DECLARE\n" + + " x NUMBER := 0;\n" + + "BEGIN\n" + + " LOOP -- After CONTINUE statement, control resumes here\n" + + " DBMS_OUTPUT.PUT_LINE ('Inside loop: x = ' || TO_CHAR(x));\n" + + " x := x + 1;\n" + + " IF x < 3 THEN\n" + + " CONTINUE;\n" + + " END IF;\n" + + " DBMS_OUTPUT.PUT_LINE\n" + + " ('Inside loop, after CONTINUE: x = ' || TO_CHAR(x));\n" + + " EXIT WHEN x = 5;\n" + + " END LOOP;\n" + + " \n" + + " DBMS_OUTPUT.PUT_LINE (' After loop: x = ' || TO_CHAR(x));\n" + + "END;"; // + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, stmtList.size()); + + String result = SQLUtils.toOracleString(stmtList.get(0)); + System.out.println(result); + assertEquals("DECLARE\n" + + "\tx NUMBER := 0;\n" + + "BEGIN\n" + + "\tLOOP\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Inside loop: x = ' || TO_CHAR(x));\n" + + "\t\tx := x + 1;\n" + + "\t\tIF x < 3 THEN\n" + + "\t\t\tCONTINUE;\n" + + "\t\tEND IF;\n" + + "\t\tDBMS_OUTPUT.PUT_LINE('Inside loop, after CONTINUE: x = ' || TO_CHAR(x));\n" + + "\t\tEXIT WHEN x = 5;\n" + + "\tEND LOOP;\n" + + "\tDBMS_OUTPUT.PUT_LINE(' After loop: x = ' || TO_CHAR(x));\n" + + "END;", result); + + assertEquals(1, stmtList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + for (SQLStatement statement : stmtList) { + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + + assertEquals(0, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + assertEquals(0, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest18.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest18.java new file mode 100644 index 0000000000..16139a46d1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest18.java @@ -0,0 +1,98 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.block; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleBlockTest18 extends OracleTest { + + public void test_0() throws Exception { + String sql = "CREATE PROCEDURE p (\n" + + " sales NUMBER,\n" + + " quota NUMBER,\n" + + " emp_id NUMBER\n" + + " )\n" + + " IS\n" + + " bonus NUMBER := 0;\n" + + " BEGIN\n" + + " IF sales > (quota + 200) THEN\n" + + " bonus := (sales - quota)/4;\n" + + " ELSE\n" + + " bonus := 50;\n" + + " END IF;\n" + + " \n" + + " DBMS_OUTPUT.PUT_LINE('bonus = ' || bonus);\n" + + " \n" + + " UPDATE employees\n" + + " SET salary = salary + bonus \n" + + " WHERE employee_id = emp_id;\n" + + " END p;"; // + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, stmtList.size()); + + String result = SQLUtils.toOracleString(stmtList.get(0)); + System.out.println(result); + assertEquals("CREATE PROCEDURE p (\n" + + "\tsales NUMBER, \n" + + "\tquota NUMBER, \n" + + "\temp_id NUMBER\n" + + ")\n" + + "AS\n" + + "\tbonus NUMBER := 0;\n" + + "BEGIN\n" + + "\tIF sales > quota + 200 THEN\n" + + "\t\tbonus := (sales - quota) / 4;\n" + + "\tELSE\n" + + "\t\tbonus := 50;\n" + + "\tEND IF;\n" + + "\tDBMS_OUTPUT.PUT_LINE('bonus = ' || bonus);\n" + + "\tUPDATE employees\n" + + "\tSET salary = salary + bonus\n" + + "\tWHERE employee_id = emp_id;\n" + + "END;", result); + + assertEquals(1, stmtList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + for (SQLStatement statement : stmtList) { + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(1, visitor.getTables().size()); + + assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + + assertEquals(5, visitor.getColumns().size()); + assertEquals(3, visitor.getConditions().size()); + assertEquals(1, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest19.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest19.java new file mode 100644 index 0000000000..21bd4929d2 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/block/OracleBlockTest19.java @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.block; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class OracleBlockTest19 extends OracleTest { + + public void test_0() throws Exception { + String sql = "BEGIN\n" + + " EXECUTE IMMEDIATE 'DROP SEQUENCE properties_seq';\n" + + "EXCEPTION\n" + + " WHEN OTHERS THEN\n" + + " IF SQLCODE != -2289 THEN\n" + + " RAISE;\n" + + " END IF;\n" + + "END;"; // + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.ORACLE); + assertEquals(1, stmtList.size()); + + String result = SQLUtils.toOracleString(stmtList.get(0)); + System.out.println(result); + assertEquals("BEGIN\n" + + "\tEXECUTE IMMEDIATE 'DROP SEQUENCE properties_seq';\n" + + "EXCEPTION\n" + + "\tWHEN OTHERS THEN\n" + + "\t\tIF SQLCODE != -2289 THEN\n" + + "\t\t\tRAISE;\n" + + "\t\tEND IF;\n" + + "END;", result); + + assertEquals(1, stmtList.size()); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + for (SQLStatement statement : stmtList) { + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + assertEquals(0, visitor.getTables().size()); + +// assertTrue(visitor.getTables().containsKey(new TableStat.Name("employees"))); + +// assertEquals(5, visitor.getColumns().size()); +// assertEquals(0, visitor.getConditions().size()); + assertEquals(0, visitor.getRelationships().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("employees", "salary"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java index de1f46dbcd..14b1c4469c 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreatePackageTest0.java @@ -112,8 +112,8 @@ public class OracleCreatePackageTest0 extends OracleTest { Assert.assertEquals("CREATE OR REPLACE PACKAGE BODY emp_mgmt\n" + "BEGIN\n" + - "\ttot_emps NUMBER\n" + - "\ttot_depts NUMBER\n" + + "\ttot_emps NUMBER;\n" + + "\ttot_depts NUMBER;\n" + "\tFUNCTION hire (\n" + "\t\tlast_name VARCHAR2, \n" + "\t\tjob_id VARCHAR2, \n" + diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest67.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest67.java new file mode 100644 index 0000000000..26a0b2f940 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTableTest67.java @@ -0,0 +1,73 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleCreateTableTest67 extends OracleTest { + + public void test_types() throws Exception { + String sql = // + " CREATE TABLE new_duplications_index (\"ID\" PRIMARY KEY, project_snapshot_id, snapshot_id, hash, index_in_file, start_line, end_line) NOLOGGING AS SELECT CAST(duplications_index_seq.nextval AS NUMBER(38)) \"ID\", project_snapshot_id, snapshot_id, hash, index_in_file, start_line, end_line FROM duplications_index "; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE TABLE new_duplications_index (\n" + + "\t\"ID\" PRIMARY KEY,\n" + + "\tproject_snapshot_id,\n" + + "\tsnapshot_id,\n" + + "\thash,\n" + + "\tindex_in_file,\n" + + "\tstart_line,\n" + + "\tend_line\n" + + ")\n" + + "NOLOGGING\n" + + "AS\n" + + "SELECT CAST(duplications_index_seq.NEXTVAL AS NUMBER(38)) AS \"ID\", project_snapshot_id, snapshot_id, hash, index_in_file\n" + + "\t, start_line, end_line\n" + + "FROM duplications_index",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(2, visitor.getTables().size()); + + Assert.assertEquals(13, visitor.getColumns().size()); + + Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("duplications_index", "project_snapshot_id"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTriggerTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTriggerTest2.java new file mode 100644 index 0000000000..81fce48fdd --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/create/OracleCreateTriggerTest2.java @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.oracle.create; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class OracleCreateTriggerTest2 extends OracleTest { + + public void test_0() throws Exception { + String sql = // + "CREATE OR REPLACE TRIGGER projects_idt\n" + + " BEFORE INSERT ON projects\n" + + " FOR EACH ROW\n" + + " BEGIN\n" + + " IF :new.id IS null THEN\n" + + " SELECT projects_seq.nextval INTO :new.id FROM dual;\n" + + " END IF;\n" + + " END;"; + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + Assert.assertEquals("CREATE OR REPLEACE TRIGGER projects_idt\n" + + "\tBEFORE INSERT\n" + + "\tON projects\n" + + "\tFOR EACH ROW\n" + + "BEGIN\n" + + "\tIF :new.id IS NULL THEN\n" + + "\t\tSELECT projects_seq.NEXTVAL\n" + + "\t\tINTO :new.id\n" + + "\t\tFROM dual;\n" + + "\tEND IF;\n" + + "END;",// + SQLUtils.toSQLString(stmt, JdbcConstants.ORACLE)); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("relationships : " + visitor.getRelationships()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + + // Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("cdc.en_complaint_ipr_stat_fdt0"))); + + Assert.assertEquals(0, visitor.getColumns().size()); + + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "*"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "YEAR"))); + // Assert.assertTrue(visitor.getColumns().contains(new TableStat.Column("pivot_table", "order_mode"))); + } +} diff --git a/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest.java b/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest.java new file mode 100644 index 0000000000..a931c053d0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.oracle.demo; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.druid.util.Utils; +import org.apache.commons.io.FileUtils; +import org.junit.Assert; + +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.List; + +public class OracleResourceTest extends OracleTest { + + public void test_0() throws Exception { + File file = new File("/Users/wenshao/Downloads/eoa_tmp_sqltext_1.csv"); + + String sql = FileUtils.readFileToString(file); + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + + // Assert.assertEquals(1, statementList.size()); + + System.out.println(sql); + + print(statementList); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + + for (int i = 0, size = statementList.size(); i < size; ++i) { + SQLStatement statement = statementList.get(i); + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + + System.out.println(); + System.out.println(); + } + + void mergValidate(String sql, String expect) { + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + StringBuilder out = new StringBuilder(); + MySqlOutputVisitor visitor = new MySqlOutputVisitor(out, true); + statemen.accept(visitor); + + System.out.println(out.toString()); + + Assert.assertEquals(expect, out.toString()); + } + +} diff --git a/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest2.java b/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest2.java new file mode 100644 index 0000000000..2d9f3d8aa9 --- /dev/null +++ b/src/test/java/com/alibaba/druid/sql/oracle/demo/OracleResourceTest2.java @@ -0,0 +1,77 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.sql.oracle.demo; + +import com.alibaba.druid.sql.OracleTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleSchemaStatVisitor; +import org.apache.commons.io.FileUtils; +import org.junit.Assert; + +import java.io.File; +import java.util.List; + +public class OracleResourceTest2 extends OracleTest { + + public void test_0() throws Exception { + File file = new File("/Users/wenshao/Downloads/Procedures.sql"); + + String sql = FileUtils.readFileToString(file); + + OracleStatementParser parser = new OracleStatementParser(sql); + List statementList = parser.parseStatementList(); + + // Assert.assertEquals(1, statementList.size()); + + System.out.println(sql); + + print(statementList); + + OracleSchemaStatVisitor visitor = new OracleSchemaStatVisitor(); + + for (int i = 0, size = statementList.size(); i < size; ++i) { + SQLStatement statement = statementList.get(i); + statement.accept(visitor); + } + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + + System.out.println(); + System.out.println(); + } + + void mergValidate(String sql, String expect) { + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + StringBuilder out = new StringBuilder(); + MySqlOutputVisitor visitor = new MySqlOutputVisitor(out, true); + statemen.accept(visitor); + + System.out.println(out.toString()); + + Assert.assertEquals(expect, out.toString()); + } + +}