@Override protected void loadUniqueKeys(DefaultRelations relations) throws SQLException { for (Record record : fetchKeys(false)) { SchemaDefinition schema = getSchema(record.get(Statistics.TABLE_SCHEMA)); String constraintName = record.get(Statistics.INDEX_NAME); String tableName = record.get(Statistics.TABLE_NAME); String columnName = record.get(Statistics.COLUMN_NAME); String key = getKeyName(tableName, constraintName); TableDefinition table = getTable(schema, tableName); if (table != null) { relations.addUniqueKey(key, table.getColumn(columnName)); } } }
@Override protected List<TableDefinition> getTables0() throws SQLException { List<TableDefinition> result = new ArrayList<TableDefinition>(); for (Record record : create() .select(Tables.TABLE_SCHEMA, Tables.TABLE_NAME, Tables.TABLE_COMMENT) .from(TABLES) .where(Tables.TABLE_SCHEMA.in(getInputSchemata())) .orderBy(Tables.TABLE_SCHEMA, Tables.TABLE_NAME) .fetch()) { SchemaDefinition schema = getSchema(record.get(Tables.TABLE_SCHEMA)); String name = record.get(Tables.TABLE_NAME); String comment = record.get(Tables.TABLE_COMMENT); MySQLTableDefinition table = new MySQLTableDefinition(schema, name, comment); result.add(table); } return result; }
@Override protected void init0() throws SQLException { for (Record record : create() .select( FunctionColumns.COLUMN_NAME, FunctionColumns.TYPE_NAME, FunctionColumns.PRECISION, FunctionColumns.SCALE, FunctionColumns.POS, FunctionColumns.NULLABLE, FunctionColumns.COLUMN_DEFAULT) .from(FUNCTION_COLUMNS) .where(FunctionColumns.ALIAS_SCHEMA.equal(getSchema().getName())) .and(FunctionColumns.ALIAS_NAME.equal(getName())) // [#4193] recent versions of H2 produce a row for the function // return value at position 0 .and(FunctionColumns.POS.gt(0)) .orderBy(FunctionColumns.POS.asc()) .fetch()) { String paramName = record.get(FunctionColumns.COLUMN_NAME); String typeName = record.get(FunctionColumns.TYPE_NAME); Integer precision = record.get(FunctionColumns.PRECISION); Short scale = record.get(FunctionColumns.SCALE); int position = record.get(FunctionColumns.POS); boolean nullable = record.get(FunctionColumns.NULLABLE, boolean.class); String defaultValue = record.get(FunctionColumns.COLUMN_DEFAULT); // VERY special case for H2 alias/function parameters. The first parameter // may be a java.sql.Connection object and in such cases it should NEVER be used. // It is only used internally by H2 to provide a connection to the current database. if (position == 0 && H2DataType.OTHER.getTypeName().equalsIgnoreCase(typeName)) { continue; } DataTypeDefinition type = new DefaultDataTypeDefinition( getDatabase(), getSchema(), typeName, precision, precision, scale, nullable, defaultValue); ParameterDefinition parameter = new DefaultParameterDefinition(this, paramName, position, type); addParameter(InOutDefinition.IN, parameter); } }
@Override protected List<RoutineDefinition> getRoutines0() throws SQLException { List<RoutineDefinition> result = new ArrayList<RoutineDefinition>(); try { create(true).fetchCount(PROC); } catch (DataAccessException e) { log.warn( "Table unavailable", "The `mysql`.`proc` table is unavailable. Stored procedures cannot be loaded. Check if you have sufficient grants"); return result; } Result<Record6<String, String, String, byte[], byte[], ProcType>> records = create() .select(Proc.DB, Proc.NAME, Proc.COMMENT, Proc.PARAM_LIST, Proc.RETURNS, Proc.TYPE) .from(PROC) .where(DB.in(getInputSchemata())) .orderBy(DB, Proc.NAME) .fetch(); Map<Record, Result<Record6<String, String, String, byte[], byte[], ProcType>>> groups = records.intoGroups(new Field[] {Proc.DB, Proc.NAME}); // [#1908] This indirection is necessary as MySQL allows for overloading // procedures and functions with the same signature. for (Entry<Record, Result<Record6<String, String, String, byte[], byte[], ProcType>>> entry : groups.entrySet()) { Result<?> overloads = entry.getValue(); for (int i = 0; i < overloads.size(); i++) { Record record = overloads.get(i); SchemaDefinition schema = getSchema(record.get(DB)); String name = record.get(Proc.NAME); String comment = record.get(Proc.COMMENT); String params = new String(record.get(Proc.PARAM_LIST)); String returns = new String(record.get(Proc.RETURNS)); ProcType type = record.get(Proc.TYPE); if (overloads.size() > 1) { result.add( new MySQLRoutineDefinition( schema, name, comment, params, returns, type, "_" + type.name())); } else { result.add( new MySQLRoutineDefinition(schema, name, comment, params, returns, type, null)); } } } return result; }
@Override protected void loadForeignKeys(DefaultRelations relations) throws SQLException { for (Record record : create() .select( ReferentialConstraints.CONSTRAINT_SCHEMA, ReferentialConstraints.CONSTRAINT_NAME, ReferentialConstraints.TABLE_NAME, ReferentialConstraints.REFERENCED_TABLE_NAME, ReferentialConstraints.UNIQUE_CONSTRAINT_NAME, ReferentialConstraints.UNIQUE_CONSTRAINT_SCHEMA, KeyColumnUsage.COLUMN_NAME) .from(REFERENTIAL_CONSTRAINTS) .join(KEY_COLUMN_USAGE) .on(ReferentialConstraints.CONSTRAINT_SCHEMA.equal(KeyColumnUsage.CONSTRAINT_SCHEMA)) .and(ReferentialConstraints.CONSTRAINT_NAME.equal(KeyColumnUsage.CONSTRAINT_NAME)) .where(ReferentialConstraints.CONSTRAINT_SCHEMA.in(getInputSchemata())) .orderBy( KeyColumnUsage.CONSTRAINT_SCHEMA.asc(), KeyColumnUsage.CONSTRAINT_NAME.asc(), KeyColumnUsage.ORDINAL_POSITION.asc()) .fetch()) { SchemaDefinition foreignKeySchema = getSchema(record.get(ReferentialConstraints.CONSTRAINT_SCHEMA)); SchemaDefinition uniqueKeySchema = getSchema(record.get(ReferentialConstraints.UNIQUE_CONSTRAINT_SCHEMA)); String foreignKey = record.get(ReferentialConstraints.CONSTRAINT_NAME); String foreignKeyColumn = record.get(KeyColumnUsage.COLUMN_NAME); String foreignKeyTableName = record.get(ReferentialConstraints.TABLE_NAME); String referencedKey = record.get(ReferentialConstraints.UNIQUE_CONSTRAINT_NAME); String referencedTableName = record.get(ReferentialConstraints.REFERENCED_TABLE_NAME); TableDefinition foreignKeyTable = getTable(foreignKeySchema, foreignKeyTableName); if (foreignKeyTable != null) { ColumnDefinition column = foreignKeyTable.getColumn(foreignKeyColumn); String key = getKeyName(referencedTableName, referencedKey); relations.addForeignKey(foreignKey, key, column, uniqueKeySchema); } } }
@Override protected List<EnumDefinition> getEnums0() throws SQLException { List<EnumDefinition> result = new ArrayList<EnumDefinition>(); Result<Record5<String, String, String, String, String>> records = create() .select( Columns.TABLE_SCHEMA, Columns.COLUMN_COMMENT, Columns.TABLE_NAME, Columns.COLUMN_NAME, Columns.COLUMN_TYPE) .from(COLUMNS) .where( Columns.COLUMN_TYPE .like("enum(%)") .and(Columns.TABLE_SCHEMA.in(getInputSchemata()))) .orderBy( Columns.TABLE_SCHEMA.asc(), Columns.TABLE_NAME.asc(), Columns.COLUMN_NAME.asc()) .fetch(); for (Record record : records) { SchemaDefinition schema = getSchema(record.get(Columns.TABLE_SCHEMA)); String comment = record.get(Columns.COLUMN_COMMENT); String table = record.get(Columns.TABLE_NAME); String column = record.get(Columns.COLUMN_NAME); String name = table + "_" + column; String columnType = record.get(Columns.COLUMN_TYPE); // [#1237] Don't generate enum classes for columns in MySQL tables // that are excluded from code generation TableDefinition tableDefinition = getTable(schema, table); if (tableDefinition != null) { ColumnDefinition columnDefinition = tableDefinition.getColumn(column); if (columnDefinition != null) { // [#1137] Avoid generating enum classes for enum types that // are explicitly forced to another type if (getConfiguredForcedType(columnDefinition, columnDefinition.getType()) == null) { DefaultEnumDefinition definition = new DefaultEnumDefinition(schema, name, comment); CSVReader reader = new CSVReader( new StringReader(columnType.replaceAll("(^enum\\()|(\\)$)", "")), ',' // Separator , '\'' // Quote character , true // Strict quotes ); for (String string : reader.next()) { definition.addLiteral(string); } result.add(definition); } } } } return result; }