@Test public void testMissingPKColumns() throws Exception { TestUtil util = getTestUtil(); WbConnection con = util.getConnection(); TestUtil.executeScript( con, "create table foobar (id1 integer not null, id2 integer not null, somedata varchar(50), primary key (id1, id2));\n" + "commit;"); String sql = "select id1, somedata from FOOBAR"; ResultInfo info = null; try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { info = new ResultInfo(rs.getMetaData(), con); } UpdateTableDetector detector = new UpdateTableDetector(con); detector.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("foobar"); detector.checkUpdateTable(toCheck, info); TableIdentifier tbl = detector.getUpdateTable(); assertEquals("FOOBAR", tbl.getTableName()); assertTrue(info.getColumn(0).isPkColumn()); assertFalse(info.getColumn(1).isPkColumn()); List<ColumnIdentifier> cols = detector.getMissingPkColumns(); assertNotNull(cols); assertEquals(1, cols.size()); assertEquals("ID2", cols.get(0).getColumnName()); }
@Test public void testNotNullIndex() throws Exception { TestUtil util = getTestUtil(); WbConnection conn = util.getConnection(); TestUtil.executeScript( conn, "create table person (id integer, id2 integer not null, name varchar(20) not null);\n" + "create unique index aaaa on person (id);\n" + "create unique index zzzz on person (id2);\n" + "commit;"); String sql = "select id, id2, name from person"; ResultInfo info = null; try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { info = new ResultInfo(rs.getMetaData(), conn); } UpdateTableDetector detector = new UpdateTableDetector(conn); detector.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("person"); detector.checkUpdateTable(toCheck, info); TableIdentifier tbl = detector.getUpdateTable(); assertEquals("PERSON", tbl.getTableName()); assertFalse(info.getColumn(0).isPkColumn()); assertTrue(info.getColumn(1).isPkColumn()); }
@Test public void testMultipleSchemas() throws Exception { TestUtil util = getTestUtil(); WbConnection con = util.getConnection(); TestUtil.executeScript( con, "create schema one;\n" + "create schema two;\n" + "create table public.foobar (id integer not null primary key, somedata varchar(50));\n" + "create table one.foobar (id_one integer not null primary key, somedata varchar(50));\n" + "create table two.foobar (id_two integer not null primary key, somedata varchar(50));\n" + "commit;"); String sql = "select id, somedata from foobar"; ResultInfo info = null; try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { info = new ResultInfo(rs.getMetaData(), con); } UpdateTableDetector detector = new UpdateTableDetector(con); detector.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("foobar"); detector.checkUpdateTable(toCheck, info); TableIdentifier tbl = detector.getUpdateTable(); assertEquals("FOOBAR", tbl.getTableName()); assertEquals("PUBLIC", tbl.getSchema()); assertTrue(CollectionUtil.isEmpty(detector.getMissingPkColumns())); }
@Test public void testDetectUpdateTable2() throws Exception { WbConnection con = PostgresTestUtil.getPostgresConnection(); assertNotNull(con); TestUtil.executeScript(con, "set search_path=path_2,path3,path_1"); Statement stmt = null; ResultSet rs = null; try { stmt = con.createStatement(); String sql = "select * from t2"; rs = stmt.executeQuery(sql); DataStore ds1 = new DataStore(rs, con); SqlUtil.closeResult(rs); ds1.setGeneratingSql(sql); ds1.checkUpdateTable(con); TableIdentifier tbl1 = ds1.getUpdateTable(); assertNotNull(tbl1); assertEquals("path_2", tbl1.getSchema()); assertEquals("t2", tbl1.getTableName()); assertTrue(ds1.hasPkColumns()); List<ColumnIdentifier> missing = ds1.getMissingPkColumns(); assertTrue(CollectionUtil.isEmpty(missing)); } finally { SqlUtil.closeStatement(stmt); } }
private DataStore getImportedKeyList(TableIdentifier tbl) throws SQLException { // I'm not adding an ORDER BY because the statement is terribly slow anyway // and an ORDER BY makes it even slower for large results StringBuilder sql = new StringBuilder(baseSql.length() + 50); sql.append(getQuery(tbl)); sql.append("AND f.table_name = ? \n"); sql.append("AND f.owner = ? \n"); if (Settings.getInstance().getDebugMetadataSql()) { LogMgr.logDebug( "OracleFKHandler.getImportedKeyList()", "Retrieving imported foreign keys using:\n" + SqlUtil.replaceParameters(sql, tbl.getRawTableName(), tbl.getRawSchema())); } ResultSet rs; DataStore result = null; try { retrievalStatement = this.getConnection().getSqlConnection().prepareStatement(sql.toString()); retrievalStatement.setString(1, tbl.getRawTableName()); retrievalStatement.setString(2, tbl.getRawSchema()); rs = retrievalStatement.executeQuery(); result = processResult(rs); } finally { // the result set is closed by processResult SqlUtil.closeStatement(retrievalStatement); retrievalStatement = null; } sortResult(result); return result; }
/** * Adjust the baseSql query to reflect if a table for the current user is queried. * * <p>If the table belongs to the current user, the user_XXX views can be used instead of the * all_XXX views. Using the user_XXX views is faster (at least on my system) than the all_XXX * views - although it is still an awfully slow statement... <br> * Querying user_constraints instead of all_constraints means that constraints between two schemas * will not be shown. In order to still enable this, the config property: <br> * <code>workbench.db.oracle.optimize_fk_query</code> <br> * can be set to false, if all_constraints should always be queried. * * @param tbl the table for which the query should be generated * @return the query to use * @see OracleUtils#optimizeCatalogQueries() */ private String getQuery(TableIdentifier tbl) { if (OracleUtils.optimizeCatalogQueries()) { String schema = tbl.getRawSchema(); if (StringUtil.isEmptyString(schema) || schema.equalsIgnoreCase(currentUser)) { return baseSql.replace(" all_c", " user_c"); } } return baseSql; }
@Test public void testDuplicateNames() throws Exception { TestUtil util = getTestUtil(); WbConnection con = util.getConnection(); String sql = "CREATE TABLE one (ident int, refid int, PRIMARY KEY(ident));\n" + "CREATE TABLE two (ident int, refid int, PRIMARY KEY(ident));\n" + "commit;"; TestUtil.executeScript(con, sql); String query = "SELECT one.ident, two.ident \n" + "FROM one, two \n" + "WHERE one.refid = two.refid;"; ResultInfo info = null; try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query)) { info = new ResultInfo(rs.getMetaData(), con); } SourceTableDetector std = new SourceTableDetector(); std.checkColumnTables(query, info, con); UpdateTableDetector utd = new UpdateTableDetector(con); utd.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("TWO"); utd.checkUpdateTable(toCheck, info); TableIdentifier tbl = utd.getUpdateTable(); assertEquals("TWO", tbl.getTableName()); assertEquals("PUBLIC", tbl.getSchema()); assertEquals("one", info.getColumn(0).getSourceTableName()); assertEquals("two", info.getColumn(1).getSourceTableName()); assertTrue(info.getColumn(1).isUpdateable()); assertTrue(info.getColumn(1).isPkColumn()); assertTrue(CollectionUtil.isEmpty(utd.getMissingPkColumns())); }
private void searchList( List<DbObject> toSearch, List<String> searchValues, boolean matchAll, boolean ignoreCase, boolean useRegex) { if (monitor != null) { monitor.setMonitorType(RowActionMonitor.MONITOR_PROCESS); } int total = toSearch.size(); int current = 1; for (DbObject object : toSearch) { numSearched++; if (cancelSearch) return; if (monitor != null) { monitor.setCurrentObject(object.getObjectName(), current, total); } try { CharSequence source = null; if (connection.getMetadata().isTableType(object.getObjectType())) { ((TableIdentifier) object).setRetrieveFkSource(true); } ProcedureDefinition def = null; if (object instanceof ProcedureDefinition) { def = (ProcedureDefinition) object; } String key = getObjectKey(object); if (!searchedObjects.contains(key)) { source = object.getSource(connection); if (StringUtil.isBlank(source)) { LogMgr.logWarning( "ObjectSourceSearcher.searchObjects()", "Empty source returned for " + object.toString()); } if (StringUtil.containsWords(source, searchValues, matchAll, ignoreCase, useRegex)) { searchResult.add(object); } searchedObjects.add(key); } } catch (SQLException sql) { LogMgr.logError( "ObjectSourceSearcher.searchObjects()", "Error retrieving object source", sql); } current++; } }
private void syncSingleSequence(WbConnection dbConnection, TableIdentifier table, String column) throws SQLException { Statement stmt = null; ResultSet rs = null; try { stmt = dbConnection.createStatement(); long maxValue = -1; rs = stmt.executeQuery( "select max(" + column + ") from " + table.getTableExpression(dbConnection)); if (rs.next()) { maxValue = rs.getLong(1) + 1; SqlUtil.closeResult(rs); } if (maxValue > 0) { String ddl = "alter table " + table.getTableExpression(dbConnection) + " alter column " + column + " restart with " + Long.toString(maxValue); LogMgr.logDebug( "FirebirdSequenceAdjuster.syncSingleSequence()", "Syncing sequence using: " + ddl); stmt.execute(ddl); } } catch (SQLException ex) { LogMgr.logError( "FirebirdSequenceAdjuster.getColumnSequences()", "Could not read sequences", ex); throw ex; } finally { SqlUtil.closeAll(rs, stmt); } }
@Test public void testSpecialName() throws Exception { TestUtil util = getTestUtil(); WbConnection con = util.getConnection(); TestUtil.executeScript( con, "create table \"FOO.BAR\" (id integer primary key, somedata varchar(50));\n" + "commit;"); String sql = "select id, somedata from \"FOO.BAR\""; ResultInfo info = null; try (Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { info = new ResultInfo(rs.getMetaData(), con); } UpdateTableDetector detector = new UpdateTableDetector(con); detector.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("\"FOO.BAR\""); detector.checkUpdateTable(toCheck, info); TableIdentifier tbl = detector.getUpdateTable(); assertEquals("FOO.BAR", tbl.getTableName()); assertTrue(info.getColumn(0).isPkColumn()); assertFalse(info.getColumn(1).isPkColumn()); resetInfo(info); detector.setCheckPKOnly(true); detector.checkUpdateTable(toCheck, info); tbl = detector.getUpdateTable(); assertEquals("FOO.BAR", tbl.getTableName()); assertTrue(info.getColumn(0).isPkColumn()); assertFalse(info.getColumn(1).isPkColumn()); }
@Test public void testSynonyms() throws Exception { TestUtil util = getTestUtil(); WbConnection conn = DerbyTestUtil.getDerbyConnection(util.getBaseDir()); TestUtil.executeScript( conn, "create table person (id integer primary key, name varchar(20) not null);\n" + "create synonym psyn for person;\n"); String sql = "select id, name from psyn"; ResultInfo info = null; try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) { info = new ResultInfo(rs.getMetaData(), conn); } info.getColumn(0).setIsPkColumn(false); UpdateTableDetector detector = new UpdateTableDetector(conn); detector.setCheckPKOnly(false); TableIdentifier toCheck = new TableIdentifier("psyn"); detector.checkUpdateTable(toCheck, info); TableIdentifier tbl = detector.getUpdateTable(); assertEquals("PSYN", tbl.getTableName()); assertTrue(info.getColumn(0).isPkColumn()); assertFalse(info.getColumn(1).isPkColumn()); resetInfo(info); detector.setCheckPKOnly(true); detector.checkUpdateTable(toCheck, info); assertEquals("PSYN", tbl.getTableName()); assertTrue(info.getColumn(0).isPkColumn()); assertFalse(info.getColumn(1).isPkColumn()); }
@Test public void testDetectUpdateTable() throws Exception { WbConnection con = PostgresTestUtil.getPostgresConnection(); assertNotNull(con); TestUtil.executeScript(con, "set search_path=path_2,path_1"); Statement stmt = null; ResultSet rs = null; try { stmt = con.createStatement(); String sql = "select * from t1"; rs = stmt.executeQuery(sql); DataStore ds1 = new DataStore(rs, con); SqlUtil.closeResult(rs); ds1.setGeneratingSql(sql); ds1.checkUpdateTable(con); TableIdentifier tbl1 = ds1.getUpdateTable(); assertNotNull(tbl1); assertEquals("path_1", tbl1.getSchema()); sql = "select * from t2"; rs = stmt.executeQuery(sql); DataStore ds2 = new DataStore(rs, con); SqlUtil.closeResult(rs); ds2.setGeneratingSql(sql); ds2.checkUpdateTable(con); TableIdentifier tbl2 = ds2.getUpdateTable(); assertNotNull(tbl2); assertEquals("path_2", tbl2.getSchema()); } finally { SqlUtil.closeStatement(stmt); } }
private void updateDateColumns(TableDefinition table, WbConnection conn) { String catalog = table.getTable().getRawCatalog(); String systemSchema = conn.getDbSettings().getProperty("systemschema", "informix"); TableIdentifier sysTabs = new TableIdentifier(catalog, systemSchema, "systables"); TableIdentifier sysCols = new TableIdentifier(catalog, systemSchema, "syscolumns"); String systables = sysTabs.getFullyQualifiedName(conn); String syscolumns = sysCols.getFullyQualifiedName(conn); String typeValues = conn.getDbSettings().getProperty("qualifier.typevalues", "10,14,266,270"); String sql = "select c.colname, c.collength \n" + "from " + systables + " t \n" + " join " + syscolumns + " c on t.tabid = c.tabid \n" + "where t.tabname = ? \n" + " and t.owner = ? \n" + " and c.coltype in (" + typeValues + ")"; String tablename = table.getTable().getRawTableName(); String schema = table.getTable().getRawSchema(); LogMgr.logDebug( "InformixColumnEnhancer.updateDateColumns()", "Query to retrieve column details:\n" + SqlUtil.replaceParameters(sql, tablename, schema)); PreparedStatement stmt = null; ResultSet rs = null; Map<String, ColumnIdentifier> cols = new TreeMap<>(CaseInsensitiveComparator.INSTANCE); for (ColumnIdentifier col : table.getColumns()) { cols.put(col.getColumnName(), col); } try { stmt = conn.getSqlConnection().prepareStatement(sql); stmt.setString(1, tablename); stmt.setString(2, schema); rs = stmt.executeQuery(); while (rs.next()) { String colname = rs.getString(1); int colLength = rs.getInt(2); ColumnIdentifier col = cols.get(colname); if (col != null) { String typeDesc = getQualifier(colLength); String dbms = SqlUtil.getPlainTypeName(col.getDbmsType()); String newType = dbms + " " + typeDesc; LogMgr.logDebug( "InformixColumnEnhancer.updateDateColumns()", "Column " + tablename + "." + colname + " has collength of: " + colLength + ". Changing type '" + col.getDbmsType() + "' to '" + newType + "'"); col.setDbmsType(newType); } else { LogMgr.logError( "InformixColumnEnhancer.updateDateColumns()", "The query returned a column name (" + colname + ") that was not part of the passed table definition!", null); } } } catch (Exception e) { LogMgr.logError( "InformixColumnEnhancer.updateDateColumns()", "Error retrieving datetime qualifiers using:\n" + SqlUtil.replaceParameters(sql, tablename, schema), e); } finally { SqlUtil.closeAll(rs, stmt); } }
protected void retrieveCurrentTrigger() { if (this.dbConnection == null || this.reader == null) return; int row = this.triggerList.getSelectedRow(); if (!WbSwingUtilities.isConnectionIdle(this, this.dbConnection)) return; if (row < 0) return; final String triggerName = this.triggerList.getValueAsString(row, TriggerReader.COLUMN_IDX_TABLE_TRIGGERLIST_TRG_NAME); final String tableName = this.triggerList.getValueAsString( row, TriggerReader.COLUMN_IDX_TABLE_TRIGGERLIST_TRG_TABLE); final String comment = this.triggerList.getValueAsString( row, TriggerReader.COLUMN_IDX_TABLE_TRIGGERLIST_TRG_COMMENT); Container parent = this.getParent(); WbSwingUtilities.showWaitCursor(parent); try { if (dbConnection.getProfile().getUseSeparateConnectionPerTab()) { levelChanger.changeIsolationLevel(dbConnection); } dbConnection.setBusy(true); try { TableIdentifier tbl = null; if (tableName != null) { tbl = new TableIdentifier(tableName, dbConnection); if (tbl.getCatalog() == null) tbl.setCatalog(currentCatalog); if (tbl.getSchema() == null) tbl.setSchema(currentSchema); } DropType dropType = DbExplorerSettings.getDropTypeToGenerate(TriggerDefinition.TRIGGER_TYPE_NAME); String sql = reader.getTriggerSource(currentCatalog, currentSchema, triggerName, tbl, comment, true); Object obj = triggerList.getUserObject(row); boolean isReplace = SqlUtil.isReplaceDDL(sql, dbConnection, dropType); if (dropType != DropType.none && obj instanceof TriggerDefinition && sql != null && !isReplace) { TriggerDefinition trg = (TriggerDefinition) obj; String drop = trg.getDropStatement(dbConnection, dropType == DropType.cascaded); if (StringUtil.isNonBlank(drop)) { sql = drop + getDelimiterForDrop() + "\n\n" + sql; } } final String sourceSql = sql == null ? "" : sql; WbSwingUtilities.invoke( () -> { source.setText(sourceSql, triggerName, TRG_TYPE_NAME); }); } catch (Throwable ex) { LogMgr.logError( "TriggerListPanel.retrieveTriggerSource() thread", "Could not read trigger source", ex); source.setPlainText(ExceptionUtil.getDisplay(ex)); } } finally { WbSwingUtilities.showDefaultCursor(parent); levelChanger.restoreIsolationLevel(dbConnection); dbConnection.setBusy(false); } if (this.triggerList.getSelectedRowCount() == 1) { EventQueue.invokeLater( () -> { source.setCaretPosition(0, false); if (DbExplorerSettings.getSelectSourcePanelAfterRetrieve()) { source.requestFocusInWindow(); } }); } }