/**
   * Looks up a column in the database. If the column and table are not found, they are created, and
   * added to the schema. This is prevent foreign key relationships from having a null pointer.
   */
  private MutableColumn lookupOrCreateColumn(
      final String catalogName,
      final String schemaName,
      final String tableName,
      final String columnName) {
    final boolean supportsCatalogs =
        getRetrieverConnection().getDatabaseSystemParameters().isSupportsCatalogs();
    MutableColumn column = null;
    final MutableSchema schema = lookupSchema(supportsCatalogs ? catalogName : null, schemaName);
    if (schema != null) {
      MutableTable table = schema.getTable(tableName);
      if (table != null) {
        column = table.getColumn(columnName);
      }

      if (column == null) {
        // Create the table, but do not add it to the schema
        table = new MutableTable(schema, tableName);
        column = new MutableColumn(table, columnName);
        table.addColumn(column);

        LOGGER.log(
            Level.FINER,
            String.format(
                "Creating new column that is referenced by a foreign key: %s",
                column.getFullName()));
      }
    }
    return column;
  }
 private MutableColumn lookupOrCreateColumn(
     final MutableTable table, final String columnName, final boolean add) {
   MutableColumn column = null;
   if (table != null) {
     column = table.getColumn(columnName);
   }
   if (column == null) {
     column = new MutableColumn(table, columnName);
     if (add) {
       LOGGER.log(Level.FINER, String.format("Adding column to table: %s", column.getFullName()));
       table.addColumn(column);
     }
   }
   return column;
 }
  void retrieveColumns(final MutableTable table, final InclusionRule columnInclusionRule)
      throws SQLException {
    MetadataResultSet results = null;
    try {
      results =
          new MetadataResultSet(
              getMetaData()
                  .getColumns(
                      unquotedName(table.getSchema().getCatalogName()),
                      unquotedName(table.getSchema().getSchemaName()),
                      unquotedName(table.getName()),
                      null));

      while (results.next()) {
        // Get the "COLUMN_DEF" value first as it the Oracle drivers
        // don't handle it properly otherwise.
        // http://issues.apache.org/jira/browse/DDLUTILS-29?page=all
        final String defaultValue = results.getString("COLUMN_DEF");
        //
        final String columnCatalogName = quotedName(results.getString("TABLE_CAT"));
        final String schemaName = quotedName(results.getString("TABLE_SCHEM"));
        final String tableName = quotedName(results.getString("TABLE_NAME"));
        final String columnName = quotedName(results.getString("COLUMN_NAME"));
        LOGGER.log(Level.FINER, String.format("Retrieving column: %s.%s", tableName, columnName));

        MutableColumn column;

        column = lookupOrCreateColumn(table, columnName, false /* add */);
        final String columnFullName = column.getFullName();
        // Note: If the table name contains an underscore character,
        // this is a wildcard character. We need to do another check to
        // see if the table name matches.
        if (columnInclusionRule.include(columnFullName)
            && table.getName().equals(tableName)
            && belongsToSchema(table, columnCatalogName, schemaName)) {
          column = lookupOrCreateColumn(table, columnName, true /* add */);

          final int ordinalPosition = results.getInt("ORDINAL_POSITION", 0);
          final int dataType = results.getInt("DATA_TYPE", 0);
          final String typeName = results.getString("TYPE_NAME");
          final int size = results.getInt("COLUMN_SIZE", 0);
          final int decimalDigits = results.getInt("DECIMAL_DIGITS", 0);
          final boolean isNullable =
              results.getInt("NULLABLE", DatabaseMetaData.columnNullableUnknown)
                  == DatabaseMetaData.columnNullable;
          final String remarks = results.getString("REMARKS");

          column.setOrdinalPosition(ordinalPosition);
          column.setType(
              lookupOrCreateColumnDataType((MutableSchema) table.getSchema(), dataType, typeName));
          column.setSize(size);
          column.setDecimalDigits(decimalDigits);
          column.setRemarks(remarks);
          column.setNullable(isNullable);
          if (defaultValue != null) {
            column.setDefaultValue(defaultValue);
          }

          column.addAttributes(results.getAttributes());

          table.addColumn(column);
        }
      }
    } catch (final SQLException e) {
      throw new SchemaCrawlerSQLException("Could not retrieve columns for table " + table, e);
    } finally {
      if (results != null) {
        results.close();
      }
    }
  }