diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a8440f..f59dfa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # DLSync Changelog This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.0.1] - 2026-02-05 +### Fixed +- Fixed session context issue when managing account-level objects (databases, schemas). DLSync metadata tables now use fully qualified names to prevent "table does not exist" errors after Snowflake automatically switches session context. ## [3.0.0] - 2026-01-15 ### Added - Added support for account level objects like database, schemas, roles, warehouses etc. diff --git a/gradle.properties b/gradle.properties index 9b86e41..0f2f246 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -releaseVersion=3.0.0 \ No newline at end of file +releaseVersion=3.0.1 \ No newline at end of file diff --git a/src/main/java/com/snowflake/dlsync/doa/ScriptRepo.java b/src/main/java/com/snowflake/dlsync/doa/ScriptRepo.java index ee0047c..e848301 100644 --- a/src/main/java/com/snowflake/dlsync/doa/ScriptRepo.java +++ b/src/main/java/com/snowflake/dlsync/doa/ScriptRepo.java @@ -42,17 +42,17 @@ private void initScriptTables() throws SQLException { log.info("Using database [{}] and schema [{}] for dlsync activities.", resultSet.getString(1), resultSet.getString(2)); log.debug("Checking for deployment tables"); try { - String query = "SELECT * FROM " + CHANGE_SYNC_TABLE_NAME + " LIMIT 1;"; + String query = "SELECT * FROM " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + " LIMIT 1;"; Statement statement = connection.createStatement(); statement.executeQuery(query); updateOldTableNames(); } catch (SQLException e) { log.info("Running for the first time. Creating required tables."); - String createChangeSyncSql = "CREATE OR REPLACE TABLE " + CHANGE_SYNC_TABLE_NAME + " (ID integer PRIMARY KEY, CHANGE_TYPE varchar, STATUS varchar, LOG varchar, CHANGE_COUNT integer, START_TIME timestamp, END_TIME timestamp);"; + String createChangeSyncSql = "CREATE OR REPLACE TABLE " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + " (ID integer PRIMARY KEY, CHANGE_TYPE varchar, STATUS varchar, LOG varchar, CHANGE_COUNT integer, START_TIME timestamp, END_TIME timestamp);"; - String createSqlHash = "CREATE OR REPLACE TABLE " + SCRIPT_HISTORY_TABLE_NAME + " (SCRIPT_ID VARCHAR, OBJECT_NAME varchar, OBJECT_TYPE varchar, ROLLBACK_SCRIPT varchar, SCRIPT_HASH varchar, DEPLOYED_HASH varchar, CHANGE_SYNC_ID integer, CREATED_BY varchar, CREATED_TS timestamp, UPDATED_BY varchar, UPDATED_TS timestamp, FOREIGN KEY (CHANGE_SYNC_ID) REFERENCES " + CHANGE_SYNC_TABLE_NAME + "(ID));"; + String createSqlHash = "CREATE OR REPLACE TABLE " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + " (SCRIPT_ID VARCHAR, OBJECT_NAME varchar, OBJECT_TYPE varchar, ROLLBACK_SCRIPT varchar, SCRIPT_HASH varchar, DEPLOYED_HASH varchar, CHANGE_SYNC_ID integer, CREATED_BY varchar, CREATED_TS timestamp, UPDATED_BY varchar, UPDATED_TS timestamp, FOREIGN KEY (CHANGE_SYNC_ID) REFERENCES " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + "(ID));"; - String createSqlEvent = "CREATE OR REPLACE TABLE " + SCRIPT_EVENT_TABLE_NAME + " (ID VARCHAR, SCRIPT_ID VARCHAR, OBJECT_NAME varchar, SCRIPT_HASH varchar, STATUS varchar, LOG varchar, CHANGE_SYNC_ID integer, CREATED_BY varchar, CREATED_TS timestamp, FOREIGN KEY (CHANGE_SYNC_ID) REFERENCES " + CHANGE_SYNC_TABLE_NAME + "(ID));"; + String createSqlEvent = "CREATE OR REPLACE TABLE " + getFullyQualifiedTableName(SCRIPT_EVENT_TABLE_NAME) + " (ID VARCHAR, SCRIPT_ID VARCHAR, OBJECT_NAME varchar, SCRIPT_HASH varchar, STATUS varchar, LOG varchar, CHANGE_SYNC_ID integer, CREATED_BY varchar, CREATED_TS timestamp, FOREIGN KEY (CHANGE_SYNC_ID) REFERENCES " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + "(ID));"; log.debug("create hash table sql: {}", createSqlHash); log.debug("create event table sql: {}", createSqlEvent); Statement statement = connection.createStatement(); @@ -64,11 +64,12 @@ private void initScriptTables() throws SQLException { private void updateOldTableNames() { try { - String query = "SELECT * FROM DL_SYNC_SCRIPT LIMIT 1;"; + String oldTableName = getFullyQualifiedTableName("DL_SYNC_SCRIPT"); + String query = "SELECT * FROM " + oldTableName + " LIMIT 1;"; Statement statement = connection.createStatement(); statement.executeQuery(query); log.info("Found old dlsync table DL_SYNC_SCRIPT renaming it to [{}]", SCRIPT_HISTORY_TABLE_NAME); - String alterSql = "ALTER TABLE IF EXISTS DL_SYNC_SCRIPT RENAME TO " + SCRIPT_HISTORY_TABLE_NAME + ";"; + String alterSql = "ALTER TABLE IF EXISTS " + oldTableName + " RENAME TO " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + ";"; statement.executeUpdate(alterSql); } catch (SQLException e) { log.debug("All tables are with new version"); @@ -76,7 +77,7 @@ private void updateOldTableNames() { } public Set loadScriptHash() throws SQLException { - String hashQuery = "SELECT * FROM " + SCRIPT_HISTORY_TABLE_NAME + ";"; + String hashQuery = "SELECT * FROM " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + ";"; log.debug("Loading hash with sql: {}", hashQuery); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(hashQuery); @@ -91,7 +92,7 @@ public Set loadScriptHash() throws SQLException { public Set loadDeployedHash() throws SQLException { String hashColumn = "DEPLOYED_HASH"; - String hashQuery = "SELECT * FROM " + SCRIPT_HISTORY_TABLE_NAME + ";"; + String hashQuery = "SELECT * FROM " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + ";"; log.debug("Loading hash with sql: {}", hashQuery); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(hashQuery); @@ -105,13 +106,13 @@ public Set loadDeployedHash() throws SQLException { } public Long insertChangeSync(ChangeType changeType, Status status, String logMessage) throws SQLException { - String queryGetId = "SELECT count(1) FROM " + CHANGE_SYNC_TABLE_NAME + ";"; + String queryGetId = "SELECT count(1) FROM " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + ";"; ResultSet rs = connection.createStatement().executeQuery(queryGetId); if(rs.next()) { changeSyncId = rs.getLong(1) + 1; } - String insertSql = "INSERT INTO " + CHANGE_SYNC_TABLE_NAME + " (ID, CHANGE_TYPE, STATUS, LOG, START_TIME) VALUES(?, ?, ?, ?, CURRENT_TIMESTAMP);"; + String insertSql = "INSERT INTO " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + " (ID, CHANGE_TYPE, STATUS, LOG, START_TIME) VALUES(?, ?, ?, ?, CURRENT_TIMESTAMP);"; PreparedStatement statement = connection.prepareStatement(insertSql); statement.setLong(1, changeSyncId); statement.setString(2, changeType.toString()); @@ -124,7 +125,7 @@ public Long insertChangeSync(ChangeType changeType, Status status, String logMes } public void updateChangeSync(ChangeType changeType, Status status, String logMessage, Long changeCount) throws SQLException { - String updateSql = "UPDATE " + CHANGE_SYNC_TABLE_NAME + " SET CHANGE_TYPE=?, STATUS=?, LOG=?, CHANGE_COUNT=?, END_TIME=CURRENT_TIMESTAMP WHERE ID = ? ;"; + String updateSql = "UPDATE " + getFullyQualifiedTableName(CHANGE_SYNC_TABLE_NAME) + " SET CHANGE_TYPE=?, STATUS=?, LOG=?, CHANGE_COUNT=?, END_TIME=CURRENT_TIMESTAMP WHERE ID = ? ;"; PreparedStatement statement = connection.prepareStatement(updateSql); statement.setString(1, changeType.toString()); statement.setString(2, status.toString()); @@ -144,7 +145,7 @@ private boolean updateScriptHash(Script script) throws SQLException { String deployedHash = Util.getMd5Hash(script.getContent()); log.debug("Updating script hash of object {}", script.getId()); if(scriptHash.containsKey(script.getId())) { - String updateSql = "UPDATE " + SCRIPT_HISTORY_TABLE_NAME + " SET ROLLBACK_SCRIPT=?, SCRIPT_HASH=?, DEPLOYED_HASH=?, CHANGE_SYNC_ID=?, updated_by=current_user, updated_ts=current_timestamp WHERE SCRIPT_ID=?;"; + String updateSql = "UPDATE " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + " SET ROLLBACK_SCRIPT=?, SCRIPT_HASH=?, DEPLOYED_HASH=?, CHANGE_SYNC_ID=?, updated_by=current_user, updated_ts=current_timestamp WHERE SCRIPT_ID=?;"; statement = connection.prepareStatement(updateSql); statement.setString(1, rollback); statement.setString(2, script.getHash()); @@ -154,7 +155,7 @@ private boolean updateScriptHash(Script script) throws SQLException { log.debug("Updating script hash with the following SQL: {}", updateSql); } else { - String insertSql = "INSERT INTO " + SCRIPT_HISTORY_TABLE_NAME + " VALUES(?, ?, ?, ?, ?, ?, ?, current_user, current_timestamp, current_user, current_timestamp);"; + String insertSql = "INSERT INTO " + getFullyQualifiedTableName(SCRIPT_HISTORY_TABLE_NAME) + " VALUES(?, ?, ?, ?, ?, ?, ?, current_user, current_timestamp, current_user, current_timestamp);"; statement = connection.prepareStatement(insertSql); statement.setString(1, script.getId()); statement.setString(2, script.getFullObjectName()); @@ -172,7 +173,7 @@ private boolean updateScriptHash(Script script) throws SQLException { private boolean insertScriptEvent(Script script, String status, String logs) throws SQLException { //varchar ID, varchar OBJECT_NAME, varchar SCRIPT_HASH, varchar STATUS, varchar log, varchar created_by, varchar created_ts; log.debug("Creating event for the object {} with status: {} and log: {} ", script.getObjectName(), status, logs); - String insertSql = "INSERT INTO " + SCRIPT_EVENT_TABLE_NAME + " SELECT UUID_STRING(), ?, ?, ?, ?, ?, ?, current_user, current_timestamp;"; + String insertSql = "INSERT INTO " + getFullyQualifiedTableName(SCRIPT_EVENT_TABLE_NAME) + " SELECT UUID_STRING(), ?, ?, ?, ?, ?, ?, current_user, current_timestamp;"; PreparedStatement statement = connection.prepareStatement(insertSql); statement.setString(1, script.getId()); statement.setObject(2, script.getFullObjectName()); @@ -301,14 +302,18 @@ public String getSchemaName() { return connectionProperties.getProperty("schema"); } + private String getFullyQualifiedTableName(String tableName) { + return String.format("%s.%s.%s", getDatabaseName(), getSchemaName(), tableName); + } + public ResultSet executeQuery(String query) throws SQLException { return connection.createStatement().executeQuery(query); } public void insertDependencyList(List dependencyList) throws SQLException { - String createTable = "CREATE TABLE IF NOT EXISTS " + DEPENDENCY_LINEAGE_TABLE_NAME + "(OBJECT_NAME VARCHAR, OBJECT_TYPE VARCHAR, DEPENDENCY VARCHAR, DEPENDECY_OBEJECT_TYPE VARCHAR, CHANGE_SYNC_ID VARCHAR, CREATED_BY VARCHAR, CREATED_TS TIMESTAMP);"; + String createTable = "CREATE TABLE IF NOT EXISTS " + getFullyQualifiedTableName(DEPENDENCY_LINEAGE_TABLE_NAME) + "(OBJECT_NAME VARCHAR, OBJECT_TYPE VARCHAR, DEPENDENCY VARCHAR, DEPENDECY_OBEJECT_TYPE VARCHAR, CHANGE_SYNC_ID VARCHAR, CREATED_BY VARCHAR, CREATED_TS TIMESTAMP);"; connection.createStatement().executeUpdate(createTable); - StringBuilder insertSql = new StringBuilder("INSERT INTO " + DEPENDENCY_LINEAGE_TABLE_NAME + " VALUES "); + StringBuilder insertSql = new StringBuilder("INSERT INTO " + getFullyQualifiedTableName(DEPENDENCY_LINEAGE_TABLE_NAME) + " VALUES "); for(ScriptDependency dependency: dependencyList) { String values = String.format("('%s', '%s', '%s', '%s', '%s', current_user, current_timestamp),", dependency.getObjectName(), dependency.getObjectType(), dependency.getDependency(), dependency.getDependencyObjectType(), changeSyncId); @@ -321,9 +326,10 @@ public void insertDependencyList(List dependencyList) throws S public void insertSortedScript(List