Search in sources :

Example 1 with Comment

use of org.h2.engine.Comment in project h2database by h2database.

the class Parser method parseColumnForTable.

private Column parseColumnForTable(String columnName, boolean defaultNullable) {
    Column column;
    boolean isIdentity = readIf("IDENTITY");
    if (isIdentity || readIf("BIGSERIAL")) {
        // Check if any of them are disallowed in the current Mode
        if (isIdentity && database.getMode().disallowedTypes.contains("IDENTITY")) {
            throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, currentToken);
        }
        column = new Column(columnName, Value.LONG);
        column.setOriginalSQL("IDENTITY");
        parseAutoIncrement(column);
        // PostgreSQL compatibility
        if (!database.getMode().serialColumnIsNotPK) {
            column.setPrimaryKey(true);
        }
    } else if (readIf("SERIAL")) {
        column = new Column(columnName, Value.INT);
        column.setOriginalSQL("SERIAL");
        parseAutoIncrement(column);
        // PostgreSQL compatibility
        if (!database.getMode().serialColumnIsNotPK) {
            column.setPrimaryKey(true);
        }
    } else {
        column = parseColumnWithType(columnName);
    }
    if (readIf("INVISIBLE")) {
        column.setVisible(false);
    } else if (readIf("VISIBLE")) {
        column.setVisible(true);
    }
    NullConstraintType nullConstraint = parseNotNullConstraint();
    switch(nullConstraint) {
        case NULL_IS_ALLOWED:
            column.setNullable(true);
            break;
        case NULL_IS_NOT_ALLOWED:
            column.setNullable(false);
            break;
        case NO_NULL_CONSTRAINT_FOUND:
            // domains may be defined as not nullable
            column.setNullable(defaultNullable & column.isNullable());
            break;
        default:
            throw DbException.get(ErrorCode.UNKNOWN_MODE_1, "Internal Error - unhandled case: " + nullConstraint.name());
    }
    if (readIf("AS")) {
        if (isIdentity) {
            getSyntaxError();
        }
        Expression expr = readExpression();
        column.setComputedExpression(expr);
    } else if (readIf("DEFAULT")) {
        Expression defaultExpression = readExpression();
        column.setDefaultExpression(session, defaultExpression);
    } else if (readIf("GENERATED")) {
        if (!readIf("ALWAYS")) {
            read("BY");
            read("DEFAULT");
        }
        read("AS");
        read("IDENTITY");
        long start = 1, increment = 1;
        if (readIf("(")) {
            read("START");
            readIf("WITH");
            start = readLong();
            readIf(",");
            if (readIf("INCREMENT")) {
                readIf("BY");
                increment = readLong();
            }
            read(")");
        }
        column.setPrimaryKey(true);
        column.setAutoIncrement(true, start, increment);
    }
    if (readIf("ON")) {
        read("UPDATE");
        Expression onUpdateExpression = readExpression();
        column.setOnUpdateExpression(session, onUpdateExpression);
    }
    if (NullConstraintType.NULL_IS_NOT_ALLOWED == parseNotNullConstraint()) {
        column.setNullable(false);
    }
    if (readIf("AUTO_INCREMENT") || readIf("BIGSERIAL") || readIf("SERIAL")) {
        parseAutoIncrement(column);
        parseNotNullConstraint();
    } else if (readIf("IDENTITY")) {
        parseAutoIncrement(column);
        column.setPrimaryKey(true);
        parseNotNullConstraint();
    }
    if (readIf("NULL_TO_DEFAULT")) {
        column.setConvertNullToDefault(true);
    }
    if (readIf("SEQUENCE")) {
        Sequence sequence = readSequence();
        column.setSequence(sequence);
    }
    if (readIf("SELECTIVITY")) {
        int value = readPositiveInt();
        column.setSelectivity(value);
    }
    String comment = readCommentIf();
    if (comment != null) {
        column.setComment(comment);
    }
    return column;
}
Also used : AlterTableRenameColumn(org.h2.command.ddl.AlterTableRenameColumn) AlterTableAlterColumn(org.h2.command.ddl.AlterTableAlterColumn) Column(org.h2.table.Column) ExpressionColumn(org.h2.expression.ExpressionColumn) IndexColumn(org.h2.table.IndexColumn) Expression(org.h2.expression.Expression) ValueExpression(org.h2.expression.ValueExpression) DropSequence(org.h2.command.ddl.DropSequence) CreateSequence(org.h2.command.ddl.CreateSequence) Sequence(org.h2.schema.Sequence) AlterSequence(org.h2.command.dml.AlterSequence) ValueString(org.h2.value.ValueString) AlterTableRenameConstraint(org.h2.command.ddl.AlterTableRenameConstraint) AlterTableAddConstraint(org.h2.command.ddl.AlterTableAddConstraint) AlterTableDropConstraint(org.h2.command.ddl.AlterTableDropConstraint)

