Why is the IS_AUTOINCREMENT metadata column returning inconsistent values based on type for MS SQL Server?

StackOverflow https://stackoverflow.com//questions/20028108

  •  21-12-2019
  •  | 
  •  

Question

I'm trying to get database schema information dynamically from the database connection, and I've encountered an odd problem. I'm not sure how this is even happening in a resultset, but it's only happening with MS SQL Server. The "IS_AUTOINCREMENT" column value is retrieved properly as "YES" when I request it using ResultSet.getString(). But when I request it using Request.getBoolean(), it improperly returns FALSE for auto-increment columns.

public Collection<DBTable> getTables() {
    HashSet<DBTable> tables = new HashSet<>();
    try {
        ResultSet rs = this.conn().getMetaData().getTables(this.conn().getCatalog(), null, null, new String[] { "TABLE" });
        while (rs.next()) {
            String catalog = rs.getString("TABLE_CAT");
            String schema = rs.getString("TABLE_SCHEM"); 
            String name = rs.getString("TABLE_NAME");
            DBTable table = new DBTable(catalog, schema, name);
            ResultSet columns = this.conn().getMetaData().getColumns(catalog, schema, name, null);
            while (columns.next()) {
                String columnName = columns.getString("COLUMN_NAME");
                int dataType = columns.getInt("DATA_TYPE"); // from java.sql.Types
                String typeName = columns.getString("TYPE_NAME");
                int columnSize = columns.getInt("COLUMN_SIZE");
                boolean isNullable = columns.getBoolean("IS_NULLABLE");
                boolean isAutoIncrement = columns.getBoolean("IS_AUTOINCREMENT");
                String autoIncString = columns.getString("IS_AUTOINCREMENT");
                if (autoIncString.equals("YES") && !isAutoIncrement)
                    throw new IllegalStateException("Why is string YES but boolean FALSE?");
                table.addColumn(new DBColumn(columnName, dataType, typeName, columnSize, isNullable, isAutoIncrement));
            }
            columns.close();
            tables.add(table);
        }
        rs.close();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return tables;
}

In this example code, the IllegalStateException is being thrown in MS SQL, but not in MySQL, when it processes an autoincrement field. I'm using JTDS v1.3.1 for SQL Server and connector/j 5.1.27 for MySQL. I'm not even sure how this can happen in a ResultSet at all.

I added some code to loop through columns (the ResultSet) to check for the data type:

for (int x = 1; x <= columns.getMetaData().getColumnCount(); x++)
    System.out.println(x + ": " + columns.getMetaData().getColumnName(x)+ " (" + columns.getMetaData().getColumnType(x) + ")");

This verifies that for MySQL and MS SQL both, the "IS_AUTOINCREMENT" column returns as a String (data type 1 from java.sql.Types). So I feel like my solution here is just to compare it to "YES" to make it true. But I still want to understand what's going on here. Any ideas?

Was it helpful?

Solution

I guess at some lower level, the "YES" answer is typed as a String -- not as a boolean. Then it comes back to you as a String.

This kind of thing is not unheard of with metadata queries, they're often put together in funky ways within the JDBC driver, and depend on what the underlying database has to offer in the way of system tables.

It's probably easier (on a lowest-common-denominator basis) to format truth-typed answers to strings, especially since 'boolean' support & compatibility is quite variable between databases.

The Java specification also says, that all of these are expected to be returned as string.

See: - http://docs.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#getColumns(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String)

Long story short -- this is the way it is, just work with it. With one little caveat: I wouldn't personally depend on exact case of the answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top