/** * Validates a column against the model's field definition. Checks for existence, supported type, * type mapping, default value, defined lengths, primary key, autoincrement. */ private void validate( List<ValidationRemark> remarks, FieldDefinition fieldDef, boolean throwError) { // unknown field if (!columns.containsKey(fieldDef.columnName.toLowerCase())) { // unknown column mapping remarks.add(error(table, fieldDef, "Does not exist in database!").throwError(throwError)); return; } ColumnInspector col = columns.get(fieldDef.columnName.toLowerCase()); Class<?> fieldClass = fieldDef.field.getType(); Class<?> jdbcClass = ModelUtils.getClassForSqlType(col.type, dateTimeClass); // supported type check // iciql maps to VARCHAR for unsupported types. if (fieldDef.dataType.equals("VARCHAR") && (fieldClass != String.class)) { remarks.add( error( table, fieldDef, "iciql does not currently implement support for " + fieldClass.getName()) .throwError(throwError)); } // number types if (!fieldClass.equals(jdbcClass)) { if (Number.class.isAssignableFrom(fieldClass)) { remarks.add( warn( table, col, format( "Precision mismatch: ModelObject={0}, ColumnObject={1}", fieldClass.getSimpleName(), jdbcClass.getSimpleName()))); } else { if (!Date.class.isAssignableFrom(jdbcClass)) { remarks.add( warn( table, col, format( "Object Mismatch: ModelObject={0}, ColumnObject={1}", fieldClass.getSimpleName(), jdbcClass.getSimpleName()))); } } } // string types if (fieldClass == String.class) { if ((fieldDef.length != col.size) && (col.size < Integer.MAX_VALUE)) { remarks.add( warn( table, col, format( "{0}.length={1}, ColumnMaxLength={2}", IQColumn.class.getSimpleName(), fieldDef.length, col.size))); } if (fieldDef.length > 0 && !fieldDef.trim) { remarks.add( consider( table, col, format( "{0}.trim=true will prevent IciqlExceptions on" + " INSERT or UPDATE, but will clip data!", IQColumn.class.getSimpleName()))); } } // numeric autoIncrement if (fieldDef.isAutoIncrement != col.isAutoIncrement) { remarks.add( warn( table, col, format( "{0}.autoIncrement={1}" + " while Column autoIncrement={2}", IQColumn.class.getSimpleName(), fieldDef.isAutoIncrement, col.isAutoIncrement))); } // default value if (!col.isAutoIncrement && !col.isPrimaryKey) { String defaultValue = null; if (fieldDef.defaultValue != null && fieldDef.defaultValue instanceof String) { defaultValue = fieldDef.defaultValue.toString(); } // check Model.defaultValue format if (!ModelUtils.isProperlyFormattedDefaultValue(defaultValue)) { remarks.add( error( table, col, format( "{0}.defaultValue=\"{1}\"" + " is improperly formatted!", IQColumn.class.getSimpleName(), defaultValue)) .throwError(throwError)); // next field return; } // compare Model.defaultValue to Column.defaultValue if (isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) { // Model.defaultValue is NULL, Column.defaultValue is NOT NULL remarks.add( warn( table, col, format( "{0}.defaultValue=\"\"" + " while column default=\"{1}\"", IQColumn.class.getSimpleName(), col.defaultValue))); } else if (!isNullOrEmpty(defaultValue) && isNullOrEmpty(col.defaultValue)) { // Column.defaultValue is NULL, Model.defaultValue is NOT NULL remarks.add( warn( table, col, format( "{0}.defaultValue=\"{1}\"" + " while column default=\"\"", IQColumn.class.getSimpleName(), defaultValue))); } else if (!isNullOrEmpty(defaultValue) && !isNullOrEmpty(col.defaultValue)) { if (!defaultValue.equals(col.defaultValue)) { // Model.defaultValue != Column.defaultValue remarks.add( warn( table, col, format( "{0}.defaultValue=\"{1}\"" + " while column default=\"{2}\"", IQColumn.class.getSimpleName(), defaultValue, col.defaultValue))); } } // sanity check Model.defaultValue literal value if (!ModelUtils.isValidDefaultValue(fieldDef.field.getType(), defaultValue)) { remarks.add( error( table, col, format( "{0}.defaultValue=\"{1}\" is invalid!", IQColumn.class.getSimpleName(), defaultValue))); } } }
TableDefinition<T> createTableIfRequired(Db db) { if (!createTableIfRequired) { // skip table and index creation // but still check for upgrades db.upgradeTable(this); return this; } SQLDialect dialect = db.getDialect(); SQLStatement stat = new SQLStatement(db); StatementBuilder buff; if (memoryTable && dialect.supportsMemoryTables()) { buff = new StatementBuilder("CREATE MEMORY TABLE IF NOT EXISTS "); } else { buff = new StatementBuilder("CREATE TABLE IF NOT EXISTS "); } buff.append(dialect.getTableName(schemaName, tableName)).append('('); for (FieldDefinition field : fields) { buff.appendExceptFirst(", "); buff.append(field.columnName).append(' ').append(field.dataType); if (field.maxLength > 0) { buff.append('(').append(field.maxLength).append(')'); } if (field.isAutoIncrement) { buff.append(" AUTO_INCREMENT"); } if (!field.allowNull) { buff.append(" NOT NULL"); } // default values if (!field.isAutoIncrement && !field.isPrimaryKey) { String dv = field.defaultValue; if (!StringUtils.isNullOrEmpty(dv)) { if (ModelUtils.isProperlyFormattedDefaultValue(dv) && ModelUtils.isValidDefaultValue(field.field.getType(), dv)) { buff.append(" DEFAULT " + dv); } } } } // primary key if (primaryKeyColumnNames != null && primaryKeyColumnNames.size() > 0) { buff.append(", PRIMARY KEY("); buff.resetCount(); for (String n : primaryKeyColumnNames) { buff.appendExceptFirst(", "); buff.append(n); } buff.append(')'); } buff.append(')'); stat.setSQL(buff.toString()); StatementLogger.create(stat.getSQL()); stat.executeUpdate(); // create indexes for (IndexDefinition index : indexes) { String sql = db.getDialect().getCreateIndex(schemaName, tableName, index); stat.setSQL(sql); StatementLogger.create(stat.getSQL()); stat.executeUpdate(); } // tables are created using IF NOT EXISTS // but we may still need to upgrade db.upgradeTable(this); return this; }