Example 2 with Comment

use of org.h2.engine.Comment in project h2database by h2database.

the class Parser method parseColumnWithType.

private Column parseColumnWithType(String columnName) {
    String original = currentToken;
    boolean regular = false;
    int originalScale = -1;
    if (readIf("LONG")) {
        if (readIf("RAW")) {
            original += " RAW";
        }
    } else if (readIf("DOUBLE")) {
        if (readIf("PRECISION")) {
            original += " PRECISION";
        }
    } else if (readIf("CHARACTER")) {
        if (readIf("VARYING")) {
            original += " VARYING";
        }
    } else if (readIf("TIME")) {
        if (readIf("(")) {
            originalScale = readPositiveInt();
            if (originalScale > ValueTime.MAXIMUM_SCALE) {
                throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(originalScale));
            }
            read(")");
        }
        if (readIf("WITHOUT")) {
            read("TIME");
            read("ZONE");
            original += " WITHOUT TIME ZONE";
        }
    } else if (readIf("TIMESTAMP")) {
        if (readIf("(")) {
            originalScale = readPositiveInt();
            // Allow non-standard TIMESTAMP(..., ...) syntax
            if (readIf(",")) {
                originalScale = readPositiveInt();
            }
            if (originalScale > ValueTimestamp.MAXIMUM_SCALE) {
                throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(originalScale));
            }
            read(")");
        }
        if (readIf("WITH")) {
            read("TIME");
            read("ZONE");
            original += " WITH TIME ZONE";
        } else if (readIf("WITHOUT")) {
            read("TIME");
            read("ZONE");
            original += " WITHOUT TIME ZONE";
        }
    } else {
        regular = true;
    }
    long precision = -1;
    int displaySize = -1;
    String[] enumerators = null;
    int scale = -1;
    String comment = null;
    Column templateColumn = null;
    DataType dataType;
    if (!identifiersToUpper) {
        original = StringUtils.toUpperEnglish(original);
    }
    UserDataType userDataType = database.findUserDataType(original);
    if (userDataType != null) {
        templateColumn = userDataType.getColumn();
        dataType = DataType.getDataType(templateColumn.getType());
        comment = templateColumn.getComment();
        original = templateColumn.getOriginalSQL();
        precision = templateColumn.getPrecision();
        displaySize = templateColumn.getDisplaySize();
        scale = templateColumn.getScale();
        enumerators = templateColumn.getEnumerators();
    } else {
        Mode mode = database.getMode();
        dataType = DataType.getTypeByName(original, mode);
        if (dataType == null || mode.disallowedTypes.contains(original)) {
            throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, currentToken);
        }
    }
    if (database.getIgnoreCase() && dataType.type == Value.STRING && !equalsToken("VARCHAR_CASESENSITIVE", original)) {
        original = "VARCHAR_IGNORECASE";
        dataType = DataType.getTypeByName(original, database.getMode());
    }
    if (regular) {
        read();
    }
    precision = precision == -1 ? dataType.defaultPrecision : precision;
    displaySize = displaySize == -1 ? dataType.defaultDisplaySize : displaySize;
    scale = scale == -1 ? dataType.defaultScale : scale;
    if (dataType.supportsPrecision || dataType.supportsScale) {
        int t = dataType.type;
        if (t == Value.TIME || t == Value.TIMESTAMP || t == Value.TIMESTAMP_TZ) {
            if (originalScale >= 0) {
                scale = originalScale;
                switch(t) {
                    case Value.TIME:
                        if (original.equals("TIME WITHOUT TIME ZONE")) {
                            original = "TIME(" + originalScale + ") WITHOUT TIME ZONE";
                        } else {
                            original = original + '(' + originalScale + ')';
                        }
                        precision = displaySize = ValueTime.getDisplaySize(originalScale);
                        break;
                    case Value.TIMESTAMP:
                        if (original.equals("TIMESTAMP WITHOUT TIME ZONE")) {
                            original = "TIMESTAMP(" + originalScale + ") WITHOUT TIME ZONE";
                        } else {
                            original = original + '(' + originalScale + ')';
                        }
                        precision = displaySize = ValueTimestamp.getDisplaySize(originalScale);
                        break;
                    case Value.TIMESTAMP_TZ:
                        original = "TIMESTAMP(" + originalScale + ") WITH TIME ZONE";
                        precision = displaySize = ValueTimestampTimeZone.getDisplaySize(originalScale);
                        break;
                }
            }
        } else if (readIf("(")) {
            if (!readIf("MAX")) {
                long p = readLong();
                if (readIf("K")) {
                    p *= 1024;
                } else if (readIf("M")) {
                    p *= 1024 * 1024;
                } else if (readIf("G")) {
                    p *= 1024 * 1024 * 1024;
                }
                if (p > Long.MAX_VALUE) {
                    p = Long.MAX_VALUE;
                }
                original += "(" + p;
                // Oracle syntax
                if (!readIf("CHAR")) {
                    readIf("BYTE");
                }
                if (dataType.supportsScale) {
                    if (readIf(",")) {
                        scale = readInt();
                        original += ", " + scale;
                    } else {
                        scale = 0;
                    }
                }
                precision = p;
                displaySize = MathUtils.convertLongToInt(precision);
                original += ")";
            }
            read(")");
        }
    } else if (dataType.type == Value.DOUBLE && original.equals("FLOAT")) {
        if (readIf("(")) {
            int p = readPositiveInt();
            read(")");
            if (p > 53) {
                throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(p));
            }
            if (p <= 24) {
                dataType = DataType.getDataType(Value.FLOAT);
            }
            original = original + '(' + p + ')';
        }
    } else if (dataType.type == Value.ENUM) {
        if (readIf("(")) {
            java.util.List<String> enumeratorList = new ArrayList<>();
            original += '(';
            String enumerator0 = readString();
            enumeratorList.add(enumerator0);
            original += "'" + enumerator0 + "'";
            while (readIfMore(true)) {
                original += ',';
                String enumeratorN = readString();
                original += "'" + enumeratorN + "'";
                enumeratorList.add(enumeratorN);
            }
            original += ')';
            enumerators = enumeratorList.toArray(new String[0]);
        }
        try {
            ValueEnum.check(enumerators);
        } catch (DbException e) {
            throw e.addSQL(original);
        }
    } else if (readIf("(")) {
        // Support for MySQL: INT(11), MEDIUMINT(8) and so on.
        // Just ignore the precision.
        readPositiveInt();
        read(")");
    }
    if (readIf("FOR")) {
        read("BIT");
        read("DATA");
        if (dataType.type == Value.STRING) {
            dataType = DataType.getTypeByName("BINARY", database.getMode());
        }
    }
    // MySQL compatibility
    readIf("UNSIGNED");
    int type = dataType.type;
    if (scale > precision) {
        throw DbException.get(ErrorCode.INVALID_VALUE_SCALE_PRECISION, Integer.toString(scale), Long.toString(precision));
    }
    Column column = new Column(columnName, type, precision, scale, displaySize, enumerators);
    if (templateColumn != null) {
        column.setNullable(templateColumn.isNullable());
        column.setDefaultExpression(session, templateColumn.getDefaultExpression());
        int selectivity = templateColumn.getSelectivity();
        if (selectivity != Constants.SELECTIVITY_DEFAULT) {
            column.setSelectivity(selectivity);
        }
        Expression checkConstraint = templateColumn.getCheckConstraint(session, columnName);
        column.addCheckConstraint(session, checkConstraint);
    }
    column.setComment(comment);
    column.setOriginalSQL(original);
    return column;
}
Also used : CreateUserDataType(org.h2.command.ddl.CreateUserDataType) DropUserDataType(org.h2.command.ddl.DropUserDataType) UserDataType(org.h2.engine.UserDataType) Mode(org.h2.engine.Mode) CompareMode(org.h2.value.CompareMode) ArrayList(java.util.ArrayList) ValueString(org.h2.value.ValueString) AlterTableRenameConstraint(org.h2.command.ddl.AlterTableRenameConstraint) AlterTableAddConstraint(org.h2.command.ddl.AlterTableAddConstraint) AlterTableDropConstraint(org.h2.command.ddl.AlterTableDropConstraint) DbException(org.h2.message.DbException) AlterTableRenameColumn(org.h2.command.ddl.AlterTableRenameColumn) AlterTableAlterColumn(org.h2.command.ddl.AlterTableAlterColumn) Column(org.h2.table.Column) ExpressionColumn(org.h2.expression.ExpressionColumn) IndexColumn(org.h2.table.IndexColumn) Expression(org.h2.expression.Expression) ValueExpression(org.h2.expression.ValueExpression) CreateUserDataType(org.h2.command.ddl.CreateUserDataType) DataType(org.h2.value.DataType) DropUserDataType(org.h2.command.ddl.DropUserDataType) UserDataType(org.h2.engine.UserDataType)

