diff --git a/symmetric-android/src/main/java/org/jumpmind/symmetric/android/AndroidDatabasePlatform.java b/symmetric-android/src/main/java/org/jumpmind/symmetric/android/AndroidDatabasePlatform.java index 847de33c58..19f6e87a38 100644 --- a/symmetric-android/src/main/java/org/jumpmind/symmetric/android/AndroidDatabasePlatform.java +++ b/symmetric-android/src/main/java/org/jumpmind/symmetric/android/AndroidDatabasePlatform.java @@ -22,8 +22,12 @@ import java.math.BigDecimal; +import org.jumpmind.db.model.Database; import org.jumpmind.db.platform.AbstractDatabasePlatform; import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; import org.jumpmind.db.platform.sqlite.SqliteDdlBuilder; import org.jumpmind.db.platform.sqlite.SqliteDdlReader; import org.jumpmind.db.sql.ISqlTemplate; @@ -110,4 +114,27 @@ protected Object parseInteger(String value) { } } + @Override + public PermissionResult getCreateSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.CREATE_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTablePermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getAlterSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.ALTER_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTriggerPermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, Status.UNIMPLEMENTED); + return result; + } } diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlSymmetricDialect.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlSymmetricDialect.java index 43e865902b..3ddf10837e 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlSymmetricDialect.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql/MsSqlSymmetricDialect.java @@ -32,6 +32,7 @@ import org.jumpmind.db.model.Table; import org.jumpmind.db.model.TypeMap; import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.IConnectionCallback; import org.jumpmind.db.sql.ISqlTemplate; import org.jumpmind.db.sql.ISqlTransaction; @@ -417,4 +418,9 @@ protected String getDbSpecificDataHasChangedCondition(Trigger trigger) { return "$(anyNonBlobColumnChanged)"; } + @Override + public PermissionType[] getSymTablePermissions() { + PermissionType[] permissions = { PermissionType.CREATE_TABLE, PermissionType.DROP_TABLE, PermissionType.CREATE_TRIGGER, PermissionType.DROP_TRIGGER, PermissionType.CREATE_FUNCTION}; + return permissions; + } } diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql2000/MsSql2000SymmetricDialect.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql2000/MsSql2000SymmetricDialect.java index 808a6a1cd4..cace2413c9 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql2000/MsSql2000SymmetricDialect.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mssql2000/MsSql2000SymmetricDialect.java @@ -1,120 +1,127 @@ -/** - * Licensed to JumpMind Inc under one or more contributor - * license agreements. See the NOTICE file distributed - * with this work for additional information regarding - * copyright ownership. JumpMind Inc licenses this file - * to you under the GNU General Public License, version 3.0 (GPLv3) - * (the "License"); you may not use this file except in compliance - * with the License. - * - * You should have received a copy of the GNU General Public License, - * version 3.0 (GPLv3) along with this library; if not, see - * . - * - * 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 org.jumpmind.symmetric.db.mssql2000; - -import org.jumpmind.db.platform.IDatabasePlatform; -import org.jumpmind.db.util.BinaryEncoding; -import org.jumpmind.symmetric.db.mssql.MsSqlSymmetricDialect; -import org.jumpmind.symmetric.service.IParameterService; - -public class MsSql2000SymmetricDialect extends MsSqlSymmetricDialect { - - - public MsSql2000SymmetricDialect(IParameterService parameterService, IDatabasePlatform platform) { - super(parameterService, platform); - this.triggerTemplate = new MsSql2000TriggerTemplate(this); - } - - @Override - protected boolean alterLockEscalation() { - return false; - } - - @Override - public void createRequiredDatabaseObjects() { - String encode = this.parameterService.getTablePrefix() + "_" + "base64_encode"; - if (!installed(SQL_FUNCTION_INSTALLED, encode)) { - String sql = " create function dbo.$(functionName) (\n" + - " @binvalue varbinary(8000)) returns varchar(8000)\n" + - " as \n" + - " begin\n" + - " declare @charvalue varchar(8000)\n" + - " declare @i int\n" + - " declare @length int\n" + - " declare @hexstring char(16)\n" + - "\n" + - " select @charvalue = ''\n" + - " select @i = 1\n" + - " select @length = datalength(@binvalue)\n" + - " select @hexstring = '0123456789abcdef'\n" + - "\n" + - " while (@i <= @length)\n" + - " begin\n" + - "\n" + - " declare @tempint int\n" + - " declare @firstint int\n" + - " declare @secondint int\n" + - "\n" + - " select @tempint = convert(int, substring(@binvalue,@i,1))\n" + - " select @firstint = floor(@tempint/16)\n" + - " select @secondint = @tempint - (@firstint*16)\n" + - "\n" + - " select @charvalue = @charvalue +\n" + - " substring(@hexstring, @firstint+1, 1) +\n" + - " substring(@hexstring, @secondint+1, 1)\n" + - "\n" + - " select @i = @i + 1\n" + - " end\n" + - " return @charvalue\n" + - " end"; - install(sql, encode); - } - - String triggersDisabled = this.parameterService.getTablePrefix() + "_" + "triggers_disabled"; - if (!installed(SQL_FUNCTION_INSTALLED, triggersDisabled)) { - String sql = - "create function dbo.$(functionName)() returns smallint \n" + - " begin \n" + - " declare @disabled varchar(1);\n" + - " declare @context_info varbinary(128); \n" + - " SELECT @Context_Info = CONTEXT_INFO\n" + - " FROM master.dbo.SYSPROCESSES \n" + - " WHERE SPID = @@SPID \n" + - " set @disabled = coalesce(replace(substring(cast(@context_info as varchar), 1, 1), 0x0, ''), ''); \n" + - " if @disabled is null or @disabled != '1' \n" + - " return 0; \n" + - " return 1; \n" + - " end "; - install(sql, triggersDisabled); - } - - String nodeDisabled = this.parameterService.getTablePrefix() + "_" + "node_disabled"; - if (!installed(SQL_FUNCTION_INSTALLED, nodeDisabled)) { - String sql = "create function dbo.$(functionName)() returns varchar(50) \n" + - " begin \n" + - " declare @node varchar(50);\n" + - " declare @context_info varbinary(128);\n" + - " SELECT @context_info = CONTEXT_INFO\n" + - " FROM master.dbo.SYSPROCESSES \n" + - " WHERE SPID = @@SPID \n " + - " SELECT @node = coalesce(replace(substring(cast(@context_info as varchar) collate SQL_Latin1_General_CP1_CI_AS, 2, 50), 0x0, ''), ''); \n " + - " return @node; " + - " end "; - install(sql, nodeDisabled); - } - - } - - @Override - public BinaryEncoding getBinaryEncoding() { - return BinaryEncoding.HEX; - } -} +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.symmetric.db.mssql2000; + +import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.util.BinaryEncoding; +import org.jumpmind.symmetric.db.mssql.MsSqlSymmetricDialect; +import org.jumpmind.symmetric.service.IParameterService; + +public class MsSql2000SymmetricDialect extends MsSqlSymmetricDialect { + + + public MsSql2000SymmetricDialect(IParameterService parameterService, IDatabasePlatform platform) { + super(parameterService, platform); + this.triggerTemplate = new MsSql2000TriggerTemplate(this); + } + + @Override + protected boolean alterLockEscalation() { + return false; + } + + @Override + public void createRequiredDatabaseObjects() { + String encode = this.parameterService.getTablePrefix() + "_" + "base64_encode"; + if (!installed(SQL_FUNCTION_INSTALLED, encode)) { + String sql = " create function dbo.$(functionName) (\n" + + " @binvalue varbinary(8000)) returns varchar(8000)\n" + + " as \n" + + " begin\n" + + " declare @charvalue varchar(8000)\n" + + " declare @i int\n" + + " declare @length int\n" + + " declare @hexstring char(16)\n" + + "\n" + + " select @charvalue = ''\n" + + " select @i = 1\n" + + " select @length = datalength(@binvalue)\n" + + " select @hexstring = '0123456789abcdef'\n" + + "\n" + + " while (@i <= @length)\n" + + " begin\n" + + "\n" + + " declare @tempint int\n" + + " declare @firstint int\n" + + " declare @secondint int\n" + + "\n" + + " select @tempint = convert(int, substring(@binvalue,@i,1))\n" + + " select @firstint = floor(@tempint/16)\n" + + " select @secondint = @tempint - (@firstint*16)\n" + + "\n" + + " select @charvalue = @charvalue +\n" + + " substring(@hexstring, @firstint+1, 1) +\n" + + " substring(@hexstring, @secondint+1, 1)\n" + + "\n" + + " select @i = @i + 1\n" + + " end\n" + + " return @charvalue\n" + + " end"; + install(sql, encode); + } + + String triggersDisabled = this.parameterService.getTablePrefix() + "_" + "triggers_disabled"; + if (!installed(SQL_FUNCTION_INSTALLED, triggersDisabled)) { + String sql = + "create function dbo.$(functionName)() returns smallint \n" + + " begin \n" + + " declare @disabled varchar(1);\n" + + " declare @context_info varbinary(128); \n" + + " SELECT @Context_Info = CONTEXT_INFO\n" + + " FROM master.dbo.SYSPROCESSES \n" + + " WHERE SPID = @@SPID \n" + + " set @disabled = coalesce(replace(substring(cast(@context_info as varchar), 1, 1), 0x0, ''), ''); \n" + + " if @disabled is null or @disabled != '1' \n" + + " return 0; \n" + + " return 1; \n" + + " end "; + install(sql, triggersDisabled); + } + + String nodeDisabled = this.parameterService.getTablePrefix() + "_" + "node_disabled"; + if (!installed(SQL_FUNCTION_INSTALLED, nodeDisabled)) { + String sql = "create function dbo.$(functionName)() returns varchar(50) \n" + + " begin \n" + + " declare @node varchar(50);\n" + + " declare @context_info varbinary(128);\n" + + " SELECT @context_info = CONTEXT_INFO\n" + + " FROM master.dbo.SYSPROCESSES \n" + + " WHERE SPID = @@SPID \n " + + " SELECT @node = coalesce(replace(substring(cast(@context_info as varchar) collate SQL_Latin1_General_CP1_CI_AS, 2, 50), 0x0, ''), ''); \n " + + " return @node; " + + " end "; + install(sql, nodeDisabled); + } + + } + + @Override + public BinaryEncoding getBinaryEncoding() { + return BinaryEncoding.HEX; + } + + @Override + public PermissionType[] getSymTablePermissions() { + PermissionType[] permissions = { PermissionType.CREATE_TABLE, PermissionType.DROP_TABLE, PermissionType.CREATE_TRIGGER, PermissionType.DROP_TRIGGER, PermissionType.CREATE_FUNCTION}; + return permissions; + } +} diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mysql/MySqlSymmetricDialect.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mysql/MySqlSymmetricDialect.java index b5486fed5f..98df9d2ab8 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mysql/MySqlSymmetricDialect.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/mysql/MySqlSymmetricDialect.java @@ -24,6 +24,7 @@ import java.sql.SQLException; import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.ISqlTransaction; import org.jumpmind.db.sql.JdbcSqlTransaction; import org.jumpmind.db.sql.SqlException; @@ -228,4 +229,10 @@ public BinaryEncoding getBinaryEncoding() { protected String getDbSpecificDataHasChangedCondition(Trigger trigger) { return "var_old_data is null or var_row_data != var_old_data"; } + + @Override + public PermissionType[] getSymTablePermissions() { + PermissionType[] permissions = { PermissionType.CREATE_TABLE, PermissionType.DROP_TABLE, PermissionType.CREATE_TRIGGER, PermissionType.DROP_TRIGGER, PermissionType.CREATE_ROUTINE}; + return permissions; + } } diff --git a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleSymmetricDialect.java b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleSymmetricDialect.java index 454e6a308a..02d181f5d3 100644 --- a/symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleSymmetricDialect.java +++ b/symmetric-client/src/main/java/org/jumpmind/symmetric/db/oracle/OracleSymmetricDialect.java @@ -27,6 +27,7 @@ import org.apache.commons.lang.time.DateUtils; import org.jumpmind.db.model.Table; import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.ISqlTransaction; import org.jumpmind.db.sql.SqlException; import org.jumpmind.db.util.BinaryEncoding; @@ -358,4 +359,10 @@ protected String getDbSpecificDataHasChangedCondition(Trigger trigger) { public String getTemplateNumberPrecisionSpec() { return parameterService.getString(ParameterConstants.DBDIALECT_ORACLE_TEMPLATE_NUMBER_SPEC,"30,10"); } + + @Override + public PermissionType[] getSymTablePermissions() { + PermissionType[] permissions = { PermissionType.CREATE_TABLE, PermissionType.DROP_TABLE, PermissionType.CREATE_TRIGGER, PermissionType.DROP_TRIGGER, PermissionType.EXECUTE}; + return permissions; + } } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractSymmetricDialect.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractSymmetricDialect.java index 79869791b0..f77987a2f8 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractSymmetricDialect.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/AbstractSymmetricDialect.java @@ -38,6 +38,7 @@ import org.jumpmind.db.platform.IAlterDatabaseInterceptor; import org.jumpmind.db.platform.IDatabasePlatform; import org.jumpmind.db.platform.IDdlBuilder; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.ISqlResultsListener; import org.jumpmind.db.sql.ISqlTemplate; import org.jumpmind.db.sql.ISqlTransaction; @@ -815,4 +816,9 @@ public IParameterService getParameterService() { public void setExtensionService(IExtensionService extensionService) { this.extensionService = extensionService; } + + public PermissionType[] getSymTablePermissions() { + PermissionType[] permissions = { PermissionType.CREATE_TABLE, PermissionType.DROP_TABLE, PermissionType.CREATE_TRIGGER, PermissionType.DROP_TRIGGER }; + return permissions; + } } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/ISymmetricDialect.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/ISymmetricDialect.java index 96c88dcb71..f22dd6852a 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/db/ISymmetricDialect.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/db/ISymmetricDialect.java @@ -1,203 +1,204 @@ -/** - * Licensed to JumpMind Inc under one or more contributor - * license agreements. See the NOTICE file distributed - * with this work for additional information regarding - * copyright ownership. JumpMind Inc licenses this file - * to you under the GNU General Public License, version 3.0 (GPLv3) - * (the "License"); you may not use this file except in compliance - * with the License. - * - * You should have received a copy of the GNU General Public License, - * version 3.0 (GPLv3) along with this library; if not, see - * . - * - * 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 org.jumpmind.symmetric.db; - -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.jumpmind.db.model.Column; -import org.jumpmind.db.model.Database; -import org.jumpmind.db.model.Table; -import org.jumpmind.db.platform.IDatabasePlatform; -import org.jumpmind.db.sql.ISqlTransaction; -import org.jumpmind.db.util.BinaryEncoding; -import org.jumpmind.symmetric.io.data.DataEventType; -import org.jumpmind.symmetric.model.Channel; -import org.jumpmind.symmetric.model.Node; -import org.jumpmind.symmetric.model.Trigger; -import org.jumpmind.symmetric.model.TriggerHistory; -import org.jumpmind.symmetric.model.TriggerRouter; -import org.jumpmind.symmetric.service.IExtensionService; -import org.jumpmind.symmetric.service.IParameterService; -import org.jumpmind.symmetric.service.impl.TransformService.TransformTableNodeGroupLink; - +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.symmetric.db; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jumpmind.db.model.Column; +import org.jumpmind.db.model.Database; +import org.jumpmind.db.model.Table; +import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.ISqlTransaction; +import org.jumpmind.db.util.BinaryEncoding; +import org.jumpmind.symmetric.io.data.DataEventType; +import org.jumpmind.symmetric.model.Channel; +import org.jumpmind.symmetric.model.Node; +import org.jumpmind.symmetric.model.Trigger; +import org.jumpmind.symmetric.model.TriggerHistory; +import org.jumpmind.symmetric.model.TriggerRouter; +import org.jumpmind.symmetric.service.IExtensionService; +import org.jumpmind.symmetric.service.IParameterService; +import org.jumpmind.symmetric.service.impl.TransformService.TransformTableNodeGroupLink; + /* * A dialect is the interface that insulates SymmetricDS from database implementation specifics. */ -public interface ISymmetricDialect { - +public interface ISymmetricDialect { + public void createTrigger(StringBuilder sqlBuffer, DataEventType dml, - Trigger trigger, TriggerHistory hist, Channel channel, - String tablePrefix, Table table); - - /* - * Get the name of this symmetric instance. This can be set in - * symmetric.properties using the symmetric.runtime.engine.name property. - */ - public String getEngineName(); - - public void removeTrigger(StringBuilder sqlBuffer, String catalogName, String schemaName, String triggerName, - String tableName); - + Trigger trigger, TriggerHistory hist, Channel channel, + String tablePrefix, Table table); + + /* + * Get the name of this symmetric instance. This can be set in + * symmetric.properties using the symmetric.runtime.engine.name property. + */ + public String getEngineName(); + + public void removeTrigger(StringBuilder sqlBuffer, String catalogName, String schemaName, String triggerName, + String tableName); + public boolean doesTriggerExist(String catalogName, String schema, String tableName, String triggerName); - public void verifyDatabaseIsCompatible(); - + public void verifyDatabaseIsCompatible(); + public void initTablesAndDatabaseObjects(); public void dropTablesAndDatabaseObjects(); - public boolean createOrAlterTablesIfNecessary(String... tables); - - public void dropRequiredDatabaseObjects(); - - public void createRequiredDatabaseObjects(); - - public IDatabasePlatform getPlatform(); - - public String getName(); - - public String getVersion(); - - public int getMajorVersion(); - - public int getMinorVersion(); - - public String getProductVersion(); - + public boolean createOrAlterTablesIfNecessary(String... tables); + + public void dropRequiredDatabaseObjects(); + + public void createRequiredDatabaseObjects(); + + public IDatabasePlatform getPlatform(); + + public String getName(); + + public String getVersion(); + + public int getMajorVersion(); + + public int getMinorVersion(); + + public String getProductVersion(); + public BinaryEncoding getBinaryEncoding(); - public String getTransactionTriggerExpression(String defaultCatalog, String defaultSchema, Trigger trigger); - + public String getTransactionTriggerExpression(String defaultCatalog, String defaultSchema, Trigger trigger); + public String createInitialLoadSqlFor(Node node, TriggerRouter trigger, Table table, TriggerHistory triggerHistory, Channel channel, String overrideSelectSql); - - public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory); - - public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory, List transforms); - - public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory, List transforms, String deleteSql); - - public String createCsvDataSql(Trigger trigger, TriggerHistory triggerHistory, Channel channel, String whereClause); - - public String createCsvPrimaryKeySql(Trigger trigger, TriggerHistory triggerHistory, Channel channel, String whereClause); - - /* - * Get the maximum size the name of a trigger can be for the database - * platform. If the generated symmetric trigger name is greater than the max - * trigger name, symmetric will truncate the name, then log a warning - * suggesting that you might want to provide your own name. - */ - public int getMaxTriggerNameLength(); - + + public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory); + + public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory, List transforms); + + public String createPurgeSqlFor(Node node, TriggerRouter triggerRouter, TriggerHistory triggerHistory, List transforms, String deleteSql); + + public String createCsvDataSql(Trigger trigger, TriggerHistory triggerHistory, Channel channel, String whereClause); + + public String createCsvPrimaryKeySql(Trigger trigger, TriggerHistory triggerHistory, Channel channel, String whereClause); + + /* + * Get the maximum size the name of a trigger can be for the database + * platform. If the generated symmetric trigger name is greater than the max + * trigger name, symmetric will truncate the name, then log a warning + * suggesting that you might want to provide your own name. + */ + public int getMaxTriggerNameLength(); + public boolean supportsTransactionId(); - /* - * Use this call to check to see if the implemented database dialect supports - * a way to check on pending database transactions. - */ - public boolean supportsTransactionViews(); - - /* - * Indicates if this dialect supports subselects in delete statements. - */ - public boolean supportsSubselectsInDelete(); - - /* - * Indicates if this dialect supports subselects in update statements. - */ - public boolean supportsSubselectsInUpdate(); - - /* - * Implement this if the database has some type of cleanup functionality - * that needs to be run when dropping database objects. An example is - * Oracle's 'purge recyclebin' - */ - public void cleanDatabase(); - - public void disableSyncTriggers(ISqlTransaction transaction); - - public void disableSyncTriggers(ISqlTransaction transaction, String nodeId); - - public void enableSyncTriggers(ISqlTransaction transaction); - - public String getSyncTriggersExpression(); - - public String getSourceNodeExpression(); - - public String getCreateSymmetricDDL(); - - public boolean isBlobSyncSupported(); - - public boolean isClobSyncSupported(); - - /* - * An indicator as to whether the ability to override the default - * transaction id provided by the dialect can be overridden in the trigger - * configuration. - */ - public boolean isTransactionIdOverrideSupported(); - - public Table getTable(TriggerHistory triggerHistory, boolean useCache); - + /* + * Use this call to check to see if the implemented database dialect supports + * a way to check on pending database transactions. + */ + public boolean supportsTransactionViews(); + + /* + * Indicates if this dialect supports subselects in delete statements. + */ + public boolean supportsSubselectsInDelete(); + + /* + * Indicates if this dialect supports subselects in update statements. + */ + public boolean supportsSubselectsInUpdate(); + + /* + * Implement this if the database has some type of cleanup functionality + * that needs to be run when dropping database objects. An example is + * Oracle's 'purge recyclebin' + */ + public void cleanDatabase(); + + public void disableSyncTriggers(ISqlTransaction transaction); + + public void disableSyncTriggers(ISqlTransaction transaction, String nodeId); + + public void enableSyncTriggers(ISqlTransaction transaction); + + public String getSyncTriggersExpression(); + + public String getSourceNodeExpression(); + + public String getCreateSymmetricDDL(); + + public boolean isBlobSyncSupported(); + + public boolean isClobSyncSupported(); + + /* + * An indicator as to whether the ability to override the default + * transaction id provided by the dialect can be overridden in the trigger + * configuration. + */ + public boolean isTransactionIdOverrideSupported(); + + public Table getTable(TriggerHistory triggerHistory, boolean useCache); + public long insertWithGeneratedKey(final String sql, final SequenceIdentifier sequenceId); - public long insertWithGeneratedKey(final String sql, final SequenceIdentifier identifier, Object... args); - - @Deprecated - public Column[] orderColumns(String[] columnNames, Table table); - - public boolean supportsOpenCursorsAcrossCommit(); - - /* - * Retrieves a list of keywords for the database. - */ - public Set getSqlKeywords(); - - public String getInitialLoadTableAlias(); - - public String preProcessTriggerSqlClause(String sqlClause); - - public void truncateTable(String tableName); - - public long getDatabaseTime(); - - public boolean areDatabaseTransactionsPendingSince(long time); - - public Date getEarliestTransactionStartTime(); - - /* - * Returns true if the trigger select lob data back from the original table. - */ - public boolean needsToSelectLobData(); - - /* - * This is a SQL clause that compares the old data to the new data in a trigger. - */ - public String getDataHasChangedCondition(Trigger trigger); - - /* - * Indicates whether captured data can contain gaps. - */ + public long insertWithGeneratedKey(final String sql, final SequenceIdentifier identifier, Object... args); + + @Deprecated + public Column[] orderColumns(String[] columnNames, Table table); + + public boolean supportsOpenCursorsAcrossCommit(); + + /* + * Retrieves a list of keywords for the database. + */ + public Set getSqlKeywords(); + + public String getInitialLoadTableAlias(); + + public String preProcessTriggerSqlClause(String sqlClause); + + public void truncateTable(String tableName); + + public long getDatabaseTime(); + + public boolean areDatabaseTransactionsPendingSince(long time); + + public Date getEarliestTransactionStartTime(); + + /* + * Returns true if the trigger select lob data back from the original table. + */ + public boolean needsToSelectLobData(); + + /* + * This is a SQL clause that compares the old data to the new data in a trigger. + */ + public String getDataHasChangedCondition(Trigger trigger); + + /* + * Indicates whether captured data can contain gaps. + */ public boolean canGapsOccurInCapturedDataIds(); public String massageDataExtractionSql(String sql, Channel channel); @@ -231,14 +232,16 @@ public void removeTrigger(StringBuilder sqlBuffer, String catalogName, String sc public String getTemplateNumberPrecisionSpec(); - public Map getSqlReplacementTokens(); - + public Map getSqlReplacementTokens(); + public int getSqlTypeForIds(); - - public AbstractTriggerTemplate getTriggerTemplate(); - - public IParameterService getParameterService(); - - public void setExtensionService(IExtensionService extensionService); + + public AbstractTriggerTemplate getTriggerTemplate(); + + public IParameterService getParameterService(); + + public void setExtensionService(IExtensionService extensionService); + + public PermissionType[] getSymTablePermissions(); } diff --git a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java index acdce37b93..5c91b3b935 100644 --- a/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java +++ b/symmetric-core/src/main/java/org/jumpmind/symmetric/service/impl/DataLoaderService.java @@ -913,7 +913,7 @@ public void end(final DataContext ctx, final Batch batch, final IStagedResource Callable loadBatchFromStage = new Callable() { public IncomingBatch call() throws Exception { IncomingBatch incomingBatch = null; - if (!isError) { + if (!isError && resource != null && resource.exists()) { try { processInfo.setStatus(ProcessInfo.Status.LOADING); @@ -949,6 +949,11 @@ protected IDataWriter chooseDataWriter(Batch batch) { } resource.setState(State.DONE); } + } else { + log.info("The batch {} was missing in staging. Setting status to resend", batch.getNodeBatchId()); + incomingBatch = new IncomingBatch(batch); + incomingBatch.setStatus(Status.RS); + incomingBatchService.updateIncomingBatch(incomingBatch); } return incomingBatch; } diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java index 8e979f5bea..dab445f535 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/AbstractDatabasePlatform.java @@ -1,921 +1,1078 @@ -package org.jumpmind.db.platform; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import static org.apache.commons.lang.StringUtils.isNotBlank; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Array; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; -import java.util.regex.Pattern; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.time.DateUtils; -import org.jumpmind.db.io.DatabaseXmlUtil; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.model.ColumnTypes; -import org.jumpmind.db.model.Database; -import org.jumpmind.db.model.ForeignKey; -import org.jumpmind.db.model.IIndex; -import org.jumpmind.db.model.IndexColumn; -import org.jumpmind.db.model.Reference; -import org.jumpmind.db.model.Table; -import org.jumpmind.db.model.TypeMap; -import org.jumpmind.db.sql.DmlStatement; -import org.jumpmind.db.sql.DmlStatement.DmlType; -import org.jumpmind.db.sql.ISqlTemplate; -import org.jumpmind.db.sql.Row; -import org.jumpmind.db.sql.SqlScript; -import org.jumpmind.db.util.BinaryEncoding; -import org.jumpmind.exception.IoException; -import org.jumpmind.util.FormatUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/* - * Base class for platform implementations. - */ -public abstract class AbstractDatabasePlatform implements IDatabasePlatform { - - /* The log for this platform. */ - protected final Logger log = LoggerFactory.getLogger(getClass()); - - public static final String REQUIRED_FIELD_NULL_SUBSTITUTE = " "; - - /* The default name for models read from the database, if no name as given. */ - protected static final String MODEL_DEFAULT_NAME = "default"; - - /* The model reader for this platform. */ - protected IDdlReader ddlReader; - - protected IDdlBuilder ddlBuilder; - - protected Map tableCache = new HashMap(); - - private long lastTimeCachedModelClearedInMs = System.currentTimeMillis(); - - protected long clearCacheModelTimeoutInMs = DateUtils.MILLIS_PER_HOUR; - - protected String defaultSchema; - - protected String defaultCatalog; - - protected Boolean storesUpperCaseIdentifiers; - - protected Boolean storesLowerCaseIdentifiers; - - protected Boolean storesMixedCaseIdentifiers; - - protected boolean metadataIgnoreCase = true; - - public AbstractDatabasePlatform() { - } - - public DatabaseInfo getDatabaseInfo() { - return getDdlBuilder().getDatabaseInfo(); - } - - abstract public ISqlTemplate getSqlTemplate(); - - abstract public ISqlTemplate getSqlTemplateDirty(); - - public DmlStatement createDmlStatement(DmlType dmlType, Table table, String textColumnExpression) { - - return createDmlStatement(dmlType, table.getCatalog(), table.getSchema(), table.getName(), - table.getPrimaryKeyColumns(), table.getColumns(), null, textColumnExpression); - } - - public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, - String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression) { - - return DmlStatementFactory.createDmlStatement(getName(), dmlType, catalogName, schemaName, - tableName, keys, columns, nullKeyValues, getDdlBuilder(), textColumnExpression); - } - - public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, - String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression, - boolean namedParameters) { - - return DmlStatementFactory.createDmlStatement(getName(), dmlType, catalogName, schemaName, - tableName, keys, columns, nullKeyValues, getDdlBuilder(), textColumnExpression, - namedParameters); - - } - - - public IDdlReader getDdlReader() { - return ddlReader; - } - - public IDdlBuilder getDdlBuilder() { - return ddlBuilder; - } - - public void setClearCacheModelTimeoutInMs(long clearCacheModelTimeoutInMs) { - this.clearCacheModelTimeoutInMs = clearCacheModelTimeoutInMs; - } - - public long getClearCacheModelTimeoutInMs() { - return clearCacheModelTimeoutInMs; - } - - public void dropTables(boolean continueOnError, Table...tables) { - Database db = new Database(); - for (Table table : tables) { - db.addTable(table); - } - dropDatabase(db, continueOnError); - } - - public void dropDatabase(Database database, boolean continueOnError) { - String sql = ddlBuilder.dropTables(database); - new SqlScript(sql, getSqlTemplate(), !continueOnError, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); - } - - public void createTables(boolean dropTablesFirst, boolean continueOnError, Table... tables) { - Database database = new Database(); - database.addTables(tables); - createDatabase(database, dropTablesFirst, continueOnError); - } - - public void createDatabase(Database targetDatabase, boolean dropTablesFirst, - boolean continueOnError) { - if (dropTablesFirst) { - dropDatabase(targetDatabase, true); - } - - String createSql = ddlBuilder.createTables(targetDatabase, false); - - if (log.isDebugEnabled()) { - log.debug("Generated create sql: \n{}", createSql); - } - - String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter(); - new SqlScript(createSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); - } - - public void alterDatabase(Database desiredDatabase, boolean continueOnError) { - alterTables(continueOnError, desiredDatabase.getTables()); - } - - public void alterTables(boolean continueOnError, Table... desiredTables) { - Database currentDatabase = new Database(); - Database desiredDatabase = new Database(); - StringBuilder tablesProcessed = new StringBuilder(); - for (Table table : desiredTables) { - tablesProcessed.append(table.getFullyQualifiedTableName()); - tablesProcessed.append(", "); - desiredDatabase.addTable(table); - Table currentTable = ddlReader.readTable(table.getCatalog(), table.getSchema(), - table.getName()); - if (currentTable != null) { - currentDatabase.addTable(currentTable); - } - } - - if (tablesProcessed.length() > 1) { - tablesProcessed.replace(tablesProcessed.length() - 2, tablesProcessed.length(), ""); - } - - String alterSql = ddlBuilder.alterDatabase(currentDatabase, desiredDatabase); - - if (StringUtils.isNotBlank(alterSql.trim())) { - log.info("Running alter sql:\n{}", alterSql); - String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter(); - new SqlScript(alterSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); - } else { - log.info("Tables up to date. No alters found for {}", tablesProcessed); - } - - } - - public Database readDatabase(String catalog, String schema, String[] tableTypes) { - Database model = ddlReader.readTables(catalog, schema, tableTypes); - if ((model.getName() == null) || (model.getName().length() == 0)) { - model.setName(MODEL_DEFAULT_NAME); - } - return model; - } - - - public Database readFromDatabase(Table... tables) { - Database fromDb = new Database(); - for (Table tableFromXml : tables) { - Table tableFromDatabase = getTableFromCache(tableFromXml.getCatalog(), - tableFromXml.getSchema(), tableFromXml.getName(), true); - if (tableFromDatabase != null) { - fromDb.addTable(tableFromDatabase); - } - } - fromDb.initialize(); - return fromDb; - } - - public Table readTableFromDatabase(String catalogName, String schemaName, String tableName) { - String originalFullyQualifiedName = Table.getFullyQualifiedTableName(catalogName, - schemaName, tableName); - String defaultedCatalogName = catalogName == null ? getDefaultCatalog() : catalogName; - String defaultedSchemaName = schemaName == null ? getDefaultSchema() : schemaName; - - Table table = ddlReader.readTable(defaultedCatalogName, defaultedSchemaName, tableName); - if (table == null && metadataIgnoreCase) { - - IDdlReader reader = getDdlReader(); - - if (isNotBlank(catalogName)) { - List catalogNames = reader.getCatalogNames(); - if (catalogNames != null) { - for (String name : catalogNames) { - if (name != null && name.equalsIgnoreCase(catalogName)) { - defaultedCatalogName = name; - break; - } - } - } - } - - if (isNotBlank(schemaName)) { - List schemaNames = reader.getSchemaNames(catalogName); - if (schemaNames != null) { - for (String name : schemaNames) { - if (name != null && name.equalsIgnoreCase(schemaName)) { - defaultedSchemaName = name; - break; - } - } - } - } - - - List tableNames = reader.getTableNames(defaultedCatalogName, defaultedSchemaName, null); - if (tableNames != null) { - for (String name : tableNames) { - if (name != null && name.equalsIgnoreCase(tableName)) { - tableName = name; - break; - } - } - } - - if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName( - defaultedCatalogName, defaultedSchemaName, tableName))) { - table = ddlReader.readTable(defaultedCatalogName, defaultedSchemaName, tableName); - } - - } - - if (table != null && log.isDebugEnabled()) { - log.debug("Just read table: \n{}", table.toVerboseString()); - } - return table; - } - - public void resetCachedTableModel() { - synchronized (this.getClass()) { - this.tableCache = new HashMap(); - lastTimeCachedModelClearedInMs = System.currentTimeMillis(); - } - } - - public Table getTableFromCache(String tableName, boolean forceReread) { - return getTableFromCache(getDefaultCatalog(), getDefaultSchema(), tableName, forceReread); - } - - public Table getTableFromCache(String catalogName, String schemaName, String tableName, - boolean forceReread) { - if (System.currentTimeMillis() - lastTimeCachedModelClearedInMs > clearCacheModelTimeoutInMs) { - resetCachedTableModel(); - } - Map model = tableCache; - String key = Table.getFullyQualifiedTableName(catalogName, schemaName, tableName); - Table retTable = model != null ? model.get(key) : null; - if (retTable == null || forceReread) { - synchronized (this.getClass()) { - try { - Table table = readTableFromDatabase(catalogName, schemaName, tableName); - tableCache.put(key, table); - retTable = table; - } catch (RuntimeException ex) { - throw ex; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - } - return retTable; - } - - public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, - String[] values) { - Column[] metaData = Table.orderColumns(columnNames, table); - return getObjectValues(encoding, values, metaData); - } - - public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, - String[] values, boolean useVariableDates, boolean fitToColumn) { - Column[] metaData = Table.orderColumns(columnNames, table); - return getObjectValues(encoding, values, metaData, useVariableDates, fitToColumn); - } - - public Object[] getObjectValues(BinaryEncoding encoding, String[] values, - Column[] orderedMetaData) { - return getObjectValues(encoding, values, orderedMetaData, false, false); - } - - public Object[] getObjectValues(BinaryEncoding encoding, String[] values, - Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn) { - if (values != null) { - List list = new ArrayList(values.length); - for (int i = 0; i < values.length; i++) { - String value = values[i]; - Column column = orderedMetaData.length > i ? orderedMetaData[i] : null; - try { - if (column != null) { - list.add(getObjectValue(value, column, encoding, useVariableDates, fitToColumn)); - } - } catch (Exception ex) { - String valueTrimmed = FormatUtils.abbreviateForLogging(value); - throw new RuntimeException("Could not convert a value of " + valueTrimmed + " for column " + - column.getName() + " of type " + column.getMappedType(), ex); - } - } - - return list.toArray(); - } else { - return null; - } - } - - protected Object getObjectValue(String value, Column column, BinaryEncoding encoding, - boolean useVariableDates, boolean fitToColumn) throws DecoderException { - Object objectValue = value; - int type = column.getMappedTypeCode(); - if ((value == null || (getDdlBuilder().getDatabaseInfo().isEmptyStringNulled() && value - .equals(""))) && column.isRequired() && column.isOfTextType()) { - objectValue = REQUIRED_FIELD_NULL_SUBSTITUTE; - } - if (value != null) { - if (type == Types.DATE || type == Types.TIMESTAMP || type == Types.TIME) { - objectValue = parseDate(type, value, useVariableDates); - } else if (type == Types.CHAR) { - String charValue = value.toString(); - if ((StringUtils.isBlank(charValue) && getDdlBuilder().getDatabaseInfo() - .isBlankCharColumnSpacePadded()) - || (StringUtils.isNotBlank(charValue) && getDdlBuilder().getDatabaseInfo() - .isNonBlankCharColumnSpacePadded())) { - objectValue = StringUtils - .rightPad(value.toString(), column.getSizeAsInt(), ' '); - } - } else if (type == Types.BIGINT) { - objectValue = parseBigInteger(value); - } else if (type == Types.INTEGER || type == Types.SMALLINT || type == Types.BIT || type == Types.TINYINT) { - objectValue = parseInteger(value); - } else if (type == Types.FLOAT) { - objectValue = parseFloat(value); - } else if (type == Types.NUMERIC || type == Types.DECIMAL - || type == Types.DOUBLE || type == Types.REAL) { - objectValue = parseBigDecimal(value); - } else if (type == Types.BOOLEAN) { - objectValue = value.equals("1") ? Boolean.TRUE : Boolean.FALSE; - } else if (!(column.getJdbcTypeName() != null && column.getJdbcTypeName().toUpperCase() - .contains(TypeMap.GEOMETRY)) - && !(column.getJdbcTypeName() != null && column.getJdbcTypeName().toUpperCase() - .contains(TypeMap.GEOGRAPHY)) - && (type == Types.BLOB || type == Types.LONGVARBINARY || type == Types.BINARY - || type == Types.VARBINARY || - // SQLServer ntext type - type == -10)) { - if (encoding == BinaryEncoding.NONE) { - objectValue = value.getBytes(); - } else if (encoding == BinaryEncoding.BASE64) { - objectValue = Base64.decodeBase64(value.getBytes()); - } else if (encoding == BinaryEncoding.HEX) { - objectValue = Hex.decodeHex(value.toCharArray()); - } - } else if (type == Types.ARRAY) { - objectValue = createArray(column, value); - } - } - if (objectValue instanceof String) { - String stringValue = cleanTextForTextBasedColumns((String) objectValue); - int size = column.getSizeAsInt(); - if (fitToColumn && size > 0 && stringValue.length() > size) { - stringValue = stringValue.substring(0, size); - } - objectValue = stringValue; - } - - return objectValue; - - } - - protected Object parseFloat(String value) { - return parseBigDecimal(value); - } - - protected Object parseBigDecimal(String value) { - /* - * The number will have either one period or one comma for the decimal - * point, but we need a period - */ - value = cleanNumber(value); - return new BigDecimal(value.replace(',', '.')); - } - - protected Object parseBigInteger(String value) { - try { - value = cleanNumber(value); - return new Long(value.trim()); - } catch (NumberFormatException ex) { - return new BigDecimal(value.replace(',', '.')).toBigInteger(); - } - } - - protected Object parseInteger(String value) { - try { - value = cleanNumber(value); - return Integer.parseInt(value); - } catch (NumberFormatException ex) { - return new BigInteger(value); - } - } - - protected String cleanNumber(String value) { - value = value.trim(); - if (value.equalsIgnoreCase("true")) { - return "1"; - } else if (value.equalsIgnoreCase("false")) { - return "0"; - } else { - return value; - } - } - - // TODO: this should be AbstractDdlBuilder.getInsertSql(Table table, - // Map columnValues, boolean genPlaceholders) - public String[] getStringValues(BinaryEncoding encoding, Column[] metaData, Row row, - boolean useVariableDates, boolean indexByPosition) { - String[] values = new String[metaData.length]; - Set keys = row.keySet(); - int i = 0; - for (String key : keys) { - Column column = metaData[i]; - String name = indexByPosition ? key : column.getName(); - int type = column.getJdbcTypeCode(); - if (row.get(name) != null) { - if (type == Types.BOOLEAN || type == Types.BIT) { - values[i] = row.getBoolean(name) ? "1" : "0"; - } else if (column.isOfNumericType()) { - values[i] = row.getString(name); - } else if (!column.isTimestampWithTimezone() - && (type == Types.DATE || type == Types.TIMESTAMP || type == Types.TIME)) { - values[i] = getDateTimeStringValue(name, type, row, useVariableDates); - } else if (column.isOfBinaryType()) { - byte[] bytes = row.getBytes(name); - if (encoding == BinaryEncoding.NONE) { - values[i] = row.getString(name); - } else if (encoding == BinaryEncoding.BASE64) { - values[i] = new String(Base64.encodeBase64(bytes)); - } else if (encoding == BinaryEncoding.HEX) { - values[i] = new String(Hex.encodeHex(bytes)); - } - } else { - values[i] = row.getString(name); - } - } - - i++; - } - return values; - } - - protected String getDateTimeStringValue(String name, int type, Row row, boolean useVariableDates) { - Object dateObj = row.get(name); - if (dateObj instanceof String) { - return (String) dateObj; - } else { - Date date = row.getDateTime(name); - if (useVariableDates) { - long diff = date.getTime() - System.currentTimeMillis(); - return "${curdate" + diff + "}"; - } else { - return FormatUtils.TIMESTAMP_FORMATTER.format(date); - } - } - } - - public Map getSqlScriptReplacementTokens() { - return null; - } - - public String scrubSql(String sql) { - Map replacementTokens = getSqlScriptReplacementTokens(); - if (replacementTokens != null) { - return FormatUtils.replaceTokens(sql, replacementTokens, false).trim(); - } else { - return sql; - } - } - - protected Array createArray(Column column, final String value) { - return null; - } - - protected String cleanTextForTextBasedColumns(String text) { - return text; - } - - public java.util.Date parseDate(int type, String value, boolean useVariableDates) { - if (StringUtils.isNotBlank(value)) { - try { - boolean useTimestamp = (type == Types.TIMESTAMP) - || (type == Types.DATE && getDdlBuilder().getDatabaseInfo() - .isDateOverridesToTimestamp()); - - if (useVariableDates && value.startsWith("${curdate")) { - long time = Long.parseLong(value.substring(10, value.length() - 1)); - if (value.substring(9, 10).equals("-")) { - time *= -1L; - } - time += System.currentTimeMillis(); - if (useTimestamp) { - return new Timestamp(time); - } - return new Date(time); - } else { - if (useTimestamp) { - return parseTimestamp(type, value); - } else if (type == Types.TIME) { - if (value.indexOf(".") == 8) { - /* - * Firebird (at least) captures fractional seconds - * in time fields which need to be parsed by - * Timestamp.valueOf - */ - return Timestamp.valueOf("1970-01-01 " + value); - } else { - return FormatUtils.parseDate(value, FormatUtils.TIME_PATTERNS); - } - } else { - return FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS); - } - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new RuntimeException(e); - } - } else { - return null; - } - } - - @Override - public Map parseQualifiedTableName(String tableName) { - - Map tableNameParts = new LinkedHashMap(); - if (StringUtils.isEmpty(tableName)) { - return tableNameParts; - } - - String[] initialSplit = tableName.split(Pattern.quote(getDatabaseInfo().getCatalogSeparator())); - if (initialSplit.length == 0) { - initialSplit = new String[] {tableName}; - } - List nameComponents = new ArrayList(); - for (String part : initialSplit) { - String[] subParts = part.split(Pattern.quote(getDatabaseInfo().getSchemaSeparator())); - if (subParts.length == 0) { - subParts = new String[] {part}; - } - for (String subPart : subParts) { - if (!StringUtils.isEmpty(subPart)) { - nameComponents.add(subPart); - } - } - } - - if (nameComponents.size() >= 3) { - tableNameParts.put("catalog", nameComponents.get(0)); - tableNameParts.put("schema", nameComponents.get(1)); - tableNameParts.put("table", nameComponents.get(2)); - } else if (nameComponents.size() == 2) { - tableNameParts.put("schema", nameComponents.get(0)); - tableNameParts.put("table", nameComponents.get(1)); - } else { - tableNameParts.put("table", nameComponents.get(0)); - } - - return tableNameParts; - } - - public Table makeAllColumnsPrimaryKeys(Table table) { - Table result = table.copy(); - for (Column column : result.getColumns()) { - if (!isLob(column.getMappedTypeCode())) { - column.setPrimaryKey(true); - } - } - return result; - } - - public boolean isLob(int type) { - return isClob(type) || isBlob(type); - } - - public boolean isClob(int type) { - return type == Types.CLOB || type == Types.NCLOB || type == Types.LONGVARCHAR || type == ColumnTypes.LONGNVARCHAR; - } - - public boolean isBlob(int type) { - return type == Types.BLOB || type == Types.BINARY || type == Types.VARBINARY || type == Types.LONGVARBINARY || type == -10; - } - - public List getLobColumns(Table table) { - List lobColumns = new ArrayList(1); - Column[] allColumns = table.getColumns(); - for (Column column : allColumns) { - if (isLob(column.getMappedTypeCode())) { - lobColumns.add(column); - } - } - return lobColumns; - } - - public void setMetadataIgnoreCase(boolean metadataIgnoreCase) { - this.metadataIgnoreCase = metadataIgnoreCase; - } - - public boolean isMetadataIgnoreCase() { - return metadataIgnoreCase; - } - - public boolean isStoresLowerCaseIdentifiers() { - if (storesLowerCaseIdentifiers == null) { - storesLowerCaseIdentifiers = getSqlTemplate().isStoresLowerCaseIdentifiers(); - } - return storesLowerCaseIdentifiers; - } - - public boolean isStoresMixedCaseQuotedIdentifiers() { - if (storesMixedCaseIdentifiers == null) { - storesMixedCaseIdentifiers = getSqlTemplate().isStoresMixedCaseQuotedIdentifiers(); - } - return storesMixedCaseIdentifiers; - } - - public boolean isStoresUpperCaseIdentifiers() { - if (storesUpperCaseIdentifiers == null) { - storesUpperCaseIdentifiers = getSqlTemplate().isStoresUpperCaseIdentifiers(); - } - return storesUpperCaseIdentifiers; - } - - public Database readDatabaseFromXml(String filePath, boolean alterCaseToMatchDatabaseDefaultCase) { - InputStream is = null; - try { - File file = new File(filePath); - if (file.exists()) { - try { - is = new FileInputStream(file); - } catch (FileNotFoundException e) { - throw new IoException(e); - } - } else { - is = AbstractDatabasePlatform.class.getResourceAsStream(filePath); - } - - if (is != null) { - return readDatabaseFromXml(is, alterCaseToMatchDatabaseDefaultCase); - } else { - throw new IoException("Could not find the file: %s", filePath); - } - } finally { - IOUtils.closeQuietly(is); - } - } - - public void prefixDatabase(String prefix, Database targetTables) { - try { - if (StringUtils.isNotBlank(prefix) && !prefix.endsWith("_")) { - prefix = prefix + "_"; - } - Table[] tables = targetTables.getTables(); - - boolean storesUpperCaseIdentifiers = isStoresUpperCaseIdentifiers(); - for (Table table : tables) { - String name = String.format("%s%s", prefix, table.getName()); - table.setName(storesUpperCaseIdentifiers ? name.toUpperCase() : name.toLowerCase()); - prefixForeignKeys(table, prefix, storesUpperCaseIdentifiers); - prefixIndexes(table, prefix, storesUpperCaseIdentifiers); - prefixColumnNames(table, storesUpperCaseIdentifiers); - } - - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - - protected void prefixColumnNames(Table table, boolean storesUpperCaseIdentifiers) { - Column[] columns = table.getColumns(); - for (Column column : columns) { - column.setName(storesUpperCaseIdentifiers ? column.getName().toUpperCase() : column - .getName().toLowerCase()); - } - } - - protected void prefixForeignKeys(Table table, String tablePrefix, - boolean storesUpperCaseIdentifiers) throws CloneNotSupportedException { - ForeignKey[] keys = table.getForeignKeys(); - for (ForeignKey key : keys) { - String prefixedName = tablePrefix + key.getForeignTableName(); - prefixedName = storesUpperCaseIdentifiers ? prefixedName.toUpperCase() : prefixedName - .toLowerCase(); - key.setForeignTableName(prefixedName); - - String keyName = tablePrefix + key.getName(); - keyName = storesUpperCaseIdentifiers ? keyName.toUpperCase() : keyName.toLowerCase(); - key.setName(keyName); - - Reference[] refs = key.getReferences(); - for (Reference reference : refs) { - reference.setForeignColumnName(storesUpperCaseIdentifiers ? reference - .getForeignColumnName().toUpperCase() : reference.getForeignColumnName() - .toLowerCase()); - reference.setLocalColumnName(storesUpperCaseIdentifiers ? reference - .getLocalColumnName().toUpperCase() : reference.getLocalColumnName() - .toLowerCase()); - } - } - } - - protected void prefixIndexes(Table table, String tablePrefix, boolean storesUpperCaseIdentifiers) - throws CloneNotSupportedException { - IIndex[] indexes = table.getIndices(); - if (indexes != null) { - for (IIndex index : indexes) { - String prefixedName = tablePrefix + index.getName(); - prefixedName = storesUpperCaseIdentifiers ? prefixedName.toUpperCase() - : prefixedName.toLowerCase(); - index.setName(prefixedName); - } - } - } - - - public void alterCaseToMatchDatabaseDefaultCase(Database database) { - Table[] tables = database.getTables(); - for (Table table : tables) { - alterCaseToMatchDatabaseDefaultCase(table); - } - } - - public String[] alterCaseToMatchDatabaseDefaultCase(String[] values) { - String[] newValues = new String[values.length]; - for (int i = 0; i < values.length; i++) { - newValues[i] = alterCaseToMatchDatabaseDefaultCase(values[i]); - } - return newValues; - } - - public String alterCaseToMatchDatabaseDefaultCase(String value) { - if (StringUtils.isNotBlank(value)) { - boolean storesUpperCase = isStoresUpperCaseIdentifiers(); - if (!FormatUtils.isMixedCase(value)) { - value = storesUpperCase ? value.toUpperCase() : value.toLowerCase(); - } - } - return value; - } - - public void alterCaseToMatchDatabaseDefaultCase(Table... tables) { - for (Table table : tables) { - alterCaseToMatchDatabaseDefaultCase(table); - } - } - - public void alterCaseToMatchDatabaseDefaultCase(Table table) { - table.setName(alterCaseToMatchDatabaseDefaultCase(table.getName())); - - Column[] columns = table.getColumns(); - for (Column column : columns) { - column.setName(alterCaseToMatchDatabaseDefaultCase(column.getName())); - } - - IIndex[] indexes = table.getIndices(); - for (IIndex index : indexes) { - index.setName(alterCaseToMatchDatabaseDefaultCase(index.getName())); - - IndexColumn[] indexColumns = index.getColumns(); - for (IndexColumn indexColumn : indexColumns) { - indexColumn.setName(alterCaseToMatchDatabaseDefaultCase(indexColumn.getName())); - } - } - - ForeignKey[] fks = table.getForeignKeys(); - for (ForeignKey foreignKey : fks) { - foreignKey.setName(alterCaseToMatchDatabaseDefaultCase(foreignKey.getName())); - foreignKey.setForeignTableName(alterCaseToMatchDatabaseDefaultCase(foreignKey.getForeignTableName())); - Reference[] references = foreignKey.getReferences(); - for (Reference reference : references) { - reference.setForeignColumnName(alterCaseToMatchDatabaseDefaultCase(reference.getForeignColumnName())); - reference.setLocalColumnName(alterCaseToMatchDatabaseDefaultCase(reference.getLocalColumnName())); - } - } - } - - public Database readDatabaseFromXml(InputStream is, boolean alterCaseToMatchDatabaseDefaultCase) { - InputStreamReader reader = new InputStreamReader(is); - Database database = DatabaseXmlUtil.read(reader); - if (alterCaseToMatchDatabaseDefaultCase) { - alterCaseToMatchDatabaseDefaultCase(database); - } - return database; - - } - - public boolean canColumnBeUsedInWhereClause(Column column) { - return true; - } - - public java.util.Date parseTimestamp(int type, String value) { - try { - return Timestamp.valueOf(value); - } catch (IllegalArgumentException ex) { - try { - return new Timestamp(FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS).getTime()); - } catch (Exception e) { - int split = value.lastIndexOf(" "); - String datetime = value.substring(0, split).trim(); - String timezone = value.substring(split).trim(); - - try { - return Timestamp.valueOf(datetime); // Try it again without the timezone component. - } catch (IllegalArgumentException ex2) { - return new Timestamp(FormatUtils.parseDate(datetime, - FormatUtils.TIMESTAMP_PATTERNS, - getTimeZone(timezone)).getTime()); - } - } - } - } - - public TimeZone getTimeZone(String value) { - TimeZone tz = TimeZone.getTimeZone("GMT" + value); // try as an offset. ("-05:00") - if (tz.getRawOffset() == 0) { - tz = TimeZone.getTimeZone(value); // try as a raw code. e.g. "EST" - } - return tz; - } - - @Override - public void makePlatformSpecific(Database database) { - Table[] tables = database.getTables(); - for (Table table : tables) { - for (Column autoIncrementColumn : table.getAutoIncrementColumns()) { - if (!autoIncrementColumn.isPrimaryKey() && !getDatabaseInfo().isNonPKIdentityColumnsSupported()) { - log.info("Removing auto increment from table " + table.getName() + " for column " + autoIncrementColumn.getName() + - " since it was not part of primary key and not supported on this database based on nonPKIdentityColumnsSupported."); - autoIncrementColumn.setAutoIncrement(false); - } - } - } - } - -} +package org.jumpmind.db.platform; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import static org.apache.commons.lang.StringUtils.isNotBlank; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Array; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.regex.Pattern; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.time.DateUtils; +import org.jumpmind.db.io.DatabaseXmlUtil; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.model.ColumnTypes; +import org.jumpmind.db.model.Database; +import org.jumpmind.db.model.ForeignKey; +import org.jumpmind.db.model.IIndex; +import org.jumpmind.db.model.IndexColumn; +import org.jumpmind.db.model.Reference; +import org.jumpmind.db.model.Table; +import org.jumpmind.db.model.TypeMap; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.DmlStatement; +import org.jumpmind.db.sql.DmlStatement.DmlType; +import org.jumpmind.db.sql.ISqlTemplate; +import org.jumpmind.db.sql.Row; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlScript; +import org.jumpmind.db.util.BinaryEncoding; +import org.jumpmind.exception.IoException; +import org.jumpmind.util.FormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/* + * Base class for platform implementations. + */ +public abstract class AbstractDatabasePlatform implements IDatabasePlatform { + + /* The log for this platform. */ + protected final Logger log = LoggerFactory.getLogger(getClass()); + + public static final String REQUIRED_FIELD_NULL_SUBSTITUTE = " "; + + /* The default name for models read from the database, if no name as given. */ + protected static final String MODEL_DEFAULT_NAME = "default"; + + protected static final String PERMISSION_TEST_TABLE_NAME = "SYM_PERMISSION_TEST"; + + /* The model reader for this platform. */ + protected IDdlReader ddlReader; + + protected IDdlBuilder ddlBuilder; + + protected Map tableCache = new HashMap(); + + private long lastTimeCachedModelClearedInMs = System.currentTimeMillis(); + + protected long clearCacheModelTimeoutInMs = DateUtils.MILLIS_PER_HOUR; + + protected String defaultSchema; + + protected String defaultCatalog; + + protected Boolean storesUpperCaseIdentifiers; + + protected Boolean storesLowerCaseIdentifiers; + + protected Boolean storesMixedCaseIdentifiers; + + protected boolean metadataIgnoreCase = true; + + public AbstractDatabasePlatform() { + } + + public DatabaseInfo getDatabaseInfo() { + return getDdlBuilder().getDatabaseInfo(); + } + + abstract public ISqlTemplate getSqlTemplate(); + + abstract public ISqlTemplate getSqlTemplateDirty(); + + public DmlStatement createDmlStatement(DmlType dmlType, Table table, String textColumnExpression) { + + return createDmlStatement(dmlType, table.getCatalog(), table.getSchema(), table.getName(), + table.getPrimaryKeyColumns(), table.getColumns(), null, textColumnExpression); + } + + public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, + String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression) { + + return DmlStatementFactory.createDmlStatement(getName(), dmlType, catalogName, schemaName, + tableName, keys, columns, nullKeyValues, getDdlBuilder(), textColumnExpression); + } + + public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, + String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression, + boolean namedParameters) { + + return DmlStatementFactory.createDmlStatement(getName(), dmlType, catalogName, schemaName, + tableName, keys, columns, nullKeyValues, getDdlBuilder(), textColumnExpression, + namedParameters); + + } + + + public IDdlReader getDdlReader() { + return ddlReader; + } + + public IDdlBuilder getDdlBuilder() { + return ddlBuilder; + } + + public void setClearCacheModelTimeoutInMs(long clearCacheModelTimeoutInMs) { + this.clearCacheModelTimeoutInMs = clearCacheModelTimeoutInMs; + } + + public long getClearCacheModelTimeoutInMs() { + return clearCacheModelTimeoutInMs; + } + + public void dropTables(boolean continueOnError, Table...tables) { + Database db = new Database(); + for (Table table : tables) { + db.addTable(table); + } + dropDatabase(db, continueOnError); + } + + public void dropDatabase(Database database, boolean continueOnError) { + String sql = ddlBuilder.dropTables(database); + new SqlScript(sql, getSqlTemplate(), !continueOnError, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); + } + + public void createTables(boolean dropTablesFirst, boolean continueOnError, Table... tables) { + Database database = new Database(); + database.addTables(tables); + createDatabase(database, dropTablesFirst, continueOnError); + } + + public void createDatabase(Database targetDatabase, boolean dropTablesFirst, + boolean continueOnError) { + if (dropTablesFirst) { + dropDatabase(targetDatabase, true); + } + + String createSql = ddlBuilder.createTables(targetDatabase, false); + + if (log.isDebugEnabled()) { + log.debug("Generated create sql: \n{}", createSql); + } + + String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter(); + new SqlScript(createSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); + } + + public void alterDatabase(Database desiredDatabase, boolean continueOnError) { + alterTables(continueOnError, desiredDatabase.getTables()); + } + + public void alterTables(boolean continueOnError, Table... desiredTables) { + Database currentDatabase = new Database(); + Database desiredDatabase = new Database(); + StringBuilder tablesProcessed = new StringBuilder(); + for (Table table : desiredTables) { + tablesProcessed.append(table.getFullyQualifiedTableName()); + tablesProcessed.append(", "); + desiredDatabase.addTable(table); + Table currentTable = ddlReader.readTable(table.getCatalog(), table.getSchema(), + table.getName()); + if (currentTable != null) { + currentDatabase.addTable(currentTable); + } + } + + if (tablesProcessed.length() > 1) { + tablesProcessed.replace(tablesProcessed.length() - 2, tablesProcessed.length(), ""); + } + + String alterSql = ddlBuilder.alterDatabase(currentDatabase, desiredDatabase); + + if (StringUtils.isNotBlank(alterSql.trim())) { + log.info("Running alter sql:\n{}", alterSql); + String delimiter = getDdlBuilder().getDatabaseInfo().getSqlCommandDelimiter(); + new SqlScript(alterSql, getSqlTemplate(), !continueOnError, false, false, delimiter, null).execute(getDatabaseInfo().isRequiresAutoCommitForDdl()); + } else { + log.info("Tables up to date. No alters found for {}", tablesProcessed); + } + + } + + public Database readDatabase(String catalog, String schema, String[] tableTypes) { + Database model = ddlReader.readTables(catalog, schema, tableTypes); + if ((model.getName() == null) || (model.getName().length() == 0)) { + model.setName(MODEL_DEFAULT_NAME); + } + return model; + } + + + public Database readFromDatabase(Table... tables) { + Database fromDb = new Database(); + for (Table tableFromXml : tables) { + Table tableFromDatabase = getTableFromCache(tableFromXml.getCatalog(), + tableFromXml.getSchema(), tableFromXml.getName(), true); + if (tableFromDatabase != null) { + fromDb.addTable(tableFromDatabase); + } + } + fromDb.initialize(); + return fromDb; + } + + public Table readTableFromDatabase(String catalogName, String schemaName, String tableName) { + String originalFullyQualifiedName = Table.getFullyQualifiedTableName(catalogName, + schemaName, tableName); + String defaultedCatalogName = catalogName == null ? getDefaultCatalog() : catalogName; + String defaultedSchemaName = schemaName == null ? getDefaultSchema() : schemaName; + + Table table = ddlReader.readTable(defaultedCatalogName, defaultedSchemaName, tableName); + if (table == null && metadataIgnoreCase) { + + IDdlReader reader = getDdlReader(); + + if (isNotBlank(catalogName)) { + List catalogNames = reader.getCatalogNames(); + if (catalogNames != null) { + for (String name : catalogNames) { + if (name != null && name.equalsIgnoreCase(catalogName)) { + defaultedCatalogName = name; + break; + } + } + } + } + + if (isNotBlank(schemaName)) { + List schemaNames = reader.getSchemaNames(catalogName); + if (schemaNames != null) { + for (String name : schemaNames) { + if (name != null && name.equalsIgnoreCase(schemaName)) { + defaultedSchemaName = name; + break; + } + } + } + } + + + List tableNames = reader.getTableNames(defaultedCatalogName, defaultedSchemaName, null); + if (tableNames != null) { + for (String name : tableNames) { + if (name != null && name.equalsIgnoreCase(tableName)) { + tableName = name; + break; + } + } + } + + if (!originalFullyQualifiedName.equals(Table.getFullyQualifiedTableName( + defaultedCatalogName, defaultedSchemaName, tableName))) { + table = ddlReader.readTable(defaultedCatalogName, defaultedSchemaName, tableName); + } + + } + + if (table != null && log.isDebugEnabled()) { + log.debug("Just read table: \n{}", table.toVerboseString()); + } + return table; + } + + public void resetCachedTableModel() { + synchronized (this.getClass()) { + this.tableCache = new HashMap(); + lastTimeCachedModelClearedInMs = System.currentTimeMillis(); + } + } + + public Table getTableFromCache(String tableName, boolean forceReread) { + return getTableFromCache(getDefaultCatalog(), getDefaultSchema(), tableName, forceReread); + } + + public Table getTableFromCache(String catalogName, String schemaName, String tableName, + boolean forceReread) { + if (System.currentTimeMillis() - lastTimeCachedModelClearedInMs > clearCacheModelTimeoutInMs) { + resetCachedTableModel(); + } + Map model = tableCache; + String key = Table.getFullyQualifiedTableName(catalogName, schemaName, tableName); + Table retTable = model != null ? model.get(key) : null; + if (retTable == null || forceReread) { + synchronized (this.getClass()) { + try { + Table table = readTableFromDatabase(catalogName, schemaName, tableName); + tableCache.put(key, table); + retTable = table; + } catch (RuntimeException ex) { + throw ex; + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + } + return retTable; + } + + public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, + String[] values) { + Column[] metaData = Table.orderColumns(columnNames, table); + return getObjectValues(encoding, values, metaData); + } + + public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, + String[] values, boolean useVariableDates, boolean fitToColumn) { + Column[] metaData = Table.orderColumns(columnNames, table); + return getObjectValues(encoding, values, metaData, useVariableDates, fitToColumn); + } + + public Object[] getObjectValues(BinaryEncoding encoding, String[] values, + Column[] orderedMetaData) { + return getObjectValues(encoding, values, orderedMetaData, false, false); + } + + public Object[] getObjectValues(BinaryEncoding encoding, String[] values, + Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn) { + if (values != null) { + List list = new ArrayList(values.length); + for (int i = 0; i < values.length; i++) { + String value = values[i]; + Column column = orderedMetaData.length > i ? orderedMetaData[i] : null; + try { + if (column != null) { + list.add(getObjectValue(value, column, encoding, useVariableDates, fitToColumn)); + } + } catch (Exception ex) { + String valueTrimmed = FormatUtils.abbreviateForLogging(value); + throw new RuntimeException("Could not convert a value of " + valueTrimmed + " for column " + + column.getName() + " of type " + column.getMappedType(), ex); + } + } + + return list.toArray(); + } else { + return null; + } + } + + protected Object getObjectValue(String value, Column column, BinaryEncoding encoding, + boolean useVariableDates, boolean fitToColumn) throws DecoderException { + Object objectValue = value; + int type = column.getMappedTypeCode(); + if ((value == null || (getDdlBuilder().getDatabaseInfo().isEmptyStringNulled() && value + .equals(""))) && column.isRequired() && column.isOfTextType()) { + objectValue = REQUIRED_FIELD_NULL_SUBSTITUTE; + } + if (value != null) { + if (type == Types.DATE || type == Types.TIMESTAMP || type == Types.TIME) { + objectValue = parseDate(type, value, useVariableDates); + } else if (type == Types.CHAR) { + String charValue = value.toString(); + if ((StringUtils.isBlank(charValue) && getDdlBuilder().getDatabaseInfo() + .isBlankCharColumnSpacePadded()) + || (StringUtils.isNotBlank(charValue) && getDdlBuilder().getDatabaseInfo() + .isNonBlankCharColumnSpacePadded())) { + objectValue = StringUtils + .rightPad(value.toString(), column.getSizeAsInt(), ' '); + } + } else if (type == Types.BIGINT) { + objectValue = parseBigInteger(value); + } else if (type == Types.INTEGER || type == Types.SMALLINT || type == Types.BIT || type == Types.TINYINT) { + objectValue = parseInteger(value); + } else if (type == Types.FLOAT) { + objectValue = parseFloat(value); + } else if (type == Types.NUMERIC || type == Types.DECIMAL + || type == Types.DOUBLE || type == Types.REAL) { + objectValue = parseBigDecimal(value); + } else if (type == Types.BOOLEAN) { + objectValue = value.equals("1") ? Boolean.TRUE : Boolean.FALSE; + } else if (!(column.getJdbcTypeName() != null && column.getJdbcTypeName().toUpperCase() + .contains(TypeMap.GEOMETRY)) + && !(column.getJdbcTypeName() != null && column.getJdbcTypeName().toUpperCase() + .contains(TypeMap.GEOGRAPHY)) + && (type == Types.BLOB || type == Types.LONGVARBINARY || type == Types.BINARY + || type == Types.VARBINARY || + // SQLServer ntext type + type == -10)) { + if (encoding == BinaryEncoding.NONE) { + objectValue = value.getBytes(); + } else if (encoding == BinaryEncoding.BASE64) { + objectValue = Base64.decodeBase64(value.getBytes()); + } else if (encoding == BinaryEncoding.HEX) { + objectValue = Hex.decodeHex(value.toCharArray()); + } + } else if (type == Types.ARRAY) { + objectValue = createArray(column, value); + } + } + if (objectValue instanceof String) { + String stringValue = cleanTextForTextBasedColumns((String) objectValue); + int size = column.getSizeAsInt(); + if (fitToColumn && size > 0 && stringValue.length() > size) { + stringValue = stringValue.substring(0, size); + } + objectValue = stringValue; + } + + return objectValue; + + } + + protected Object parseFloat(String value) { + return parseBigDecimal(value); + } + + protected Object parseBigDecimal(String value) { + /* + * The number will have either one period or one comma for the decimal + * point, but we need a period + */ + value = cleanNumber(value); + return new BigDecimal(value.replace(',', '.')); + } + + protected Object parseBigInteger(String value) { + try { + value = cleanNumber(value); + return new Long(value.trim()); + } catch (NumberFormatException ex) { + return new BigDecimal(value.replace(',', '.')).toBigInteger(); + } + } + + protected Object parseInteger(String value) { + try { + value = cleanNumber(value); + return Integer.parseInt(value); + } catch (NumberFormatException ex) { + return new BigInteger(value); + } + } + + protected String cleanNumber(String value) { + value = value.trim(); + if (value.equalsIgnoreCase("true")) { + return "1"; + } else if (value.equalsIgnoreCase("false")) { + return "0"; + } else { + return value; + } + } + + // TODO: this should be AbstractDdlBuilder.getInsertSql(Table table, + // Map columnValues, boolean genPlaceholders) + public String[] getStringValues(BinaryEncoding encoding, Column[] metaData, Row row, + boolean useVariableDates, boolean indexByPosition) { + String[] values = new String[metaData.length]; + Set keys = row.keySet(); + int i = 0; + for (String key : keys) { + Column column = metaData[i]; + String name = indexByPosition ? key : column.getName(); + int type = column.getJdbcTypeCode(); + if (row.get(name) != null) { + if (type == Types.BOOLEAN || type == Types.BIT) { + values[i] = row.getBoolean(name) ? "1" : "0"; + } else if (column.isOfNumericType()) { + values[i] = row.getString(name); + } else if (!column.isTimestampWithTimezone() + && (type == Types.DATE || type == Types.TIMESTAMP || type == Types.TIME)) { + values[i] = getDateTimeStringValue(name, type, row, useVariableDates); + } else if (column.isOfBinaryType()) { + byte[] bytes = row.getBytes(name); + if (encoding == BinaryEncoding.NONE) { + values[i] = row.getString(name); + } else if (encoding == BinaryEncoding.BASE64) { + values[i] = new String(Base64.encodeBase64(bytes)); + } else if (encoding == BinaryEncoding.HEX) { + values[i] = new String(Hex.encodeHex(bytes)); + } + } else { + values[i] = row.getString(name); + } + } + + i++; + } + return values; + } + + protected String getDateTimeStringValue(String name, int type, Row row, boolean useVariableDates) { + Object dateObj = row.get(name); + if (dateObj instanceof String) { + return (String) dateObj; + } else { + Date date = row.getDateTime(name); + if (useVariableDates) { + long diff = date.getTime() - System.currentTimeMillis(); + return "${curdate" + diff + "}"; + } else { + return FormatUtils.TIMESTAMP_FORMATTER.format(date); + } + } + } + + public Map getSqlScriptReplacementTokens() { + return null; + } + + public String scrubSql(String sql) { + Map replacementTokens = getSqlScriptReplacementTokens(); + if (replacementTokens != null) { + return FormatUtils.replaceTokens(sql, replacementTokens, false).trim(); + } else { + return sql; + } + } + + protected Array createArray(Column column, final String value) { + return null; + } + + protected String cleanTextForTextBasedColumns(String text) { + return text; + } + + public java.util.Date parseDate(int type, String value, boolean useVariableDates) { + if (StringUtils.isNotBlank(value)) { + try { + boolean useTimestamp = (type == Types.TIMESTAMP) + || (type == Types.DATE && getDdlBuilder().getDatabaseInfo() + .isDateOverridesToTimestamp()); + + if (useVariableDates && value.startsWith("${curdate")) { + long time = Long.parseLong(value.substring(10, value.length() - 1)); + if (value.substring(9, 10).equals("-")) { + time *= -1L; + } + time += System.currentTimeMillis(); + if (useTimestamp) { + return new Timestamp(time); + } + return new Date(time); + } else { + if (useTimestamp) { + return parseTimestamp(type, value); + } else if (type == Types.TIME) { + if (value.indexOf(".") == 8) { + /* + * Firebird (at least) captures fractional seconds + * in time fields which need to be parsed by + * Timestamp.valueOf + */ + return Timestamp.valueOf("1970-01-01 " + value); + } else { + return FormatUtils.parseDate(value, FormatUtils.TIME_PATTERNS); + } + } else { + return FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS); + } + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException(e); + } + } else { + return null; + } + } + + @Override + public Map parseQualifiedTableName(String tableName) { + + Map tableNameParts = new LinkedHashMap(); + if (StringUtils.isEmpty(tableName)) { + return tableNameParts; + } + + String[] initialSplit = tableName.split(Pattern.quote(getDatabaseInfo().getCatalogSeparator())); + if (initialSplit.length == 0) { + initialSplit = new String[] {tableName}; + } + List nameComponents = new ArrayList(); + for (String part : initialSplit) { + String[] subParts = part.split(Pattern.quote(getDatabaseInfo().getSchemaSeparator())); + if (subParts.length == 0) { + subParts = new String[] {part}; + } + for (String subPart : subParts) { + if (!StringUtils.isEmpty(subPart)) { + nameComponents.add(subPart); + } + } + } + + if (nameComponents.size() >= 3) { + tableNameParts.put("catalog", nameComponents.get(0)); + tableNameParts.put("schema", nameComponents.get(1)); + tableNameParts.put("table", nameComponents.get(2)); + } else if (nameComponents.size() == 2) { + tableNameParts.put("schema", nameComponents.get(0)); + tableNameParts.put("table", nameComponents.get(1)); + } else { + tableNameParts.put("table", nameComponents.get(0)); + } + + return tableNameParts; + } + + public Table makeAllColumnsPrimaryKeys(Table table) { + Table result = table.copy(); + for (Column column : result.getColumns()) { + if (!isLob(column.getMappedTypeCode())) { + column.setPrimaryKey(true); + } + } + return result; + } + + public boolean isLob(int type) { + return isClob(type) || isBlob(type); + } + + public boolean isClob(int type) { + return type == Types.CLOB || type == Types.NCLOB || type == Types.LONGVARCHAR || type == ColumnTypes.LONGNVARCHAR; + } + + public boolean isBlob(int type) { + return type == Types.BLOB || type == Types.BINARY || type == Types.VARBINARY || type == Types.LONGVARBINARY || type == -10; + } + + public List getLobColumns(Table table) { + List lobColumns = new ArrayList(1); + Column[] allColumns = table.getColumns(); + for (Column column : allColumns) { + if (isLob(column.getMappedTypeCode())) { + lobColumns.add(column); + } + } + return lobColumns; + } + + public void setMetadataIgnoreCase(boolean metadataIgnoreCase) { + this.metadataIgnoreCase = metadataIgnoreCase; + } + + public boolean isMetadataIgnoreCase() { + return metadataIgnoreCase; + } + + public boolean isStoresLowerCaseIdentifiers() { + if (storesLowerCaseIdentifiers == null) { + storesLowerCaseIdentifiers = getSqlTemplate().isStoresLowerCaseIdentifiers(); + } + return storesLowerCaseIdentifiers; + } + + public boolean isStoresMixedCaseQuotedIdentifiers() { + if (storesMixedCaseIdentifiers == null) { + storesMixedCaseIdentifiers = getSqlTemplate().isStoresMixedCaseQuotedIdentifiers(); + } + return storesMixedCaseIdentifiers; + } + + public boolean isStoresUpperCaseIdentifiers() { + if (storesUpperCaseIdentifiers == null) { + storesUpperCaseIdentifiers = getSqlTemplate().isStoresUpperCaseIdentifiers(); + } + return storesUpperCaseIdentifiers; + } + + public Database readDatabaseFromXml(String filePath, boolean alterCaseToMatchDatabaseDefaultCase) { + InputStream is = null; + try { + File file = new File(filePath); + if (file.exists()) { + try { + is = new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new IoException(e); + } + } else { + is = AbstractDatabasePlatform.class.getResourceAsStream(filePath); + } + + if (is != null) { + return readDatabaseFromXml(is, alterCaseToMatchDatabaseDefaultCase); + } else { + throw new IoException("Could not find the file: %s", filePath); + } + } finally { + IOUtils.closeQuietly(is); + } + } + + public void prefixDatabase(String prefix, Database targetTables) { + try { + if (StringUtils.isNotBlank(prefix) && !prefix.endsWith("_")) { + prefix = prefix + "_"; + } + Table[] tables = targetTables.getTables(); + + boolean storesUpperCaseIdentifiers = isStoresUpperCaseIdentifiers(); + for (Table table : tables) { + String name = String.format("%s%s", prefix, table.getName()); + table.setName(storesUpperCaseIdentifiers ? name.toUpperCase() : name.toLowerCase()); + prefixForeignKeys(table, prefix, storesUpperCaseIdentifiers); + prefixIndexes(table, prefix, storesUpperCaseIdentifiers); + prefixColumnNames(table, storesUpperCaseIdentifiers); + } + + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + + protected void prefixColumnNames(Table table, boolean storesUpperCaseIdentifiers) { + Column[] columns = table.getColumns(); + for (Column column : columns) { + column.setName(storesUpperCaseIdentifiers ? column.getName().toUpperCase() : column + .getName().toLowerCase()); + } + } + + protected void prefixForeignKeys(Table table, String tablePrefix, + boolean storesUpperCaseIdentifiers) throws CloneNotSupportedException { + ForeignKey[] keys = table.getForeignKeys(); + for (ForeignKey key : keys) { + String prefixedName = tablePrefix + key.getForeignTableName(); + prefixedName = storesUpperCaseIdentifiers ? prefixedName.toUpperCase() : prefixedName + .toLowerCase(); + key.setForeignTableName(prefixedName); + + String keyName = tablePrefix + key.getName(); + keyName = storesUpperCaseIdentifiers ? keyName.toUpperCase() : keyName.toLowerCase(); + key.setName(keyName); + + Reference[] refs = key.getReferences(); + for (Reference reference : refs) { + reference.setForeignColumnName(storesUpperCaseIdentifiers ? reference + .getForeignColumnName().toUpperCase() : reference.getForeignColumnName() + .toLowerCase()); + reference.setLocalColumnName(storesUpperCaseIdentifiers ? reference + .getLocalColumnName().toUpperCase() : reference.getLocalColumnName() + .toLowerCase()); + } + } + } + + protected void prefixIndexes(Table table, String tablePrefix, boolean storesUpperCaseIdentifiers) + throws CloneNotSupportedException { + IIndex[] indexes = table.getIndices(); + if (indexes != null) { + for (IIndex index : indexes) { + String prefixedName = tablePrefix + index.getName(); + prefixedName = storesUpperCaseIdentifiers ? prefixedName.toUpperCase() + : prefixedName.toLowerCase(); + index.setName(prefixedName); + } + } + } + + + public void alterCaseToMatchDatabaseDefaultCase(Database database) { + Table[] tables = database.getTables(); + for (Table table : tables) { + alterCaseToMatchDatabaseDefaultCase(table); + } + } + + public String[] alterCaseToMatchDatabaseDefaultCase(String[] values) { + String[] newValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + newValues[i] = alterCaseToMatchDatabaseDefaultCase(values[i]); + } + return newValues; + } + + public String alterCaseToMatchDatabaseDefaultCase(String value) { + if (StringUtils.isNotBlank(value)) { + boolean storesUpperCase = isStoresUpperCaseIdentifiers(); + if (!FormatUtils.isMixedCase(value)) { + value = storesUpperCase ? value.toUpperCase() : value.toLowerCase(); + } + } + return value; + } + + public void alterCaseToMatchDatabaseDefaultCase(Table... tables) { + for (Table table : tables) { + alterCaseToMatchDatabaseDefaultCase(table); + } + } + + public void alterCaseToMatchDatabaseDefaultCase(Table table) { + table.setName(alterCaseToMatchDatabaseDefaultCase(table.getName())); + + Column[] columns = table.getColumns(); + for (Column column : columns) { + column.setName(alterCaseToMatchDatabaseDefaultCase(column.getName())); + } + + IIndex[] indexes = table.getIndices(); + for (IIndex index : indexes) { + index.setName(alterCaseToMatchDatabaseDefaultCase(index.getName())); + + IndexColumn[] indexColumns = index.getColumns(); + for (IndexColumn indexColumn : indexColumns) { + indexColumn.setName(alterCaseToMatchDatabaseDefaultCase(indexColumn.getName())); + } + } + + ForeignKey[] fks = table.getForeignKeys(); + for (ForeignKey foreignKey : fks) { + foreignKey.setName(alterCaseToMatchDatabaseDefaultCase(foreignKey.getName())); + foreignKey.setForeignTableName(alterCaseToMatchDatabaseDefaultCase(foreignKey.getForeignTableName())); + Reference[] references = foreignKey.getReferences(); + for (Reference reference : references) { + reference.setForeignColumnName(alterCaseToMatchDatabaseDefaultCase(reference.getForeignColumnName())); + reference.setLocalColumnName(alterCaseToMatchDatabaseDefaultCase(reference.getLocalColumnName())); + } + } + } + + public Database readDatabaseFromXml(InputStream is, boolean alterCaseToMatchDatabaseDefaultCase) { + InputStreamReader reader = new InputStreamReader(is); + Database database = DatabaseXmlUtil.read(reader); + if (alterCaseToMatchDatabaseDefaultCase) { + alterCaseToMatchDatabaseDefaultCase(database); + } + return database; + + } + + public boolean canColumnBeUsedInWhereClause(Column column) { + return true; + } + + public java.util.Date parseTimestamp(int type, String value) { + try { + return Timestamp.valueOf(value); + } catch (IllegalArgumentException ex) { + try { + return new Timestamp(FormatUtils.parseDate(value, FormatUtils.TIMESTAMP_PATTERNS).getTime()); + } catch (Exception e) { + int split = value.lastIndexOf(" "); + String datetime = value.substring(0, split).trim(); + String timezone = value.substring(split).trim(); + + try { + return Timestamp.valueOf(datetime); // Try it again without the timezone component. + } catch (IllegalArgumentException ex2) { + return new Timestamp(FormatUtils.parseDate(datetime, + FormatUtils.TIMESTAMP_PATTERNS, + getTimeZone(timezone)).getTime()); + } + } + } + } + + public TimeZone getTimeZone(String value) { + TimeZone tz = TimeZone.getTimeZone("GMT" + value); // try as an offset. ("-05:00") + if (tz.getRawOffset() == 0) { + tz = TimeZone.getTimeZone(value); // try as a raw code. e.g. "EST" + } + return tz; + } + + @Override + public void makePlatformSpecific(Database database) { + Table[] tables = database.getTables(); + for (Table table : tables) { + for (Column autoIncrementColumn : table.getAutoIncrementColumns()) { + if (!autoIncrementColumn.isPrimaryKey() && !getDatabaseInfo().isNonPKIdentityColumnsSupported()) { + log.info("Removing auto increment from table " + table.getName() + " for column " + autoIncrementColumn.getName() + + " since it was not part of primary key and not supported on this database based on nonPKIdentityColumnsSupported."); + autoIncrementColumn.setAutoIncrement(false); + } + } + } + } + + public List checkSymTablePermissions(PermissionType... permissionTypes) { + List results = new ArrayList(); + Database database = new Database(); + PermissionResult createResult = getCreateSymTablePermission(database); + PermissionResult createTriggerResult = getCreateSymTriggerPermission(); + PermissionResult dropTriggerResult = getDropSymTriggerPermission(); + boolean drop = false; + for (PermissionType permissionType : permissionTypes) { + switch (permissionType) { + case CREATE_TABLE: + results.add(createResult); + break; + case ALTER_TABLE: + PermissionResult alterResult = getAlterSymTablePermission(database); + results.add(alterResult); + break; + case CREATE_TRIGGER: + results.add(createTriggerResult); + break; + case DROP_TRIGGER: + results.add(dropTriggerResult); + break; + case EXECUTE: + PermissionResult executeResult = getExecuteSymPermission(); + results.add(executeResult); + break; + case DROP_TABLE: + drop = true; + break; + case CREATE_FUNCTION: + PermissionResult createFunctionResult = getCreateSymFunctionPermission(); + results.add(createFunctionResult); + break; + case CREATE_ROUTINE: + PermissionResult createRoutineResult = getCreateSymRoutinePermission(); + results.add(createRoutineResult); + break; + } + } + PermissionResult dropPermission = getDropSymTablePermission(); + if (drop) { + results.add(dropPermission); + } + return results; + } + + protected PermissionResult getCreateSymTablePermission(Database database) { + Column idColumn = new Column("TEST_ID"); + idColumn.setMappedType("INTEGER"); + Column valueColumn = new Column("TEST_VALUE"); + valueColumn.setMappedType("INTEGER"); + + Table table = new Table(PERMISSION_TEST_TABLE_NAME, idColumn, valueColumn); + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TABLE, Status.FAIL); + getDropSymTablePermission(); + + try { + database.addTable(table); + createDatabase(database, false, false); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE permission"); + } + + return result; + } + + protected PermissionResult getDropSymTablePermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + String dropSql = "DROP TABLE " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter; + + PermissionResult result = new PermissionResult(PermissionType.DROP_TABLE, Status.FAIL); + + try { + getSqlTemplate().update(dropSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant DROP permission"); + } + + return result; + } + + protected PermissionResult getAlterSymTablePermission(Database database) { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + Column idColumn = new Column("TEST_ID"); + idColumn.setMappedType("INTEGER"); + Column valueColumn = new Column("TEST_VALUE"); + valueColumn.setMappedType("INTEGER"); + Column alterColumn = new Column("TEST_ALTER"); + alterColumn.setMappedType("INTEGER"); + + Table table = new Table(PERMISSION_TEST_TABLE_NAME, idColumn, valueColumn); + Table alterTable = new Table(PERMISSION_TEST_TABLE_NAME, idColumn, valueColumn, alterColumn); + + PermissionResult result = new PermissionResult(PermissionType.ALTER_TABLE, Status.FAIL); + + try { + database.removeAllTablesExcept(); + database.addTable(alterTable); + alterDatabase(database, false); + database.removeAllTablesExcept(); + database.addTable(table); + alterDatabase(database, false); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant ALTER permission"); + } + + return result; + } + + protected PermissionResult getDropSymTriggerPermission() { + String dropTriggerSql = "DROP TRIGGER TEST_TRIGGER"; + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(dropTriggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant DROP TRIGGER permission or TRIGGER permission"); + } + + return result; + } + + protected PermissionResult getCreateSymTriggerPermission() { + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.UNIMPLEMENTED); + return result; + } + + protected PermissionResult getExecuteSymPermission() { + PermissionResult result = new PermissionResult(PermissionType.EXECUTE, Status.NOT_APPLICABLE); + return result; + } + + protected PermissionResult getCreateSymRoutinePermission() { + PermissionResult result = new PermissionResult(PermissionType.CREATE_ROUTINE, Status.NOT_APPLICABLE); + return result; + } + + protected PermissionResult getCreateSymFunctionPermission() { + PermissionResult result = new PermissionResult(PermissionType.CREATE_FUNCTION, Status.NOT_APPLICABLE); + return result; + } + +} diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDatabasePlatform.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDatabasePlatform.java index 76a8626d9e..49799fa05c 100644 --- a/symmetric-db/src/main/java/org/jumpmind/db/platform/IDatabasePlatform.java +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/IDatabasePlatform.java @@ -1,188 +1,190 @@ -package org.jumpmind.db.platform; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -import org.jumpmind.db.model.Column; -import org.jumpmind.db.model.Database; -import org.jumpmind.db.model.Table; -import org.jumpmind.db.sql.DmlStatement; -import org.jumpmind.db.sql.ISqlTemplate; -import org.jumpmind.db.sql.Row; -import org.jumpmind.db.sql.DmlStatement.DmlType; -import org.jumpmind.db.util.BinaryEncoding; - -/* - * A platform encapsulates the database-related functionality such as performing queries - * and manipulations. It also contains functionality to read and build DDL to create and - * alter database tables. - */ -public interface IDatabasePlatform { - - /** - * @see DatabaseNamesConstants - * @return a constant that represents this database type from {@link DatabaseNamesConstants} - */ - public String getName(); - - /** - * Returns information about this platform. - * - * @return The info object - */ - public DatabaseInfo getDatabaseInfo(); - - /** - * Returns a new ddl builder for the this platform. - */ - public IDdlBuilder getDdlBuilder(); - - /** - * Returns the ddl reader (which reads a database model from a live - * database) for this platform. - * - * @return The model reader - */ - public IDdlReader getDdlReader(); - - public ISqlTemplate getSqlTemplate(); - - public ISqlTemplate getSqlTemplateDirty(); - - /** - * The amount of time table metadata will be cached when using {@link IDatabasePlatform#getT - * @param clearCacheModelTimeoutInMs - */ - public void setClearCacheModelTimeoutInMs(long clearCacheModelTimeoutInMs); - - public long getClearCacheModelTimeoutInMs(); - - public String getDefaultSchema(); - - public String getDefaultCatalog(); - - /** - * Reads the database model from the live database to which the given - * connection is pointing. - */ - public Database readDatabase(String catalog, String schema, String[] tableTypes); - - public Database readFromDatabase(Table... tables); - - public Table readTableFromDatabase(String catalogName, String schemaName, String tablename); - - public void resetCachedTableModel(); - - public Table getTableFromCache(String tableName, boolean forceReread); - - public Table getTableFromCache(String catalogName, String schemaName, String tableName, - boolean forceReread); - - public void createDatabase(Database targetDatabase, boolean dropTablesFirst, - boolean continueOnError); - - public void createTables(boolean dropTablesFirst, - boolean continueOnError, Table... tables); - - public void alterDatabase(Database desiredDatabase, boolean continueOnError); - - public void alterTables(boolean continueOnError, Table... desiredTables); - - public void dropDatabase(Database database, boolean continueOnError); - - public void dropTables(boolean continueOnError, Table...tables); - - public DmlStatement createDmlStatement(DmlType dmlType, Table table, String textColumnExpression); - - public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, - String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression); - - public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, - String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression, - boolean namedParameters); - - public Object[] getObjectValues(BinaryEncoding encoding, String[] values, - Column[] orderedMetaData); - - public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, - String[] values); - - public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, - String[] values, boolean useVariableDates, boolean fitToColumn); - - public Object[] getObjectValues(BinaryEncoding encoding, String[] values, - Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn); - - public String[] getStringValues(BinaryEncoding encoding, Column[] metaData, Row row, boolean useVariableDates, boolean indexByPosition); - - public Database readDatabaseFromXml(String filePath, boolean alterCaseToMatchDatabaseDefaultCase); - - public Database readDatabaseFromXml(InputStream in, boolean alterCaseToMatchDatabaseDefaultCase); - - public String[] alterCaseToMatchDatabaseDefaultCase(String[] values); - - public String alterCaseToMatchDatabaseDefaultCase(String values); - - public void alterCaseToMatchDatabaseDefaultCase(Table table); - - public void alterCaseToMatchDatabaseDefaultCase(Table... tables); - - public void alterCaseToMatchDatabaseDefaultCase(Database database); - - public void prefixDatabase(String prefix, Database targetTables); - - public boolean isLob(int type); - - public boolean isClob(int type); - - public boolean isBlob(int type); - - public List getLobColumns(Table table); - - public Map getSqlScriptReplacementTokens(); - - public String scrubSql(String sql); - - public boolean isStoresLowerCaseIdentifiers(); - - public boolean isStoresUpperCaseIdentifiers(); - - public boolean isStoresMixedCaseQuotedIdentifiers(); - - public T getDataSource(); - - public void setMetadataIgnoreCase(boolean value); - - public boolean isMetadataIgnoreCase(); - - public java.util.Date parseDate(int type, String value, boolean useVariableDates); - - public Map parseQualifiedTableName(String tableName); - - public Table makeAllColumnsPrimaryKeys(Table table); - - public boolean canColumnBeUsedInWhereClause(Column column); - - public void makePlatformSpecific(Database database); - -} +package org.jumpmind.db.platform; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import org.jumpmind.db.model.Column; +import org.jumpmind.db.model.Database; +import org.jumpmind.db.model.Table; +import org.jumpmind.db.sql.DmlStatement; +import org.jumpmind.db.sql.ISqlTemplate; +import org.jumpmind.db.sql.Row; +import org.jumpmind.db.sql.DmlStatement.DmlType; +import org.jumpmind.db.util.BinaryEncoding; + +/* + * A platform encapsulates the database-related functionality such as performing queries + * and manipulations. It also contains functionality to read and build DDL to create and + * alter database tables. + */ +public interface IDatabasePlatform { + + /** + * @see DatabaseNamesConstants + * @return a constant that represents this database type from {@link DatabaseNamesConstants} + */ + public String getName(); + + /** + * Returns information about this platform. + * + * @return The info object + */ + public DatabaseInfo getDatabaseInfo(); + + /** + * Returns a new ddl builder for the this platform. + */ + public IDdlBuilder getDdlBuilder(); + + /** + * Returns the ddl reader (which reads a database model from a live + * database) for this platform. + * + * @return The model reader + */ + public IDdlReader getDdlReader(); + + public ISqlTemplate getSqlTemplate(); + + public ISqlTemplate getSqlTemplateDirty(); + + /** + * The amount of time table metadata will be cached when using {@link IDatabasePlatform#getT + * @param clearCacheModelTimeoutInMs + */ + public void setClearCacheModelTimeoutInMs(long clearCacheModelTimeoutInMs); + + public long getClearCacheModelTimeoutInMs(); + + public String getDefaultSchema(); + + public String getDefaultCatalog(); + + /** + * Reads the database model from the live database to which the given + * connection is pointing. + */ + public Database readDatabase(String catalog, String schema, String[] tableTypes); + + public Database readFromDatabase(Table... tables); + + public Table readTableFromDatabase(String catalogName, String schemaName, String tablename); + + public void resetCachedTableModel(); + + public Table getTableFromCache(String tableName, boolean forceReread); + + public Table getTableFromCache(String catalogName, String schemaName, String tableName, + boolean forceReread); + + public void createDatabase(Database targetDatabase, boolean dropTablesFirst, + boolean continueOnError); + + public void createTables(boolean dropTablesFirst, + boolean continueOnError, Table... tables); + + public void alterDatabase(Database desiredDatabase, boolean continueOnError); + + public void alterTables(boolean continueOnError, Table... desiredTables); + + public void dropDatabase(Database database, boolean continueOnError); + + public void dropTables(boolean continueOnError, Table...tables); + + public DmlStatement createDmlStatement(DmlType dmlType, Table table, String textColumnExpression); + + public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, + String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression); + + public DmlStatement createDmlStatement(DmlType dmlType, String catalogName, String schemaName, + String tableName, Column[] keys, Column[] columns, boolean[] nullKeyValues, String textColumnExpression, + boolean namedParameters); + + public Object[] getObjectValues(BinaryEncoding encoding, String[] values, + Column[] orderedMetaData); + + public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, + String[] values); + + public Object[] getObjectValues(BinaryEncoding encoding, Table table, String[] columnNames, + String[] values, boolean useVariableDates, boolean fitToColumn); + + public Object[] getObjectValues(BinaryEncoding encoding, String[] values, + Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn); + + public String[] getStringValues(BinaryEncoding encoding, Column[] metaData, Row row, boolean useVariableDates, boolean indexByPosition); + + public Database readDatabaseFromXml(String filePath, boolean alterCaseToMatchDatabaseDefaultCase); + + public Database readDatabaseFromXml(InputStream in, boolean alterCaseToMatchDatabaseDefaultCase); + + public String[] alterCaseToMatchDatabaseDefaultCase(String[] values); + + public String alterCaseToMatchDatabaseDefaultCase(String values); + + public void alterCaseToMatchDatabaseDefaultCase(Table table); + + public void alterCaseToMatchDatabaseDefaultCase(Table... tables); + + public void alterCaseToMatchDatabaseDefaultCase(Database database); + + public void prefixDatabase(String prefix, Database targetTables); + + public boolean isLob(int type); + + public boolean isClob(int type); + + public boolean isBlob(int type); + + public List getLobColumns(Table table); + + public Map getSqlScriptReplacementTokens(); + + public String scrubSql(String sql); + + public boolean isStoresLowerCaseIdentifiers(); + + public boolean isStoresUpperCaseIdentifiers(); + + public boolean isStoresMixedCaseQuotedIdentifiers(); + + public T getDataSource(); + + public void setMetadataIgnoreCase(boolean value); + + public boolean isMetadataIgnoreCase(); + + public java.util.Date parseDate(int type, String value, boolean useVariableDates); + + public Map parseQualifiedTableName(String tableName); + + public Table makeAllColumnsPrimaryKeys(Table table); + + public boolean canColumnBeUsedInWhereClause(Column column); + + public void makePlatformSpecific(Database database); + + public List checkSymTablePermissions(PermissionType... permissionTypes); + +} diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionResult.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionResult.java new file mode 100644 index 0000000000..0d19ec8a95 --- /dev/null +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionResult.java @@ -0,0 +1,116 @@ +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.db.platform; + +import java.util.Map; +import java.util.TreeMap; + +public class PermissionResult { + + public enum Status { + PASS, FAIL, UNIMPLEMENTED, UNSUPPORTED, NOT_APPLICABLE + } + + public enum PermissionCategory { + TABLE_MODIFICATION, TRIGGERS, ADDITIONAL + } + + private PermissionType permissionType; + + private Status status; + + private Exception exception; + + private String solution; + + private PermissionCategory category; + + private static Map categories = new TreeMap(); + + static { + categories.put(PermissionType.CREATE_TABLE, PermissionCategory.TABLE_MODIFICATION); + categories.put(PermissionType.DROP_TABLE, PermissionCategory.TABLE_MODIFICATION); + categories.put(PermissionType.ALTER_TABLE, PermissionCategory.TABLE_MODIFICATION); + categories.put(PermissionType.CREATE_TRIGGER, PermissionCategory.TRIGGERS); + categories.put(PermissionType.DROP_TRIGGER, PermissionCategory.TRIGGERS); + categories.put(PermissionType.CREATE_FUNCTION, PermissionCategory.ADDITIONAL); + categories.put(PermissionType.CREATE_ROUTINE, PermissionCategory.ADDITIONAL); + categories.put(PermissionType.EXECUTE, PermissionCategory.ADDITIONAL); + } + + public PermissionResult(PermissionType permissionType, Status status, Exception exception, String solution) { + this.setPermissionType(permissionType); + this.setStatus(status); + this.setException(exception); + this.setSolution(solution); + this.category = categories.get(permissionType); + } + + public PermissionResult(PermissionType permissionType, Status status) { + this.setPermissionType(permissionType); + this.setStatus(status); + this.category = categories.get(permissionType); + } + + public PermissionType getPermissionType() { + return permissionType; + } + + public void setPermissionType(PermissionType permissionType) { + this.permissionType = permissionType; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Exception getException() { + return exception; + } + + public void setException(Exception exception) { + this.exception = exception; + } + + public String getSolution() { + return solution; + } + + public void setSolution(String solution) { + this.solution = solution; + } + + public PermissionCategory getCategory() { + return category; + } + + public void setCategory(PermissionCategory category) { + this.category = category; + } + + public String toString() { + return "Permission Type: " + permissionType + ", Status: " + status; + } +} diff --git a/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionType.java b/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionType.java new file mode 100644 index 0000000000..13270cb425 --- /dev/null +++ b/symmetric-db/src/main/java/org/jumpmind/db/platform/PermissionType.java @@ -0,0 +1,25 @@ +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.db.platform; + +public enum PermissionType { + CREATE_TABLE, ALTER_TABLE, DROP_TABLE, CREATE_TRIGGER, DROP_TRIGGER, EXECUTE, CREATE_ROUTINE, CREATE_FUNCTION +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/ase/AseDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/ase/AseDatabasePlatform.java index 3907ca04a8..001d461bd4 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/ase/AseDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/ase/AseDatabasePlatform.java @@ -1,97 +1,121 @@ -package org.jumpmind.db.platform.ase; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.JdbcUtils; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for Sybase. - */ -public class AseDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Sybase jdbc driver. */ - public static final String JDBC_DRIVER = "com.sybase.jdbc4.jdbc.SybDriver"; - - /* The old Sybase jdbc driver. */ - public static final String JDBC_DRIVER_OLD = "com.sybase.jdbc4.jdbc.SybDriver"; - - /* The subprotocol used by the standard Sybase driver. */ - public static final String JDBC_SUBPROTOCOL = "sybase:Tds"; - - /* The maximum size that text and binary columns can have. */ - public static final long MAX_TEXT_SIZE = 2147483647; - - private Map sqlScriptReplacementTokens; - - public AseDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - - sqlScriptReplacementTokens = new HashMap(); - sqlScriptReplacementTokens.put("current_timestamp", "getdate()"); - } - - @Override - protected AseDdlBuilder createDdlBuilder() { - return new AseDdlBuilder(); - } - - @Override - protected AseDdlReader createDdlReader() { - return new AseDdlReader(this); - } - - @Override - protected AseJdbcSqlTemplate createSqlTemplate() { - return new AseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory()); - } - - public String getName() { - return DatabaseNamesConstants.ASE; - } - - public String getDefaultCatalog() { - if (StringUtils.isBlank(defaultCatalog)) { - defaultCatalog = getSqlTemplate().queryForObject("select DB_NAME()", String.class); - } - return defaultCatalog; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("select USER_NAME()", - String.class); - } - return defaultSchema; - } - - @Override - public Map getSqlScriptReplacementTokens() { - return sqlScriptReplacementTokens; - } -} +package org.jumpmind.db.platform.ase; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.JdbcUtils; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for Sybase. + */ +public class AseDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Sybase jdbc driver. */ + public static final String JDBC_DRIVER = "com.sybase.jdbc4.jdbc.SybDriver"; + + /* The old Sybase jdbc driver. */ + public static final String JDBC_DRIVER_OLD = "com.sybase.jdbc4.jdbc.SybDriver"; + + /* The subprotocol used by the standard Sybase driver. */ + public static final String JDBC_SUBPROTOCOL = "sybase:Tds"; + + /* The maximum size that text and binary columns can have. */ + public static final long MAX_TEXT_SIZE = 2147483647; + + private Map sqlScriptReplacementTokens; + + public AseDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + + sqlScriptReplacementTokens = new HashMap(); + sqlScriptReplacementTokens.put("current_timestamp", "getdate()"); + } + + @Override + protected AseDdlBuilder createDdlBuilder() { + return new AseDdlBuilder(); + } + + @Override + protected AseDdlReader createDdlReader() { + return new AseDdlReader(this); + } + + @Override + protected AseJdbcSqlTemplate createSqlTemplate() { + return new AseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory()); + } + + public String getName() { + return DatabaseNamesConstants.ASE; + } + + public String getDefaultCatalog() { + if (StringUtils.isBlank(defaultCatalog)) { + defaultCatalog = getSqlTemplate().queryForObject("select DB_NAME()", String.class); + } + return defaultCatalog; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("select USER_NAME()", + String.class); + } + return defaultSchema; + } + + @Override + public Map getSqlScriptReplacementTokens() { + return sqlScriptReplacementTokens; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "create trigger TEST_TRIGGER on " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " for insert as begin select 1 end"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2DatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2DatabasePlatform.java index 4d912885e9..19ec806311 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2DatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/db2/Db2DatabasePlatform.java @@ -1,83 +1,106 @@ -package org.jumpmind.db.platform.db2; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The DB2 platform implementation. - */ -public class Db2DatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard DB2 jdbc driver. */ - public static final String JDBC_DRIVER = "com.ibm.db2.jcc.DB2Driver"; - - /* The subprotocol used by the standard DB2 driver. */ - public static final String JDBC_SUBPROTOCOL = "db2"; - - /* - * Creates a new platform instance. - */ - public Db2DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected Db2DdlBuilder createDdlBuilder() { - return new Db2DdlBuilder(); - } - - @Override - protected Db2DdlReader createDdlReader() { - return new Db2DdlReader(this); - } - - @Override - protected Db2JdbcSqlTemplate createSqlTemplate() { - return new Db2JdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.DB2; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("select CURRENT SCHEMA from sysibm.sysdummy1", String.class); - } - return defaultSchema; - } - - public String getDefaultCatalog() { - return ""; - } - - @Override - public boolean canColumnBeUsedInWhereClause(Column column) { - return !column.isOfBinaryType(); - } - -} +package org.jumpmind.db.platform.db2; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The DB2 platform implementation. + */ +public class Db2DatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard DB2 jdbc driver. */ + public static final String JDBC_DRIVER = "com.ibm.db2.jcc.DB2Driver"; + + /* The subprotocol used by the standard DB2 driver. */ + public static final String JDBC_SUBPROTOCOL = "db2"; + + /* + * Creates a new platform instance. + */ + public Db2DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected Db2DdlBuilder createDdlBuilder() { + return new Db2DdlBuilder(); + } + + @Override + protected Db2DdlReader createDdlReader() { + return new Db2DdlReader(this); + } + + @Override + protected Db2JdbcSqlTemplate createSqlTemplate() { + return new Db2JdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.DB2; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("select CURRENT SCHEMA from sysibm.sysdummy1", String.class); + } + return defaultSchema; + } + + public String getDefaultCatalog() { + return ""; + } + + @Override + public boolean canColumnBeUsedInWhereClause(Column column) { + return !column.isOfBinaryType(); + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " FOR EACH ROW BEGIN ATOMIC END"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/derby/DerbyDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/derby/DerbyDatabasePlatform.java index b1c1831fc7..180b3b4e3a 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/derby/DerbyDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/derby/DerbyDatabasePlatform.java @@ -1,93 +1,118 @@ -package org.jumpmind.db.platform.derby; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import java.sql.Types; - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for Derby. - */ -public class DerbyDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The derby jdbc driver for use as a client for a normal server. */ - public static final String JDBC_DRIVER = "org.apache.derby.jdbc.ClientDriver"; - - /* The derby jdbc driver for use as an embedded database. */ - public static final String JDBC_DRIVER_EMBEDDED = "org.apache.derby.jdbc.EmbeddedDriver"; - - /* The subprotocol used by the derby drivers. */ - public static final String JDBC_SUBPROTOCOL = "derby"; - - /* - * Creates a new Derby platform instance. - */ - public DerbyDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected DerbyDdlBuilder createDdlBuilder() { - return new DerbyDdlBuilder(); - } - - @Override - protected DerbyDdlReader createDdlReader() { - return new DerbyDdlReader(this); - } - - @Override - protected DerbyJdbcSqlTemplate createSqlTemplate() { - return new DerbyJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.DERBY; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("values CURRENT SCHEMA", String.class); - } - return defaultSchema; - } - - public String getDefaultCatalog() { - return ""; - } - - @Override - public boolean isClob(int type) { - return type == Types.CLOB; - } - - @Override - public boolean canColumnBeUsedInWhereClause(Column column) { - return !column.isOfBinaryType(); - } - -} +package org.jumpmind.db.platform.derby; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.sql.Types; + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for Derby. + */ +public class DerbyDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The derby jdbc driver for use as a client for a normal server. */ + public static final String JDBC_DRIVER = "org.apache.derby.jdbc.ClientDriver"; + + /* The derby jdbc driver for use as an embedded database. */ + public static final String JDBC_DRIVER_EMBEDDED = "org.apache.derby.jdbc.EmbeddedDriver"; + + /* The subprotocol used by the derby drivers. */ + public static final String JDBC_SUBPROTOCOL = "derby"; + + /* + * Creates a new Derby platform instance. + */ + public DerbyDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected DerbyDdlBuilder createDdlBuilder() { + return new DerbyDdlBuilder(); + } + + @Override + protected DerbyDdlReader createDdlReader() { + return new DerbyDdlReader(this); + } + + @Override + protected DerbyJdbcSqlTemplate createSqlTemplate() { + return new DerbyJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.DERBY; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("values CURRENT SCHEMA", String.class); + } + return defaultSchema; + } + + public String getDefaultCatalog() { + return ""; + } + + @Override + public boolean isClob(int type) { + return type == Types.CLOB; + } + + @Override + public boolean canColumnBeUsedInWhereClause(Column column) { + return !column.isOfBinaryType(); + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " FOR EACH ROW MODE DB2SQL INSERT INTO " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " VALUES(NULL,NULL)"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } + +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/firebird/FirebirdDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/firebird/FirebirdDatabasePlatform.java index 10a7916054..b8c5afacc7 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/firebird/FirebirdDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/firebird/FirebirdDatabasePlatform.java @@ -1,74 +1,97 @@ -package org.jumpmind.db.platform.firebird; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for the Firebird database. - * It is assumed that the database is configured with sql dialect 3! - */ -public class FirebirdDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Firebird jdbc driver. */ - public static final String JDBC_DRIVER = "org.firebirdsql.jdbc.FBDriver"; - - /* The subprotocol used by the standard Firebird driver. */ - public static final String JDBC_SUBPROTOCOL = "firebirdsql"; - - /* - * Creates a new Firebird platform instance. - */ - public FirebirdDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected FirebirdDdlBuilder createDdlBuilder() { - return new FirebirdDdlBuilder(); - } - - @Override - protected FirebirdDdlReader createDdlReader() { - return new FirebirdDdlReader(this); - } - - @Override - protected FirebirdJdbcSqlTemplate createSqlTemplate() { - return new FirebirdJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.FIREBIRD; - } - - public String getDefaultCatalog() { - return null; - } - - public String getDefaultSchema() { - return null; - } - -} +package org.jumpmind.db.platform.firebird; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for the Firebird database. + * It is assumed that the database is configured with sql dialect 3! + */ +public class FirebirdDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Firebird jdbc driver. */ + public static final String JDBC_DRIVER = "org.firebirdsql.jdbc.FBDriver"; + + /* The subprotocol used by the standard Firebird driver. */ + public static final String JDBC_SUBPROTOCOL = "firebirdsql"; + + /* + * Creates a new Firebird platform instance. + */ + public FirebirdDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected FirebirdDdlBuilder createDdlBuilder() { + return new FirebirdDdlBuilder(); + } + + @Override + protected FirebirdDdlReader createDdlReader() { + return new FirebirdDdlReader(this); + } + + @Override + protected FirebirdJdbcSqlTemplate createSqlTemplate() { + return new FirebirdJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.FIREBIRD; + } + + public String getDefaultCatalog() { + return null; + } + + public String getDefaultSchema() { + return null; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER FOR " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " AFTER UPDATE AS BEGIN END"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2DatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2DatabasePlatform.java index 1f6fa76f65..58e249df06 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2DatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2DatabasePlatform.java @@ -25,6 +25,10 @@ import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; import org.jumpmind.db.platform.DatabaseNamesConstants; import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; import org.jumpmind.db.sql.SqlTemplateSettings; /* @@ -78,4 +82,25 @@ public String getDefaultCatalog() { return defaultCatalog; } + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + "FOR EACH ROW CALL " + delimiter + "org.jumpmind.db.platform.h2.H2TestTrigger" + delimiter; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } + } \ No newline at end of file diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2TestTrigger.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2TestTrigger.java new file mode 100644 index 0000000000..0899749c83 --- /dev/null +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/h2/H2TestTrigger.java @@ -0,0 +1,25 @@ +package org.jumpmind.db.platform.h2; + +import java.sql.Connection; +import java.sql.SQLException; +import org.h2.api.Trigger; + +public class H2TestTrigger implements Trigger { + + @Override + public void init(Connection conn, String schemaName, + String triggerName, String tableName, boolean before, int type) + throws SQLException {} + + @Override + public void fire(Connection conn, Object[] oldRow, Object[] newRow) + throws SQLException { + + } + + @Override + public void close() throws SQLException {} + + @Override + public void remove() throws SQLException {} +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb/HsqlDbDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb/HsqlDbDatabasePlatform.java index a0ac81cbf7..e2e203be9f 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb/HsqlDbDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb/HsqlDbDatabasePlatform.java @@ -1,73 +1,97 @@ -package org.jumpmind.db.platform.hsqldb; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for the HsqlDb database. - */ -public class HsqlDbDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Hsqldb jdbc driver. */ - public static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver"; - - /* The subprotocol used by the standard Hsqldb driver. */ - public static final String JDBC_SUBPROTOCOL = "hsqldb"; - - /* - * Creates a new instance of the Hsqldb platform. - */ - public HsqlDbDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected HsqlDbDdlBuilder createDdlBuilder() { - return new HsqlDbDdlBuilder(); - } - - @Override - protected HsqlDbDdlReader createDdlReader() { - return new HsqlDbDdlReader(this); - } - - @Override - protected HsqlDbJdbcSqlTemplate createSqlTemplate() { - return new HsqlDbJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.HSQLDB; - } - - public String getDefaultCatalog() { - return null; - } - - public String getDefaultSchema() { - return null; - } - -} +package org.jumpmind.db.platform.hsqldb; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for the HsqlDb database. + */ +public class HsqlDbDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Hsqldb jdbc driver. */ + public static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver"; + + /* The subprotocol used by the standard Hsqldb driver. */ + public static final String JDBC_SUBPROTOCOL = "hsqldb"; + + /* + * Creates a new instance of the Hsqldb platform. + */ + public HsqlDbDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected HsqlDbDdlBuilder createDdlBuilder() { + return new HsqlDbDdlBuilder(); + } + + @Override + protected HsqlDbDdlReader createDdlReader() { + return new HsqlDbDdlReader(this); + } + + @Override + protected HsqlDbJdbcSqlTemplate createSqlTemplate() { + return new HsqlDbJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.HSQLDB; + } + + public String getDefaultCatalog() { + return null; + } + + public String getDefaultSchema() { + return null; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " FOR EACH ROW INSERT INTO " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " VALUES(NULL,NULL)"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb2/HsqlDb2DatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb2/HsqlDb2DatabasePlatform.java index f7e594af7c..7f517452a7 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb2/HsqlDb2DatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/hsqldb2/HsqlDb2DatabasePlatform.java @@ -1,79 +1,103 @@ -package org.jumpmind.db.platform.hsqldb2; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for the HsqlDb database. - */ -public class HsqlDb2DatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Hsqldb jdbc driver. */ - public static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver"; - - /* The subprotocol used by the standard Hsqldb driver. */ - public static final String JDBC_SUBPROTOCOL = "hsqldb"; - - /* - * Creates a new instance of the Hsqldb platform. - */ - public HsqlDb2DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected HsqlDb2DdlBuilder createDdlBuilder() { - return new HsqlDb2DdlBuilder(); - } - - @Override - protected HsqlDb2DdlReader createDdlReader() { - return new HsqlDb2DdlReader(this); - } - - @Override - protected HsqlDb2JdbcSqlTemplate createSqlTemplate() { - return new HsqlDb2JdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.HSQLDB2; - } - - public String getDefaultSchema() { - return getDefaultCatalog(); - } - - public String getDefaultCatalog() { - if (defaultCatalog == null) { - defaultCatalog = (String) getSqlTemplate() - .queryForObject( - "select value from INFORMATION_SCHEMA.SYSTEM_SESSIONINFO where key='CURRENT SCHEMA'", - String.class); - } - return defaultCatalog; - } - -} +package org.jumpmind.db.platform.hsqldb2; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for the HsqlDb database. + */ +public class HsqlDb2DatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Hsqldb jdbc driver. */ + public static final String JDBC_DRIVER = "org.hsqldb.jdbcDriver"; + + /* The subprotocol used by the standard Hsqldb driver. */ + public static final String JDBC_SUBPROTOCOL = "hsqldb"; + + /* + * Creates a new instance of the Hsqldb platform. + */ + public HsqlDb2DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected HsqlDb2DdlBuilder createDdlBuilder() { + return new HsqlDb2DdlBuilder(); + } + + @Override + protected HsqlDb2DdlReader createDdlReader() { + return new HsqlDb2DdlReader(this); + } + + @Override + protected HsqlDb2JdbcSqlTemplate createSqlTemplate() { + return new HsqlDb2JdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.HSQLDB2; + } + + public String getDefaultSchema() { + return getDefaultCatalog(); + } + + public String getDefaultCatalog() { + if (defaultCatalog == null) { + defaultCatalog = (String) getSqlTemplate() + .queryForObject( + "select value from INFORMATION_SCHEMA.SYSTEM_SESSIONINFO where key='CURRENT SCHEMA'", + String.class); + } + return defaultCatalog; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " FOR EACH ROW INSERT INTO " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " VALUES(NULL,NULL)"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/informix/InformixDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/informix/InformixDatabasePlatform.java index 987df1ba67..485ac0a5f5 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/informix/InformixDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/informix/InformixDatabasePlatform.java @@ -1,92 +1,114 @@ -/** - * Licensed to JumpMind Inc under one or more contributor - * license agreements. See the NOTICE file distributed - * with this work for additional information regarding - * copyright ownership. JumpMind Inc licenses this file - * to you under the GNU General Public License, version 3.0 (GPLv3) - * (the "License"); you may not use this file except in compliance - * with the License. - * - * You should have received a copy of the GNU General Public License, - * version 3.0 (GPLv3) along with this library; if not, see - * . - * - * 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 org.jumpmind.db.platform.informix; - -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.platform.IDatabasePlatform; -import org.jumpmind.db.sql.SqlTemplateSettings; - -public class InformixDatabasePlatform extends AbstractJdbcDatabasePlatform implements IDatabasePlatform { - - public static final String JDBC_DRIVER = "com.informix.jdbc.IfxDriver"; - - public static final String JDBC_SUBPROTOCOL = "informix-sqli"; - - private Map sqlScriptReplacementTokens; - - public InformixDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - - sqlScriptReplacementTokens = new HashMap(); - sqlScriptReplacementTokens.put("current_timestamp", "current"); - } - - @Override - protected InformixDdlBuilder createDdlBuilder() { - return new InformixDdlBuilder(); - } - - @Override - protected InformixDdlReader createDdlReader() { - return new InformixDdlReader(this); - } - - @Override - protected InformixJdbcSqlTemplate createSqlTemplate() { - return new InformixJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.INFORMIX; - } - - - public String getDefaultCatalog() { - return null; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = getSqlTemplate().queryForObject("select trim(user) from sysmaster:sysdual", - String.class); - } - return defaultSchema; - } - - @Override - public Map getSqlScriptReplacementTokens() { - return sqlScriptReplacementTokens; - } - - @Override - public boolean isClob(int type) { - return type == Types.CLOB; - } - -} +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.db.platform.informix; + +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +public class InformixDatabasePlatform extends AbstractJdbcDatabasePlatform implements IDatabasePlatform { + + public static final String JDBC_DRIVER = "com.informix.jdbc.IfxDriver"; + + public static final String JDBC_SUBPROTOCOL = "informix-sqli"; + + private Map sqlScriptReplacementTokens; + + public InformixDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + + sqlScriptReplacementTokens = new HashMap(); + sqlScriptReplacementTokens.put("current_timestamp", "current"); + } + + @Override + protected InformixDdlBuilder createDdlBuilder() { + return new InformixDdlBuilder(); + } + + @Override + protected InformixDdlReader createDdlReader() { + return new InformixDdlReader(this); + } + + @Override + protected InformixJdbcSqlTemplate createSqlTemplate() { + return new InformixJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.INFORMIX; + } + + public String getDefaultCatalog() { + return null; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = getSqlTemplate().queryForObject("select trim(user) from sysmaster:sysdual", String.class); + } + return defaultSchema; + } + + @Override + public Map getSqlScriptReplacementTokens() { + return sqlScriptReplacementTokens; + } + + @Override + public boolean isClob(int type) { + return type == Types.CLOB; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER DELETE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " FOR EACH ROW(DELETE FROM " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " WHERE TEST_ID IS NULL)"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/interbase/InterbaseDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/interbase/InterbaseDatabasePlatform.java index 3c3600ed07..4afd134e9a 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/interbase/InterbaseDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/interbase/InterbaseDatabasePlatform.java @@ -1,73 +1,82 @@ -package org.jumpmind.db.platform.interbase; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for the Interbase database. - */ -public class InterbaseDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The interbase jdbc driver. */ - public static final String JDBC_DRIVER = "interbase.interclient.Driver"; - - /* The subprotocol used by the interbase driver. */ - public static final String JDBC_SUBPROTOCOL = "interbase"; - - /* - * Creates a new platform instance. - */ - public InterbaseDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected InterbaseDdlBuilder createDdlBuilder() { - return new InterbaseDdlBuilder(); - } - - @Override - protected InterbaseDdlReader createDdlReader() { - return new InterbaseDdlReader(this); - } - - @Override - protected InterbaseJdbcSqlTemplate createSqlTemplate() { - return new InterbaseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.INTERBASE; - } - - public String getDefaultCatalog() { - return null; - } - - public String getDefaultSchema() { - return null; - } - -} +package org.jumpmind.db.platform.interbase; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for the Interbase database. + */ +public class InterbaseDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The interbase jdbc driver. */ + public static final String JDBC_DRIVER = "interbase.interclient.Driver"; + + /* The subprotocol used by the interbase driver. */ + public static final String JDBC_SUBPROTOCOL = "interbase"; + + /* + * Creates a new platform instance. + */ + public InterbaseDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected InterbaseDdlBuilder createDdlBuilder() { + return new InterbaseDdlBuilder(); + } + + @Override + protected InterbaseDdlReader createDdlReader() { + return new InterbaseDdlReader(this); + } + + @Override + protected InterbaseJdbcSqlTemplate createSqlTemplate() { + return new InterbaseJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.INTERBASE; + } + + public String getDefaultCatalog() { + return null; + } + + public String getDefaultSchema() { + return null; + } + + @Override + public PermissionResult getDropSymTriggerPermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, Status.UNIMPLEMENTED); + return result; + } + +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mssql/MsSql2000DatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mssql/MsSql2000DatabasePlatform.java index 3f66ebc52d..afba7bb9bb 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mssql/MsSql2000DatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mssql/MsSql2000DatabasePlatform.java @@ -1,103 +1,145 @@ -/** - * Licensed to JumpMind Inc under one or more contributor - * license agreements. See the NOTICE file distributed - * with this work for additional information regarding - * copyright ownership. JumpMind Inc licenses this file - * to you under the GNU General Public License, version 3.0 (GPLv3) - * (the "License"); you may not use this file except in compliance - * with the License. - * - * You should have received a copy of the GNU General Public License, - * version 3.0 (GPLv3) along with this library; if not, see - * . - * - * 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 org.jumpmind.db.platform.mssql; - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.platform.IDdlBuilder; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for the Microsoft SQL Server 2000 database. - */ -public class MsSql2000DatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard SQLServer jdbc driver. */ - public static final String JDBC_DRIVER = "net.sourceforge.jtds.jdbc.Driver"; - - /* The sub protocol used by the standard SQL Server driver. */ - public static final String JDBC_SUBPROTOCOL = "jtds"; - - /* - * Creates a new platform instance. - */ - public MsSql2000DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected IDdlBuilder createDdlBuilder() { - return new MsSql2000DdlBuilder(getName()); - } - - @Override - protected MsSqlDdlReader createDdlReader() { - return new MsSqlDdlReader(this); - } - - @Override - protected MsSqlJdbcSqlTemplate createSqlTemplate() { - return new MsSqlJdbcSqlTemplate(dataSource, settings, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.MSSQL2000; - } - - public String getDefaultCatalog() { - if (StringUtils.isBlank(defaultCatalog)) { - defaultCatalog = (String) getSqlTemplate().queryForObject("select DB_NAME()", - String.class); - } - return defaultCatalog; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("select current_user", - String.class); - } - return defaultSchema; - } - - @Override - public boolean isClob(int type) { - return super.isClob(type) || - // SQL-Server ntext binary type - type == -10; - } - - @Override - public boolean canColumnBeUsedInWhereClause(Column column) { - return !column.isOfBinaryType(); - } - - @Override - protected Object parseFloat(String value) { - return cleanNumber(value).replace(',', '.'); - } -} - - +/** + * Licensed to JumpMind Inc under one or more contributor + * license agreements. See the NOTICE file distributed + * with this work for additional information regarding + * copyright ownership. JumpMind Inc licenses this file + * to you under the GNU General Public License, version 3.0 (GPLv3) + * (the "License"); you may not use this file except in compliance + * with the License. + * + * You should have received a copy of the GNU General Public License, + * version 3.0 (GPLv3) along with this library; if not, see + * . + * + * 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 org.jumpmind.db.platform.mssql; + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.IDdlBuilder; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for the Microsoft SQL Server 2000 database. + */ +public class MsSql2000DatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard SQLServer jdbc driver. */ + public static final String JDBC_DRIVER = "net.sourceforge.jtds.jdbc.Driver"; + + /* The sub protocol used by the standard SQL Server driver. */ + public static final String JDBC_SUBPROTOCOL = "jtds"; + + /* + * Creates a new platform instance. + */ + public MsSql2000DatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected IDdlBuilder createDdlBuilder() { + return new MsSql2000DdlBuilder(getName()); + } + + @Override + protected MsSqlDdlReader createDdlReader() { + return new MsSqlDdlReader(this); + } + + @Override + protected MsSqlJdbcSqlTemplate createSqlTemplate() { + return new MsSqlJdbcSqlTemplate(dataSource, settings, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.MSSQL2000; + } + + public String getDefaultCatalog() { + if (StringUtils.isBlank(defaultCatalog)) { + defaultCatalog = (String) getSqlTemplate().queryForObject("select DB_NAME()", String.class); + } + return defaultCatalog; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("select current_user", String.class); + } + return defaultSchema; + } + + @Override + public boolean isClob(int type) { + return super.isClob(type) || + // SQL-Server ntext binary type + type == -10; + } + + @Override + public boolean canColumnBeUsedInWhereClause(Column column) { + return !column.isOfBinaryType(); + } + + @Override + protected Object parseFloat(String value) { + return cleanNumber(value).replace(',', '.'); + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " AFTER UPDATE AS SELECT 1 GO"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } + + @Override + public PermissionResult getCreateSymFunctionPermission() { + String routineSql = "CREATE FUNCTION TEST_FUNC() RETURNS INTEGER BEGIN RETURN 1; END"; + String dropSql = "IF OBJECT_ID('TEST_FUNC') IS NOT NULL DROP FUNCTION TEST_FUNC"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_FUNCTION, Status.FAIL); + + try { + getSqlTemplate().update(dropSql); + getSqlTemplate().update(routineSql); + result.setStatus(Status.PASS); + getSqlTemplate().update(dropSql); + } catch (SqlException e) { + result.setException(e); + if (result.getSolution() != null) { + result.setSolution("Grant CREATE FUNCTION Privilege"); + } + } + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mysql/MySqlDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mysql/MySqlDatabasePlatform.java index 062cecd403..8f71c97825 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mysql/MySqlDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/mysql/MySqlDatabasePlatform.java @@ -1,92 +1,135 @@ -package org.jumpmind.db.platform.mysql; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for MySQL. - */ -public class MySqlDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard MySQL jdbc driver. */ - public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; - - /* The old MySQL jdbc driver. */ - public static final String JDBC_DRIVER_OLD = "org.gjt.mm.mysql.Driver"; - - /* The subprotocol used by the standard MySQL driver. */ - public static final String JDBC_SUBPROTOCOL = "mysql"; - - /* - * Creates a new platform instance. - */ - public MySqlDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, overrideSettings(settings)); - } - - @Override - protected MySqlDdlBuilder createDdlBuilder() { - return new MySqlDdlBuilder(); - } - - @Override - protected MySqlDdlReader createDdlReader() { - return new MySqlDdlReader(this); - } - - @Override - protected MySqlJdbcSqlTemplate createSqlTemplate() { - return new MySqlJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); - } - - /* - * According to the documentation (and experience) the jdbc driver for mysql - * requires the fetch size to be as follows. - */ - protected static SqlTemplateSettings overrideSettings(SqlTemplateSettings settings) { - if (settings == null) { - settings = new SqlTemplateSettings(); - } - settings.setFetchSize(Integer.MIN_VALUE); - return settings; - } - - public String getName() { - return DatabaseNamesConstants.MYSQL; - } - - public String getDefaultSchema() { - return null; - } - - public String getDefaultCatalog() { - if (StringUtils.isBlank(defaultCatalog)) { - defaultCatalog = getSqlTemplate().queryForObject("select database()", String.class); - } - return defaultCatalog; - } - -} +package org.jumpmind.db.platform.mysql; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for MySQL. + */ +public class MySqlDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard MySQL jdbc driver. */ + public static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; + + /* The old MySQL jdbc driver. */ + public static final String JDBC_DRIVER_OLD = "org.gjt.mm.mysql.Driver"; + + /* The subprotocol used by the standard MySQL driver. */ + public static final String JDBC_SUBPROTOCOL = "mysql"; + + /* + * Creates a new platform instance. + */ + public MySqlDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, overrideSettings(settings)); + } + + @Override + protected MySqlDdlBuilder createDdlBuilder() { + return new MySqlDdlBuilder(); + } + + @Override + protected MySqlDdlReader createDdlReader() { + return new MySqlDdlReader(this); + } + + @Override + protected MySqlJdbcSqlTemplate createSqlTemplate() { + return new MySqlJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo()); + } + + /* + * According to the documentation (and experience) the jdbc driver for mysql + * requires the fetch size to be as follows. + */ + protected static SqlTemplateSettings overrideSettings(SqlTemplateSettings settings) { + if (settings == null) { + settings = new SqlTemplateSettings(); + } + settings.setFetchSize(Integer.MIN_VALUE); + return settings; + } + + public String getName() { + return DatabaseNamesConstants.MYSQL; + } + + public String getDefaultSchema() { + return null; + } + + public String getDefaultCatalog() { + if (StringUtils.isBlank(defaultCatalog)) { + defaultCatalog = getSqlTemplate().queryForObject("select database()", String.class); + } + return defaultCatalog; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + " FOR EACH ROW INSERT INTO " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " VALUES(NULL,NULL)"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } + + @Override + public PermissionResult getCreateSymRoutinePermission() { + String routineSql = "CREATE PROCEDURE TEST_PROC() BEGIN SELECT 1; END"; + String dropSql = "DROP PROCEDURE IF EXISTS TEST_PROC"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_ROUTINE, Status.FAIL); + + try { + getSqlTemplate().update(dropSql); + getSqlTemplate().update(routineSql); + result.setStatus(Status.PASS); + getSqlTemplate().update(dropSql); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE ROUTINE Privilege"); + } + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/oracle/OracleDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/oracle/OracleDatabasePlatform.java index cddf443331..d510ad050b 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/oracle/OracleDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/oracle/OracleDatabasePlatform.java @@ -1,100 +1,144 @@ -package org.jumpmind.db.platform.oracle; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.ISqlTemplate; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * Provides support for the Oracle platform. - */ -public class OracleDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Oracle jdbc driver. */ - public static final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver"; - - /* The old Oracle jdbc driver. */ - public static final String JDBC_DRIVER_OLD = "oracle.jdbc.dnlddriver.OracleDriver"; - - /* The thin subprotocol used by the standard Oracle driver. */ - public static final String JDBC_SUBPROTOCOL_THIN = "oracle:thin"; - - /* The thin subprotocol used by the standard Oracle driver. */ - public static final String JDBC_SUBPROTOCOL_OCI8 = "oracle:oci8"; - - /* The old thin subprotocol used by the standard Oracle driver. */ - public static final String JDBC_SUBPROTOCOL_THIN_OLD = "oracle:dnldthin"; - - /* - * Creates a new platform instance. - */ - public OracleDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - } - - @Override - protected OracleDdlBuilder createDdlBuilder() { - return new OracleDdlBuilder(); - } - - @Override - protected OracleDdlReader createDdlReader() { - return new OracleDdlReader(this); - } - - @Override - protected OracleJdbcSqlTemplate createSqlTemplate() { - return new OracleJdbcSqlTemplate(dataSource, settings, new OracleLobHandler(), getDatabaseInfo()); - } - - @Override - protected ISqlTemplate createSqlTemplateDirty() { - return sqlTemplate; - } - - public String getName() { - return DatabaseNamesConstants.ORACLE; - } - - public String getDefaultCatalog() { - return null; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject( - "SELECT sys_context('USERENV', 'CURRENT_SCHEMA') FROM dual", String.class); - } - return defaultSchema; - } - - @Override - public boolean canColumnBeUsedInWhereClause(Column column) { - String jdbcTypeName = column.getJdbcTypeName(); - return !column.isOfBinaryType() || "RAW".equals(jdbcTypeName); - } - -} +package org.jumpmind.db.platform.oracle; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.ISqlTemplate; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * Provides support for the Oracle platform. + */ +public class OracleDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Oracle jdbc driver. */ + public static final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver"; + + /* The old Oracle jdbc driver. */ + public static final String JDBC_DRIVER_OLD = "oracle.jdbc.dnlddriver.OracleDriver"; + + /* The thin subprotocol used by the standard Oracle driver. */ + public static final String JDBC_SUBPROTOCOL_THIN = "oracle:thin"; + + /* The thin subprotocol used by the standard Oracle driver. */ + public static final String JDBC_SUBPROTOCOL_OCI8 = "oracle:oci8"; + + /* The old thin subprotocol used by the standard Oracle driver. */ + public static final String JDBC_SUBPROTOCOL_THIN_OLD = "oracle:dnldthin"; + + /* + * Creates a new platform instance. + */ + public OracleDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + } + + @Override + protected OracleDdlBuilder createDdlBuilder() { + return new OracleDdlBuilder(); + } + + @Override + protected OracleDdlReader createDdlReader() { + return new OracleDdlReader(this); + } + + @Override + protected OracleJdbcSqlTemplate createSqlTemplate() { + return new OracleJdbcSqlTemplate(dataSource, settings, new OracleLobHandler(), getDatabaseInfo()); + } + + @Override + protected ISqlTemplate createSqlTemplateDirty() { + return sqlTemplate; + } + + public String getName() { + return DatabaseNamesConstants.ORACLE; + } + + public String getDefaultCatalog() { + return null; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject( + "SELECT sys_context('USERENV', 'CURRENT_SCHEMA') FROM dual", String.class); + } + return defaultSchema; + } + + @Override + public boolean canColumnBeUsedInWhereClause(Column column) { + String jdbcTypeName = column.getJdbcTypeName(); + return !column.isOfBinaryType() || "RAW".equals(jdbcTypeName); + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE OR REPLACE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " BEGIN END"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } + + @Override + public PermissionResult getExecuteSymPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String executeSql = "SELECT DBMS_LOB.GETLENGTH('TEST'), UTL_RAW.CAST_TO_RAW('TEST') FROM DUAL"; + + PermissionResult result = new PermissionResult(PermissionType.EXECUTE, Status.FAIL); + + try { + getSqlTemplate().update(executeSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant EXECUTE on DBMS_LOB and UTL_RAW"); + } + + return result; + } + +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/postgresql/PostgreSqlDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/postgresql/PostgreSqlDatabasePlatform.java index d962aa4595..d8db1155b2 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/postgresql/PostgreSqlDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/postgresql/PostgreSqlDatabasePlatform.java @@ -1,198 +1,257 @@ -package org.jumpmind.db.platform.postgresql; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import java.sql.Array; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Map; - -import javax.sql.DataSource; -import javax.sql.rowset.serial.SerialBlob; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.Column; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.SqlTemplateSettings; -import org.jumpmind.db.sql.SymmetricLobHandler; -import org.jumpmind.db.util.BinaryEncoding; - -/* - * The platform implementation for PostgresSql. - */ -public class PostgreSqlDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard PostgreSQL jdbc driver. */ - public static final String JDBC_DRIVER = "org.postgresql.Driver"; - - /* The subprotocol used by the standard PostgreSQL driver. */ - public static final String JDBC_SUBPROTOCOL = "postgresql"; - - /* - * Creates a new platform instance. - */ - public PostgreSqlDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, overrideSettings(settings)); - } - - protected static SqlTemplateSettings overrideSettings(SqlTemplateSettings settings) { - if (settings == null) { - settings = new SqlTemplateSettings(); - } - // Query timeout needs to be zero for postrgres because the jdbc driver does - // not support a timeout setting of of other than zero. - settings.setQueryTimeout(0); - return settings; - } - - protected static boolean isBlobStoredByReference(String jdbcTypeName) { - if ("OID".equalsIgnoreCase(jdbcTypeName) || "LO".equalsIgnoreCase(jdbcTypeName)) { - return true; - } else { - return false; - } - } - - @Override - protected PostgreSqlDdlBuilder createDdlBuilder() { - return new PostgreSqlDdlBuilder(); - } - - @Override - protected PostgreSqlDdlReader createDdlReader() { - return new PostgreSqlDdlReader(this); - } - - @Override - protected PostgreSqlJdbcSqlTemplate createSqlTemplate() { - SymmetricLobHandler lobHandler = new PostgresLobHandler(); - return new PostgreSqlJdbcSqlTemplate(dataSource, settings, lobHandler, getDatabaseInfo()); - } - - public String getName() { - return DatabaseNamesConstants.POSTGRESQL; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("select current_schema()", String.class); - } - return defaultSchema; - } - - public String getDefaultCatalog() { - return null; - } - - - @Override - protected Array createArray(Column column, final String value) { - if (StringUtils.isNotBlank(value)) { - - String jdbcTypeName = column.getJdbcTypeName(); - if (jdbcTypeName.startsWith("_")) { - jdbcTypeName = jdbcTypeName.substring(1); - } - int jdbcBaseType = Types.VARCHAR; - if (jdbcTypeName.toLowerCase().contains("int")) { - jdbcBaseType = Types.INTEGER; - } - - final String baseTypeName = jdbcTypeName; - final int baseType = jdbcBaseType; - return new Array() { - public String getBaseTypeName() { - return baseTypeName; - } - - public void free() throws SQLException { - } - - public int getBaseType() { - return baseType; - } - - public Object getArray() { - return null; - } - - public Object getArray(Map> map) { - return null; - } - - public Object getArray(long index, int count) { - return null; - } - - public Object getArray(long index, int count, Map> map) { - return null; - } - - public ResultSet getResultSet() { - return null; - } - - public ResultSet getResultSet(Map> map) { - return null; - } - - public ResultSet getResultSet(long index, int count) { - return null; - } - - public ResultSet getResultSet(long index, int count, Map> map) { - return null; - } - - public String toString() { - return value; - } - }; - } else { - return null; - } - } - - @Override - protected String cleanTextForTextBasedColumns(String text) { - return text.replace("\0", ""); - } - - - @Override - public Object[] getObjectValues(BinaryEncoding encoding, String[] values, - Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn) { - Object[] objectValues = super.getObjectValues(encoding, values, orderedMetaData, useVariableDates, fitToColumn); - for (int i = 0; i < orderedMetaData.length; i++) { - if (orderedMetaData[i] != null && orderedMetaData[i].getMappedTypeCode() == Types.BLOB - && objectValues[i] != null) { - try { - objectValues[i] = new SerialBlob((byte[]) objectValues[i]); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - return objectValues; - } - -} +package org.jumpmind.db.platform.postgresql; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.Map; + +import javax.sql.DataSource; +import javax.sql.rowset.serial.SerialBlob; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.model.Column; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; +import org.jumpmind.db.sql.SymmetricLobHandler; +import org.jumpmind.db.util.BinaryEncoding; + +/* + * The platform implementation for PostgresSql. + */ +public class PostgreSqlDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard PostgreSQL jdbc driver. */ + public static final String JDBC_DRIVER = "org.postgresql.Driver"; + + /* The subprotocol used by the standard PostgreSQL driver. */ + public static final String JDBC_SUBPROTOCOL = "postgresql"; + + /* + * Creates a new platform instance. + */ + public PostgreSqlDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, overrideSettings(settings)); + } + + protected static SqlTemplateSettings overrideSettings(SqlTemplateSettings settings) { + if (settings == null) { + settings = new SqlTemplateSettings(); + } + // Query timeout needs to be zero for postrgres because the jdbc driver does + // not support a timeout setting of of other than zero. + settings.setQueryTimeout(0); + return settings; + } + + protected static boolean isBlobStoredByReference(String jdbcTypeName) { + if ("OID".equalsIgnoreCase(jdbcTypeName) || "LO".equalsIgnoreCase(jdbcTypeName)) { + return true; + } else { + return false; + } + } + + @Override + protected PostgreSqlDdlBuilder createDdlBuilder() { + return new PostgreSqlDdlBuilder(); + } + + @Override + protected PostgreSqlDdlReader createDdlReader() { + return new PostgreSqlDdlReader(this); + } + + @Override + protected PostgreSqlJdbcSqlTemplate createSqlTemplate() { + SymmetricLobHandler lobHandler = new PostgresLobHandler(); + return new PostgreSqlJdbcSqlTemplate(dataSource, settings, lobHandler, getDatabaseInfo()); + } + + public String getName() { + return DatabaseNamesConstants.POSTGRESQL; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("select current_schema()", String.class); + } + return defaultSchema; + } + + public String getDefaultCatalog() { + return null; + } + + + @Override + protected Array createArray(Column column, final String value) { + if (StringUtils.isNotBlank(value)) { + + String jdbcTypeName = column.getJdbcTypeName(); + if (jdbcTypeName.startsWith("_")) { + jdbcTypeName = jdbcTypeName.substring(1); + } + int jdbcBaseType = Types.VARCHAR; + if (jdbcTypeName.toLowerCase().contains("int")) { + jdbcBaseType = Types.INTEGER; + } + + final String baseTypeName = jdbcTypeName; + final int baseType = jdbcBaseType; + return new Array() { + public String getBaseTypeName() { + return baseTypeName; + } + + public void free() throws SQLException { + } + + public int getBaseType() { + return baseType; + } + + public Object getArray() { + return null; + } + + public Object getArray(Map> map) { + return null; + } + + public Object getArray(long index, int count) { + return null; + } + + public Object getArray(long index, int count, Map> map) { + return null; + } + + public ResultSet getResultSet() { + return null; + } + + public ResultSet getResultSet(Map> map) { + return null; + } + + public ResultSet getResultSet(long index, int count) { + return null; + } + + public ResultSet getResultSet(long index, int count, Map> map) { + return null; + } + + public String toString() { + return value; + } + }; + } else { + return null; + } + } + + @Override + protected String cleanTextForTextBasedColumns(String text) { + return text.replace("\0", ""); + } + + + @Override + public Object[] getObjectValues(BinaryEncoding encoding, String[] values, + Column[] orderedMetaData, boolean useVariableDates, boolean fitToColumn) { + Object[] objectValues = super.getObjectValues(encoding, values, orderedMetaData, useVariableDates, fitToColumn); + for (int i = 0; i < orderedMetaData.length; i++) { + if (orderedMetaData[i] != null && orderedMetaData[i].getMappedTypeCode() == Types.BLOB + && objectValues[i] != null) { + try { + objectValues[i] = new SerialBlob((byte[]) objectValues[i]); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + return objectValues; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE OR REPLACE FUNCTION TEST_TRIGGER() RETURNS trigger AS $$ BEGIN END $$ LANGUAGE plpgsql"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission and/or DROP TRIGGER permission"); + } + + return result; + } + + @Override + public PermissionResult getDropSymTriggerPermission() { + String dropTriggerSql = "DROP FUNCTION TEST_TRIGGER()"; + + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, PermissionResult.Status.FAIL); + + try { + getSqlTemplate().update(dropTriggerSql); + result.setStatus(PermissionResult.Status.PASS); + } catch (SqlException e) { + result.setException(e); + } + + return result; + } + + @Override + protected PermissionResult getDropSymTablePermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + String dropSql = "drop table " + PERMISSION_TEST_TABLE_NAME; + + PermissionResult result = new PermissionResult(PermissionType.DROP_TABLE, Status.FAIL); + + try { + getSqlTemplate().update(dropSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant DROP permission"); + } + + return result; + } + +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/redshift/RedshiftDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/redshift/RedshiftDatabasePlatform.java index 4989a29151..02aace7a80 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/redshift/RedshiftDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/redshift/RedshiftDatabasePlatform.java @@ -27,9 +27,12 @@ import javax.sql.DataSource; import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.model.ColumnTypes; +import org.jumpmind.db.model.Database; import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; import org.jumpmind.db.sql.SqlTemplateSettings; public class RedshiftDatabasePlatform extends AbstractJdbcDatabasePlatform { @@ -88,4 +91,28 @@ public Map getSqlScriptReplacementTokens() { public boolean isClob(int type) { return type == Types.CLOB; } + + @Override + public PermissionResult getCreateSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.CREATE_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTablePermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getAlterSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.ALTER_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTriggerPermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, Status.UNIMPLEMENTED); + return result; + } } diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlanywhere/SqlAnywhereDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlanywhere/SqlAnywhereDatabasePlatform.java index 6edf12b02b..a7a6a56b9f 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlanywhere/SqlAnywhereDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlanywhere/SqlAnywhereDatabasePlatform.java @@ -1,97 +1,121 @@ -package org.jumpmind.db.platform.sqlanywhere; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import java.util.HashMap; -import java.util.Map; - -import javax.sql.DataSource; - -import org.apache.commons.lang.StringUtils; -import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; -import org.jumpmind.db.platform.DatabaseNamesConstants; -import org.jumpmind.db.sql.JdbcUtils; -import org.jumpmind.db.sql.SqlTemplateSettings; - -/* - * The platform implementation for Sybase. - */ -public class SqlAnywhereDatabasePlatform extends AbstractJdbcDatabasePlatform { - - /* The standard Sybase jdbc driver. */ - public static final String JDBC_DRIVER = "com.sybase.jdbc4.jdbc.SybDriver"; - - /* The old Sybase jdbc driver. */ - public static final String JDBC_DRIVER_OLD = "com.sybase.jdbc4.jdbc.SybDriver"; - - /* The subprotocol used by the standard Sybase driver. */ - public static final String JDBC_SUBPROTOCOL = "sybase:Tds"; - - /* The maximum size that text and binary columns can have. */ - public static final long MAX_TEXT_SIZE = 2147483647; - - private Map sqlScriptReplacementTokens; - - public SqlAnywhereDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { - super(dataSource, settings); - - sqlScriptReplacementTokens = new HashMap(); - sqlScriptReplacementTokens.put("current_timestamp", "getdate()"); - } - - @Override - protected SqlAnywhereDdlBuilder createDdlBuilder() { - return new SqlAnywhereDdlBuilder(); - } - - @Override - protected SqlAnywhereDdlReader createDdlReader() { - return new SqlAnywhereDdlReader(this); - } - - @Override - protected SqlAnywhereJdbcSqlTemplate createSqlTemplate() { - return new SqlAnywhereJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory()); - } - - public String getName() { - return DatabaseNamesConstants.SQLANYWHERE; - } - - public String getDefaultCatalog() { - if (StringUtils.isBlank(defaultCatalog)) { - defaultCatalog = getSqlTemplate().queryForObject("select DB_NAME()", String.class); - } - return defaultCatalog; - } - - public String getDefaultSchema() { - if (StringUtils.isBlank(defaultSchema)) { - defaultSchema = (String) getSqlTemplate().queryForObject("select USER_NAME()", - String.class); - } - return defaultSchema; - } - - @Override - public Map getSqlScriptReplacementTokens() { - return sqlScriptReplacementTokens; - } -} +package org.jumpmind.db.platform.sqlanywhere; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import org.apache.commons.lang.StringUtils; +import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; +import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.sql.JdbcUtils; +import org.jumpmind.db.sql.SqlException; +import org.jumpmind.db.sql.SqlTemplateSettings; + +/* + * The platform implementation for Sybase. + */ +public class SqlAnywhereDatabasePlatform extends AbstractJdbcDatabasePlatform { + + /* The standard Sybase jdbc driver. */ + public static final String JDBC_DRIVER = "com.sybase.jdbc4.jdbc.SybDriver"; + + /* The old Sybase jdbc driver. */ + public static final String JDBC_DRIVER_OLD = "com.sybase.jdbc4.jdbc.SybDriver"; + + /* The subprotocol used by the standard Sybase driver. */ + public static final String JDBC_SUBPROTOCOL = "sybase:Tds"; + + /* The maximum size that text and binary columns can have. */ + public static final long MAX_TEXT_SIZE = 2147483647; + + private Map sqlScriptReplacementTokens; + + public SqlAnywhereDatabasePlatform(DataSource dataSource, SqlTemplateSettings settings) { + super(dataSource, settings); + + sqlScriptReplacementTokens = new HashMap(); + sqlScriptReplacementTokens.put("current_timestamp", "getdate()"); + } + + @Override + protected SqlAnywhereDdlBuilder createDdlBuilder() { + return new SqlAnywhereDdlBuilder(); + } + + @Override + protected SqlAnywhereDdlReader createDdlReader() { + return new SqlAnywhereDdlReader(this); + } + + @Override + protected SqlAnywhereJdbcSqlTemplate createSqlTemplate() { + return new SqlAnywhereJdbcSqlTemplate(dataSource, settings, null, getDatabaseInfo(), JdbcUtils.getNativeJdbcExtractory()); + } + + public String getName() { + return DatabaseNamesConstants.SQLANYWHERE; + } + + public String getDefaultCatalog() { + if (StringUtils.isBlank(defaultCatalog)) { + defaultCatalog = getSqlTemplate().queryForObject("select DB_NAME()", String.class); + } + return defaultCatalog; + } + + public String getDefaultSchema() { + if (StringUtils.isBlank(defaultSchema)) { + defaultSchema = (String) getSqlTemplate().queryForObject("select USER_NAME()", + String.class); + } + return defaultSchema; + } + + @Override + public Map getSqlScriptReplacementTokens() { + return sqlScriptReplacementTokens; + } + + @Override + public PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE OR REPLACE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + " BEGIN SELECT 1 END"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } +} diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlite/SqliteDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlite/SqliteDatabasePlatform.java index 655e0a58d1..9a86065621 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlite/SqliteDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/sqlite/SqliteDatabasePlatform.java @@ -28,8 +28,12 @@ import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; import org.jumpmind.db.platform.DatabaseNamesConstants; import org.jumpmind.db.platform.IDatabasePlatform; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionResult.Status; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.ISqlTemplate; import org.jumpmind.db.sql.Row; +import org.jumpmind.db.sql.SqlException; import org.jumpmind.db.sql.SqlTemplateSettings; public class SqliteDatabasePlatform extends AbstractJdbcDatabasePlatform implements @@ -113,4 +117,25 @@ protected Object parseInteger(String value) { return super.parseInteger(value); } } + + @Override + protected PermissionResult getCreateSymTriggerPermission() { + String delimiter = getDatabaseInfo().getDelimiterToken(); + delimiter = delimiter != null ? delimiter : ""; + + String triggerSql = "CREATE TRIGGER TEST_TRIGGER AFTER UPDATE ON " + delimiter + PERMISSION_TEST_TABLE_NAME + delimiter + + "FOR EACH ROW BEGIN SELECT 1; END"; + + PermissionResult result = new PermissionResult(PermissionType.CREATE_TRIGGER, Status.FAIL); + + try { + getSqlTemplate().update(triggerSql); + result.setStatus(Status.PASS); + } catch (SqlException e) { + result.setException(e); + result.setSolution("Grant CREATE TRIGGER permission or TRIGGER permission"); + } + + return result; + } } diff --git a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/voltdb/VoltDbDatabasePlatform.java b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/voltdb/VoltDbDatabasePlatform.java index f745de54e9..6de2afa643 100644 --- a/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/voltdb/VoltDbDatabasePlatform.java +++ b/symmetric-jdbc/src/main/java/org/jumpmind/db/platform/voltdb/VoltDbDatabasePlatform.java @@ -32,6 +32,9 @@ import org.jumpmind.db.model.Table; import org.jumpmind.db.platform.AbstractJdbcDatabasePlatform; import org.jumpmind.db.platform.DatabaseNamesConstants; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; +import org.jumpmind.db.platform.PermissionResult.Status; import org.jumpmind.db.sql.ISqlTemplate; import org.jumpmind.db.sql.SqlTemplateSettings; import org.jumpmind.db.sql.SymmetricLobHandler; @@ -117,5 +120,28 @@ protected VoltDbDdlReader createDdlReader() { protected VoltDbJdbcSqlTemplate createSqlTemplate() { return new VoltDbJdbcSqlTemplate(dataSource, settings, new SymmetricLobHandler(), getDatabaseInfo()); } - + + @Override + public PermissionResult getCreateSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.CREATE_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTablePermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getAlterSymTablePermission(Database database) { + PermissionResult result = new PermissionResult(PermissionType.ALTER_TABLE, Status.UNIMPLEMENTED); + return result; + } + + @Override + public PermissionResult getDropSymTriggerPermission() { + PermissionResult result = new PermissionResult(PermissionType.DROP_TRIGGER, Status.UNIMPLEMENTED); + return result; + } } diff --git a/symmetric-jdbc/src/test/java/org/jumpmind/db/DatabasePlatformTest.java b/symmetric-jdbc/src/test/java/org/jumpmind/db/DatabasePlatformTest.java index a788aeab73..b76af3ad34 100644 --- a/symmetric-jdbc/src/test/java/org/jumpmind/db/DatabasePlatformTest.java +++ b/symmetric-jdbc/src/test/java/org/jumpmind/db/DatabasePlatformTest.java @@ -22,6 +22,7 @@ import java.io.InputStreamReader; import java.sql.Types; +import java.util.List; import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -33,6 +34,8 @@ import org.jumpmind.db.platform.DatabaseNamesConstants; import org.jumpmind.db.platform.IDatabasePlatform; import org.jumpmind.db.platform.IDdlBuilder; +import org.jumpmind.db.platform.PermissionResult; +import org.jumpmind.db.platform.PermissionType; import org.jumpmind.db.sql.ISqlTemplate; import org.jumpmind.db.sql.SqlScript; @@ -58,7 +61,6 @@ public static void setup() throws Exception { platform.createDatabase(DatabaseXmlUtil.read(new InputStreamReader( DatabasePlatformTest.class.getResourceAsStream("/testCreateDatabase.xml"))), true, true); - } @Before @@ -171,7 +173,7 @@ protected Table dropCreateAndThenReadTable(Table table) { platform.createDatabase(database, true, false); return platform.getTableFromCache(table.getName(), true); } - + @Test public void testDisableAutoincrement() throws Exception { Table table = new Table("TEST_AUTOPK_DISABLE"); @@ -202,7 +204,7 @@ public void testDisableAutoincrement() throws Exception { } } - + @Test public void testUpgradePrimaryKeyAutoIncrementFromIntToBigInt() throws Exception { boolean upgradeSupported = !platform.getName().equals(DatabaseNamesConstants.DERBY) @@ -269,7 +271,7 @@ protected String getSequenceName(IDatabasePlatform platform) { return "test_upgrade_id"; } } - + @Test public void testCreateAndReadTestSimpleTable() throws Exception { Table table = platform.getTableFromCache(SIMPLE_TABLE, true); @@ -286,7 +288,7 @@ public void testReadTestUppercase() throws Exception { .getColumnWithName("id").isAutoIncrement()); } - + @Test public void testNvarcharType() { Table table = new Table("test_nvarchar"); @@ -294,5 +296,16 @@ public void testNvarcharType() { table.addColumn(new Column("note", false, ColumnTypes.NVARCHAR, 100, 0)); platform.createTables(true, false, table); } - + + @Test + public void getPermissionsTest() { + List results = platform.checkSymTablePermissions(PermissionType.values()); + + for (PermissionResult result : results) { + System.out.println(result.toString()); + if (result.getException() != null) { + System.out.println(result.getException().toString()); + } + } + } }