@Override public String[] getColumnNamesForProcedure(String procedureName) { List<String> ret = new ArrayList<String>(); try { DatabaseMetaData metaData = this.getConnection().getMetaData(); ResultSet results = metaData.getProcedureColumns(null, null, procedureName, null); if (null == results) { LOG.debug("Get Procedure Columns returns null"); return null; } try { while (results.next()) { if (results.getInt("COLUMN_TYPE") != DatabaseMetaData.procedureColumnReturn) { String name = results.getString("COLUMN_NAME"); ret.add(name); } } String[] result = ret.toArray(new String[ret.size()]); LOG.debug("getColumnsNamesForProcedure returns " + StringUtils.join(ret, ",")); return result; } finally { results.close(); getConnection().commit(); } } catch (SQLException e) { LoggingUtils.logAll(LOG, "Error reading procedure metadata: ", e); throw new RuntimeException("Can't fetch column names for procedure.", e); } }
@Override public String[] getColumnNames(String tableName) { Connection c = null; Statement s = null; ResultSet rs = null; List<String> columns = new ArrayList<String>(); String listColumnsQuery = getListColumnsQuery(tableName); try { c = getConnection(); s = c.createStatement(); rs = s.executeQuery(listColumnsQuery); while (rs.next()) { columns.add(rs.getString(1)); } c.commit(); } catch (SQLException sqle) { try { if (c != null) { c.rollback(); } } catch (SQLException ce) { LoggingUtils.logAll(LOG, "Failed to rollback transaction", ce); } LoggingUtils.logAll(LOG, "Failed to list columns from query: " + listColumnsQuery, sqle); throw new RuntimeException(sqle); } finally { if (rs != null) { try { rs.close(); } catch (SQLException re) { LoggingUtils.logAll(LOG, "Failed to close resultset", re); } } if (s != null) { try { s.close(); } catch (SQLException se) { LoggingUtils.logAll(LOG, "Failed to close statement", se); } } } return filterSpecifiedColumnNames(columns.toArray(new String[columns.size()])); }
@Override public String[] listTables() { Connection c = null; Statement s = null; ResultSet rs = null; List<String> tables = new ArrayList<String>(); try { c = getConnection(); s = c.createStatement(); rs = s.executeQuery(getListTablesQuery()); while (rs.next()) { tables.add(rs.getString(1)); } c.commit(); } catch (SQLException sqle) { try { if (c != null) { c.rollback(); } } catch (SQLException ce) { LoggingUtils.logAll(LOG, "Failed to rollback transaction", ce); } LoggingUtils.logAll(LOG, "Failed to list tables", sqle); throw new RuntimeException(sqle); } finally { if (rs != null) { try { rs.close(); } catch (SQLException re) { LoggingUtils.logAll(LOG, "Failed to close resultset", re); } } if (s != null) { try { s.close(); } catch (SQLException se) { LoggingUtils.logAll(LOG, "Failed to close statement", se); } } } return tables.toArray(new String[tables.size()]); }
@Override public Map<String, String> getColumnTypeNamesForProcedure(String procedureName) { Map<String, String> ret = new TreeMap<String, String>(); try { DatabaseMetaData metaData = this.getConnection().getMetaData(); ResultSet results = metaData.getProcedureColumns(null, null, procedureName, null); if (null == results) { LOG.debug("getColumnTypesForProcedure returns null"); return null; } try { while (results.next()) { if (results.getInt("COLUMN_TYPE") != DatabaseMetaData.procedureColumnReturn) { // we don't care if we get several rows for the // same ORDINAL_POSITION (e.g. like H2 gives us) // as we'll just overwrite the entry in the map: ret.put(results.getString("COLUMN_NAME"), results.getString("TYPE_NAME")); } } LOG.debug("Columns returned = " + StringUtils.join(ret.keySet(), ",")); LOG.debug("Type names returned = " + StringUtils.join(ret.values(), ",")); return ret.isEmpty() ? null : ret; } finally { if (results != null) { results.close(); } getConnection().commit(); } } catch (SQLException sqlException) { LoggingUtils.logAll( LOG, "Error reading primary key metadata: " + sqlException.toString(), sqlException); return null; } }
@Override public void execAndPrint(String s) { // Override default execAndPrint() with a special version that forces // use of fully-buffered ResultSets (MySQLManager uses streaming ResultSets // in the default execute() method; but the execAndPrint() method needs to // issue overlapped queries for metadata.) ResultSet results = null; try { // Explicitly setting fetchSize to zero disables streaming. results = super.execute(s, 0); } catch (SQLException sqlE) { LoggingUtils.logAll(LOG, "Error executing statement: ", sqlE); release(); return; } PrintWriter pw = new PrintWriter(System.out, true); try { formatAndPrintResultSet(results, pw); } finally { pw.close(); } }
@Override public String getPrimaryKey(String tableName) { Connection c = null; Statement s = null; ResultSet rs = null; List<String> columns = new ArrayList<String>(); try { c = getConnection(); s = c.createStatement(); String primaryKeyQuery = getPrimaryKeyQuery(tableName); LOG.debug( "Retrieving primary key for table '" + tableName + "' with query " + primaryKeyQuery); rs = s.executeQuery(primaryKeyQuery); while (rs.next()) { columns.add(rs.getString(1)); } c.commit(); } catch (SQLException sqle) { try { if (c != null) { c.rollback(); } } catch (SQLException ce) { LoggingUtils.logAll(LOG, "Failed to rollback transaction", ce); } LoggingUtils.logAll(LOG, "Failed to list primary key", sqle); throw new RuntimeException(sqle); } finally { if (rs != null) { try { rs.close(); } catch (SQLException re) { LoggingUtils.logAll(LOG, "Failed to close resultset", re); } } if (s != null) { try { s.close(); } catch (SQLException se) { LoggingUtils.logAll(LOG, "Failed to close statement", se); } } } if (columns.size() == 0) { // Table has no primary key return null; } if (columns.size() > 1) { // The primary key is multi-column primary key. Warn the user. LOG.warn( "The table " + tableName + " " + "contains a multi-column primary key. Sqoop will default to " + "the column " + columns.get(0) + " only for this job."); } return columns.get(0); }