Example 3 with Comment

use of org.h2.engine.Comment in project h2database by h2database.

the class Parser method parseCreateTable.

private CreateTable parseCreateTable(boolean temp, boolean globalTemp, boolean persistIndexes) {
    boolean ifNotExists = readIfNotExists();
    String tableName = readIdentifierWithSchema();
    if (temp && globalTemp && equalsToken("SESSION", schemaName)) {
        // support weird syntax: declare global temporary table session.xy
        // (...) not logged
        schemaName = session.getCurrentSchemaName();
        globalTemp = false;
    }
    Schema schema = getSchema();
    CreateTable command = new CreateTable(session, schema);
    command.setPersistIndexes(persistIndexes);
    command.setTemporary(temp);
    command.setGlobalTemporary(globalTemp);
    command.setIfNotExists(ifNotExists);
    command.setTableName(tableName);
    command.setComment(readCommentIf());
    if (readIf("(")) {
        if (!readIf(")")) {
            do {
                parseTableColumnDefinition(command, schema, tableName);
            } while (readIfMore(false));
        }
    }
    // Allows "COMMENT='comment'" in DDL statements (MySQL syntax)
    if (readIf("COMMENT")) {
        if (readIf("=")) {
            // read the complete string comment, but nothing with it for now
            readString();
        }
    }
    if (readIf("ENGINE")) {
        if (readIf("=")) {
            // map MySQL engine types onto H2 behavior
            String tableEngine = readUniqueIdentifier();
            if ("InnoDb".equalsIgnoreCase(tableEngine)) {
            // ok
            } else if (!"MyISAM".equalsIgnoreCase(tableEngine)) {
                throw DbException.getUnsupportedException(tableEngine);
            }
        } else {
            command.setTableEngine(readUniqueIdentifier());
        }
    }
    if (readIf("WITH")) {
        command.setTableEngineParams(readTableEngineParams());
    }
    // MySQL compatibility
    if (readIf("AUTO_INCREMENT")) {
        read("=");
        if (currentTokenType != VALUE || currentValue.getType() != Value.INT) {
            throw DbException.getSyntaxError(sqlCommand, parseIndex, "integer");
        }
        read();
    }
    readIf("DEFAULT");
    if (readIf("CHARSET")) {
        read("=");
        if (!readIf("UTF8")) {
            read("UTF8MB4");
        }
    }
    if (temp) {
        if (readIf("ON")) {
            read("COMMIT");
            if (readIf("DROP")) {
                command.setOnCommitDrop();
            } else if (readIf("DELETE")) {
                read("ROWS");
                command.setOnCommitTruncate();
            }
        } else if (readIf("NOT")) {
            if (readIf("PERSISTENT")) {
                command.setPersistData(false);
            } else {
                read("LOGGED");
            }
        }
        if (readIf("TRANSACTIONAL")) {
            command.setTransactional(true);
        }
    } else if (!persistIndexes && readIf("NOT")) {
        read("PERSISTENT");
        command.setPersistData(false);
    }
    if (readIf("HIDDEN")) {
        command.setHidden(true);
    }
    if (readIf("AS")) {
        if (readIf("SORTED")) {
            command.setSortedInsertMode(true);
        }
        command.setQuery(parseSelect());
    }
    // for MySQL compatibility
    if (readIf("ROW_FORMAT")) {
        if (readIf("=")) {
            readColumnIdentifier();
        }
    }
    return command;
}
Also used : DropSchema(org.h2.command.ddl.DropSchema) CreateSchema(org.h2.command.ddl.CreateSchema) Schema(org.h2.schema.Schema) CreateTable(org.h2.command.ddl.CreateTable) ValueString(org.h2.value.ValueString)

Example 4 with Comment

use of org.h2.engine.Comment in project h2database by h2database.

the class Parser method parsePrepared.

private Prepared parsePrepared() {
    int start = lastParseIndex;
    Prepared c = null;
    String token = currentToken;
    if (token.length() == 0) {
        c = new NoOperation(session);
    } else {
        char first = token.charAt(0);
        switch(first) {
            case '?':
                // read the ? as a parameter
                readTerm();
                // this is an 'out' parameter - set a dummy value
                parameters.get(0).setValue(ValueNull.INSTANCE);
                read("=");
                read("CALL");
                c = parseCall();
                break;
            case '(':
                c = parseSelect();
                break;
            case 'a':
            case 'A':
                if (readIf("ALTER")) {
                    c = parseAlter();
                } else if (readIf("ANALYZE")) {
                    c = parseAnalyze();
                }
                break;
            case 'b':
            case 'B':
                if (readIf("BACKUP")) {
                    c = parseBackup();
                } else if (readIf("BEGIN")) {
                    c = parseBegin();
                }
                break;
            case 'c':
            case 'C':
                if (readIf("COMMIT")) {
                    c = parseCommit();
                } else if (readIf("CREATE")) {
                    c = parseCreate();
                } else if (readIf("CALL")) {
                    c = parseCall();
                } else if (readIf("CHECKPOINT")) {
                    c = parseCheckpoint();
                } else if (readIf("COMMENT")) {
                    c = parseComment();
                }
                break;
            case 'd':
            case 'D':
                if (readIf("DELETE")) {
                    c = parseDelete();
                } else if (readIf("DROP")) {
                    c = parseDrop();
                } else if (readIf("DECLARE")) {
                    // support for DECLARE GLOBAL TEMPORARY TABLE...
                    c = parseCreate();
                } else if (readIf("DEALLOCATE")) {
                    c = parseDeallocate();
                }
                break;
            case 'e':
            case 'E':
                if (readIf("EXPLAIN")) {
                    c = parseExplain();
                } else if (readIf("EXECUTE")) {
                    c = parseExecute();
                }
                break;
            case 'f':
            case 'F':
                if (isToken("FROM")) {
                    c = parseSelect();
                }
                break;
            case 'g':
            case 'G':
                if (readIf("GRANT")) {
                    c = parseGrantRevoke(CommandInterface.GRANT);
                }
                break;
            case 'h':
            case 'H':
                if (readIf("HELP")) {
                    c = parseHelp();
                }
                break;
            case 'i':
            case 'I':
                if (readIf("INSERT")) {
                    c = parseInsert();
                }
                break;
            case 'm':
            case 'M':
                if (readIf("MERGE")) {
                    c = parseMerge();
                }
                break;
            case 'p':
            case 'P':
                if (readIf("PREPARE")) {
                    c = parsePrepare();
                }
                break;
            case 'r':
            case 'R':
                if (readIf("ROLLBACK")) {
                    c = parseRollback();
                } else if (readIf("REVOKE")) {
                    c = parseGrantRevoke(CommandInterface.REVOKE);
                } else if (readIf("RUNSCRIPT")) {
                    c = parseRunScript();
                } else if (readIf("RELEASE")) {
                    c = parseReleaseSavepoint();
                } else if (readIf("REPLACE")) {
                    c = parseReplace();
                }
                break;
            case 's':
            case 'S':
                if (isToken("SELECT")) {
                    c = parseSelect();
                } else if (readIf("SET")) {
                    c = parseSet();
                } else if (readIf("SAVEPOINT")) {
                    c = parseSavepoint();
                } else if (readIf("SCRIPT")) {
                    c = parseScript();
                } else if (readIf("SHUTDOWN")) {
                    c = parseShutdown();
                } else if (readIf("SHOW")) {
                    c = parseShow();
                }
                break;
            case 't':
            case 'T':
                if (readIf("TRUNCATE")) {
                    c = parseTruncate();
                }
                break;
            case 'u':
            case 'U':
                if (readIf("UPDATE")) {
                    c = parseUpdate();
                } else if (readIf("USE")) {
                    c = parseUse();
                }
                break;
            case 'v':
            case 'V':
                if (readIf("VALUES")) {
                    c = parseValues();
                }
                break;
            case 'w':
            case 'W':
                if (readIf("WITH")) {
                    c = parseWithStatementOrQuery();
                }
                break;
            case ';':
                c = new NoOperation(session);
                break;
            default:
                throw getSyntaxError();
        }
        if (indexedParameterList != null) {
            for (int i = 0, size = indexedParameterList.size(); i < size; i++) {
                if (indexedParameterList.get(i) == null) {
                    indexedParameterList.set(i, new Parameter(i));
                }
            }
            parameters = indexedParameterList;
        }
        if (readIf("{")) {
            do {
                int index = (int) readLong() - 1;
                if (index < 0 || index >= parameters.size()) {
                    throw getSyntaxError();
                }
                Parameter p = parameters.get(index);
                if (p == null) {
                    throw getSyntaxError();
                }
                read(":");
                Expression expr = readExpression();
                expr = expr.optimize(session);
                p.setValue(expr.getValue(session));
            } while (readIf(","));
            read("}");
            for (Parameter p : parameters) {
                p.checkSet();
            }
            parameters.clear();
        }
    }
    if (c == null) {
        throw getSyntaxError();
    }
    setSQL(c, null, start);
    return c;
}
Also used : NoOperation(org.h2.command.dml.NoOperation) Expression(org.h2.expression.Expression) ValueExpression(org.h2.expression.ValueExpression) Parameter(org.h2.expression.Parameter) ConditionInParameter(org.h2.expression.ConditionInParameter) ValueString(org.h2.value.ValueString) AlterTableRenameConstraint(org.h2.command.ddl.AlterTableRenameConstraint) AlterTableAddConstraint(org.h2.command.ddl.AlterTableAddConstraint) AlterTableDropConstraint(org.h2.command.ddl.AlterTableDropConstraint)

Example 5 with Comment

use of org.h2.engine.Comment in project h2database by h2database.

the class AlterTableAddConstraint method tryUpdate.

/**
 * Try to execute the statement.
 *
 * @return the update count
 */
private int tryUpdate() {
    if (!transactional) {
        session.commit(true);
    }
    Database db = session.getDatabase();
    Table table = getSchema().findTableOrView(session, tableName);
    if (table == null) {
        if (ifTableExists) {
            return 0;
        }
        throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, tableName);
    }
    if (getSchema().findConstraint(session, constraintName) != null) {
        if (ifNotExists) {
            return 0;
        }
        throw DbException.get(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName);
    }
    session.getUser().checkRight(table, Right.ALL);
    db.lockMeta(session);
    table.lock(session, true, true);
    Constraint constraint;
    switch(type) {
        case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY:
            {
                IndexColumn.mapColumns(indexColumns, table);
                index = table.findPrimaryKey();
                ArrayList<Constraint> constraints = table.getConstraints();
                for (int i = 0; constraints != null && i < constraints.size(); i++) {
                    Constraint c = constraints.get(i);
                    if (Constraint.Type.PRIMARY_KEY == c.getConstraintType()) {
                        throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
                    }
                }
                if (index != null) {
                    // if there is an index, it must match with the one declared
                    // we don't test ascending / descending
                    IndexColumn[] pkCols = index.getIndexColumns();
                    if (pkCols.length != indexColumns.length) {
                        throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
                    }
                    for (int i = 0; i < pkCols.length; i++) {
                        if (pkCols[i].column != indexColumns[i].column) {
                            throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY);
                        }
                    }
                }
                if (index == null) {
                    IndexType indexType = IndexType.createPrimaryKey(table.isPersistIndexes(), primaryKeyHash);
                    String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY);
                    int id = getObjectId();
                    try {
                        index = table.addIndex(session, indexName, id, indexColumns, indexType, true, null);
                    } finally {
                        getSchema().freeUniqueName(indexName);
                    }
                }
                index.getIndexType().setBelongsToConstraint(true);
                int constraintId = getObjectId();
                String name = generateConstraintName(table);
                ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true);
                pk.setColumns(indexColumns);
                pk.setIndex(index, true);
                constraint = pk;
                break;
            }
        case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE:
            {
                IndexColumn.mapColumns(indexColumns, table);
                boolean isOwner = false;
                if (index != null && canUseUniqueIndex(index, table, indexColumns)) {
                    isOwner = true;
                    index.getIndexType().setBelongsToConstraint(true);
                } else {
                    index = getUniqueIndex(table, indexColumns);
                    if (index == null) {
                        index = createIndex(table, indexColumns, true);
                        isOwner = true;
                    }
                }
                int id = getObjectId();
                String name = generateConstraintName(table);
                ConstraintUnique unique = new ConstraintUnique(getSchema(), id, name, table, false);
                unique.setColumns(indexColumns);
                unique.setIndex(index, isOwner);
                constraint = unique;
                break;
            }
        case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK:
            {
                int id = getObjectId();
                String name = generateConstraintName(table);
                ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table);
                TableFilter filter = new TableFilter(session, table, null, false, null, 0, null);
                checkExpression.mapColumns(filter, 0);
                checkExpression = checkExpression.optimize(session);
                check.setExpression(checkExpression);
                check.setTableFilter(filter);
                constraint = check;
                if (checkExisting) {
                    check.checkExistingData(session);
                }
                break;
            }
        case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL:
            {
                Table refTable = refSchema.resolveTableOrView(session, refTableName);
                if (refTable == null) {
                    throw DbException.get(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, refTableName);
                }
                session.getUser().checkRight(refTable, Right.ALL);
                if (!refTable.canReference()) {
                    throw DbException.getUnsupportedException("Reference " + refTable.getSQL());
                }
                boolean isOwner = false;
                IndexColumn.mapColumns(indexColumns, table);
                if (index != null && canUseIndex(index, table, indexColumns, false)) {
                    isOwner = true;
                    index.getIndexType().setBelongsToConstraint(true);
                } else {
                    index = getIndex(table, indexColumns, false);
                    if (index == null) {
                        index = createIndex(table, indexColumns, false);
                        isOwner = true;
                    }
                }
                if (refIndexColumns == null) {
                    Index refIdx = refTable.getPrimaryKey();
                    refIndexColumns = refIdx.getIndexColumns();
                } else {
                    IndexColumn.mapColumns(refIndexColumns, refTable);
                }
                if (refIndexColumns.length != indexColumns.length) {
                    throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
                }
                boolean isRefOwner = false;
                if (refIndex != null && refIndex.getTable() == refTable && canUseIndex(refIndex, refTable, refIndexColumns, false)) {
                    isRefOwner = true;
                    refIndex.getIndexType().setBelongsToConstraint(true);
                } else {
                    refIndex = null;
                }
                if (refIndex == null) {
                    refIndex = getIndex(refTable, refIndexColumns, false);
                    if (refIndex == null) {
                        refIndex = createIndex(refTable, refIndexColumns, true);
                        isRefOwner = true;
                    }
                }
                int id = getObjectId();
                String name = generateConstraintName(table);
                ConstraintReferential refConstraint = new ConstraintReferential(getSchema(), id, name, table);
                refConstraint.setColumns(indexColumns);
                refConstraint.setIndex(index, isOwner);
                refConstraint.setRefTable(refTable);
                refConstraint.setRefColumns(refIndexColumns);
                refConstraint.setRefIndex(refIndex, isRefOwner);
                if (checkExisting) {
                    refConstraint.checkExistingData(session);
                }
                refTable.addConstraint(refConstraint);
                refConstraint.setDeleteAction(deleteAction);
                refConstraint.setUpdateAction(updateAction);
                constraint = refConstraint;
                break;
            }
        default:
            throw DbException.throwInternalError("type=" + type);
    }
    // parent relationship is already set with addConstraint
    constraint.setComment(comment);
    if (table.isTemporary() && !table.isGlobalTemporary()) {
        session.addLocalTempTableConstraint(constraint);
    } else {
        db.addSchemaObject(session, constraint);
    }
    table.addConstraint(constraint);
    return 0;
}
Also used : Table(org.h2.table.Table) Constraint(org.h2.constraint.Constraint) TableFilter(org.h2.table.TableFilter) Database(org.h2.engine.Database) ArrayList(java.util.ArrayList) ConstraintUnique(org.h2.constraint.ConstraintUnique) Index(org.h2.index.Index) ConstraintCheck(org.h2.constraint.ConstraintCheck) IndexType(org.h2.index.IndexType) ConstraintReferential(org.h2.constraint.ConstraintReferential)

Aggregations

Database (org.h2.engine.Database)9 ValueString (org.h2.value.ValueString)8 Table (org.h2.table.Table)7 AlterTableAddConstraint (org.h2.command.ddl.AlterTableAddConstraint)5 StatementBuilder (org.h2.util.StatementBuilder)5 AlterTableDropConstraint (org.h2.command.ddl.AlterTableDropConstraint)4 AlterTableRenameConstraint (org.h2.command.ddl.AlterTableRenameConstraint)4 Constraint (org.h2.constraint.Constraint)4 ExpressionColumn (org.h2.expression.ExpressionColumn)4 DbException (org.h2.message.DbException)4 Column (org.h2.table.Column)4 IndexColumn (org.h2.table.IndexColumn)4 PreparedStatement (java.sql.PreparedStatement)3 DbObject (org.h2.engine.DbObject)3 Expression (org.h2.expression.Expression)3 ValueExpression (org.h2.expression.ValueExpression)3 Index (org.h2.index.Index)3 Sequence (org.h2.schema.Sequence)3 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2