Search in sources :

Example 1 with IndexColumn

use of com.wplatform.ddal.dbobject.table.IndexColumn in project jdbc-shards by wplatform.

the class IndexMate method getCostRangeIndex.

/**
 * Calculate the cost for the given mask as if this index was a typical
 * b-tree range index. This is the estimated cost required to search one
 * row, and then iterate over the given number of rows.
 *
 * @param masks     the search mask
 * @param rowCount  the number of rows in the index
 * @param filter    the table filter
 * @param sortOrder the sort order
 * @return the estimated cost
 */
protected long getCostRangeIndex(int[] masks, long rowCount, TableFilter filter, SortOrder sortOrder) {
    rowCount += Constants.COST_ROW_OFFSET;
    long cost = rowCount;
    long rows = rowCount;
    int totalSelectivity = 0;
    if (masks == null) {
        return cost;
    }
    for (int i = 0, len = columns.length; i < len; i++) {
        Column column = columns[i];
        int index = column.getColumnId();
        int mask = masks[index];
        if ((mask & IndexCondition.EQUALITY) == IndexCondition.EQUALITY) {
            if (i == columns.length - 1 && getIndexType().isUnique()) {
                cost = 3;
                break;
            }
            totalSelectivity = 100 - ((100 - totalSelectivity) * (100 - column.getSelectivity()) / 100);
            long distinctRows = rowCount * totalSelectivity / 100;
            if (distinctRows <= 0) {
                distinctRows = 1;
            }
            rows = Math.max(rowCount / distinctRows, 1);
            cost = 2 + rows;
        } else if ((mask & IndexCondition.RANGE) == IndexCondition.RANGE) {
            cost = 2 + rows / 4;
            break;
        } else if ((mask & IndexCondition.START) == IndexCondition.START) {
            cost = 2 + rows / 3;
            break;
        } else if ((mask & IndexCondition.END) == IndexCondition.END) {
            cost = rows / 3;
            break;
        } else {
            break;
        }
    }
    // it will be cheaper than another index, so adjust the cost accordingly
    if (sortOrder != null) {
        boolean sortOrderMatches = true;
        int coveringCount = 0;
        int[] sortTypes = sortOrder.getSortTypes();
        for (int i = 0, len = sortTypes.length; i < len; i++) {
            if (i >= indexColumns.length) {
                // more of the order by columns
                break;
            }
            Column col = sortOrder.getColumn(i, filter);
            if (col == null) {
                sortOrderMatches = false;
                break;
            }
            IndexColumn indexCol = indexColumns[i];
            if (col != indexCol.column) {
                sortOrderMatches = false;
                break;
            }
            int sortType = sortTypes[i];
            if (sortType != indexCol.sortType) {
                sortOrderMatches = false;
                break;
            }
            coveringCount++;
        }
        if (sortOrderMatches) {
            // "coveringCount" makes sure that when we have two
            // or more covering indexes, we choose the one
            // that covers more
            cost -= coveringCount;
        }
    }
    return cost;
}
Also used : IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn) Column(com.wplatform.ddal.dbobject.table.Column) IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn)

Example 2 with IndexColumn

use of com.wplatform.ddal.dbobject.table.IndexColumn in project jdbc-shards by wplatform.

the class CreateTableExecutor method doTranslate.

@Override
protected String doTranslate(TableNode tableNode) {
    StatementBuilder buff = new StatementBuilder("CREATE ");
    if (prepared.isTemporary()) {
        buff.append("TEMPORARY ");
    }
    buff.append("TABLE ");
    if (prepared.isIfNotExists()) {
        buff.append("IF NOT EXISTS ");
    }
    buff.append(identifier(tableNode.getCompositeObjectName()));
    if (prepared.getComment() != null) {
    // buff.append(" COMMENT ").append(StringUtils.quoteStringSQL(prepared.getComment()));
    }
    buff.append("(");
    for (Column column : prepared.getColumns()) {
        buff.appendExceptFirst(", ");
        buff.append(column.getCreateSQL());
    }
    for (DefineCommand command : prepared.getConstraintCommands()) {
        buff.appendExceptFirst(", ");
        int type = command.getType();
        switch(type) {
            case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY:
                {
                    AlterTableAddConstraint stmt = (AlterTableAddConstraint) command;
                    buff.append(" CONSTRAINT PRIMARY KEY");
                    if (stmt.isPrimaryKeyHash()) {
                        buff.append(" USING HASH");
                    }
                    buff.resetCount();
                    buff.append("(");
                    for (IndexColumn c : stmt.getIndexColumns()) {
                        buff.appendExceptFirst(", ");
                        buff.append(identifier(c.columnName));
                    }
                    buff.append(")");
                    break;
                }
            case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE:
                {
                    AlterTableAddConstraint stmt = (AlterTableAddConstraint) command;
                    buff.append(" CONSTRAINT UNIQUE KEY");
                    buff.resetCount();
                    buff.append("(");
                    for (IndexColumn c : stmt.getIndexColumns()) {
                        buff.appendExceptFirst(", ");
                        buff.append(identifier(c.columnName));
                    }
                    buff.append(")");
                    break;
                }
            case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK:
                {
                    AlterTableAddConstraint stmt = (AlterTableAddConstraint) command;
                    String enclose = StringUtils.enclose(stmt.getCheckExpression().getSQL());
                    buff.append(" CHECK").append(enclose);
                    break;
                }
            case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL:
                {
                    AlterTableAddConstraint stmt = (AlterTableAddConstraint) command;
                    String refTableName = stmt.getRefTableName();
                    TableMate table = getTableMate(stmt.getTableName());
                    TableMate refTable = getTableMate(refTableName);
                    if (refTable != null) {
                        TableNode[] partitionNode = refTable.getPartitionNode();
                        if (partitionNode.length > 1) {
                            TableNode[] tableNodes = table.getPartitionNode();
                            TableNode[] refTableNodes = partitionNode;
                            Map<TableNode, TableNode> symmetryRelation = getSymmetryRelation(tableNodes, refTableNodes);
                            TableNode relation = symmetryRelation.get(tableNode);
                            if (relation == null) {
                                throw DbException.get(ErrorCode.CHECK_CONSTRAINT_INVALID, "The original table and reference table should be symmetrical.");
                            }
                            refTableName = relation.getCompositeObjectName();
                        } else if (partitionNode.length == 1) {
                            refTableName = partitionNode[0].getCompositeObjectName();
                        }
                    }
                    IndexColumn[] cols = stmt.getIndexColumns();
                    IndexColumn[] refCols = stmt.getRefIndexColumns();
                    buff.resetCount();
                    buff.append(" CONSTRAINT FOREIGN KEY(");
                    for (IndexColumn c : cols) {
                        buff.appendExceptFirst(", ");
                        buff.append(c.columnName);
                    }
                    buff.append(")");
                    buff.append(" REFERENCES ");
                    buff.append(identifier(refTableName)).append("(");
                    buff.resetCount();
                    for (IndexColumn r : refCols) {
                        buff.appendExceptFirst(", ");
                        buff.append(r.columnName);
                    }
                    buff.append(")");
                    break;
                }
            case CommandInterface.CREATE_INDEX:
                {
                    CreateIndex stmt = (CreateIndex) command;
                    if (stmt.isSpatial()) {
                        buff.append(" SPATIAL INDEX");
                    } else {
                        buff.append(" INDEX");
                        if (stmt.isHash()) {
                            buff.append(" USING HASH");
                        }
                    }
                    buff.resetCount();
                    buff.append("(");
                    for (IndexColumn c : stmt.getIndexColumns()) {
                        buff.appendExceptFirst(", ");
                        buff.append(identifier(c.columnName));
                    }
                    buff.append(")");
                    break;
                }
            default:
                throw DbException.throwInternalError("type=" + type);
        }
    }
    buff.append(")");
    if (prepared.getTableEngine() != null) {
        buff.append(" ENGINE = ");
        buff.append(prepared.getTableEngine());
    }
    ArrayList<String> tableEngineParams = prepared.getTableEngineParams();
    if (tableEngineParams != null && tableEngineParams.isEmpty()) {
        buff.append("WITH ");
        buff.resetCount();
        for (String parameter : tableEngineParams) {
            buff.appendExceptFirst(", ");
            buff.append(StringUtils.quoteIdentifier(parameter));
        }
    }
    if (prepared.getCharset() != null) {
        buff.append(" DEFAULT CHARACTER SET = ");
        buff.append(prepared.getCharset());
    }
    return buff.toString();
}
Also used : AlterTableAddConstraint(com.wplatform.ddal.command.ddl.AlterTableAddConstraint) CreateIndex(com.wplatform.ddal.command.ddl.CreateIndex) IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn) Column(com.wplatform.ddal.dbobject.table.Column) StatementBuilder(com.wplatform.ddal.util.StatementBuilder) TableNode(com.wplatform.ddal.dispatch.rule.TableNode) TableMate(com.wplatform.ddal.dbobject.table.TableMate) Map(java.util.Map) AlterTableAddConstraint(com.wplatform.ddal.command.ddl.AlterTableAddConstraint) DefineCommand(com.wplatform.ddal.command.ddl.DefineCommand) IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn)

Example 3 with IndexColumn

use of com.wplatform.ddal.dbobject.table.IndexColumn in project jdbc-shards by wplatform.

the class AlterTableAddConstraintExecutor method doBuildReferences.

private String doBuildReferences(String forTable, String forRefTable) {
    StatementBuilder buff = new StatementBuilder("ALTER TABLE ");
    buff.append(identifier(forTable)).append(" ADD CONSTRAINT ");
    String constraintName = prepared.getConstraintName();
    if (!StringUtils.isNullOrEmpty(constraintName)) {
        buff.append(constraintName);
    }
    IndexColumn[] cols = prepared.getIndexColumns();
    IndexColumn[] refCols = prepared.getRefIndexColumns();
    buff.append(" FOREIGN KEY(");
    for (IndexColumn c : cols) {
        buff.appendExceptFirst(", ");
        buff.append(c.getSQL());
    }
    buff.append(')');
    buff.append(" REFERENCES ");
    buff.append(forRefTable).append('(');
    buff.resetCount();
    for (IndexColumn r : refCols) {
        buff.appendExceptFirst(", ");
        buff.append(r.getSQL());
    }
    buff.append(')');
    if (prepared.getDeleteAction() != AlterTableAddConstraint.RESTRICT) {
        buff.append(" ON DELETE ");
        appendAction(buff, prepared.getDeleteAction());
    }
    if (prepared.getUpdateAction() != AlterTableAddConstraint.RESTRICT) {
        buff.append(" ON UPDATE ");
        appendAction(buff, prepared.getDeleteAction());
    }
    return buff.toString();
}
Also used : StatementBuilder(com.wplatform.ddal.util.StatementBuilder) IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn)

Example 4 with IndexColumn

use of com.wplatform.ddal.dbobject.table.IndexColumn in project jdbc-shards by wplatform.

the class AlterTableAddConstraintExecutor method doBuildUnique.

private String doBuildUnique(String forTable, String uniqueType) {
    StatementBuilder buff = new StatementBuilder("ALTER TABLE ");
    buff.append(identifier(forTable)).append(" ADD CONSTRAINT ");
    String constraintName = prepared.getConstraintName();
    // MySQL constraintName is optional
    if (!StringUtils.isNullOrEmpty(constraintName)) {
        buff.append(constraintName);
    }
    buff.append(' ').append(uniqueType);
    if (prepared.isPrimaryKeyHash()) {
        buff.append(" USING ").append("HASH");
    }
    buff.append('(');
    for (IndexColumn c : prepared.getIndexColumns()) {
        buff.appendExceptFirst(", ");
        buff.append(identifier(c.column.getName()));
    }
    buff.append(')');
    return buff.toString();
}
Also used : StatementBuilder(com.wplatform.ddal.util.StatementBuilder) IndexColumn(com.wplatform.ddal.dbobject.table.IndexColumn)

Aggregations

IndexColumn (com.wplatform.ddal.dbobject.table.IndexColumn)4 StatementBuilder (com.wplatform.ddal.util.StatementBuilder)3 Column (com.wplatform.ddal.dbobject.table.Column)2 AlterTableAddConstraint (com.wplatform.ddal.command.ddl.AlterTableAddConstraint)1 CreateIndex (com.wplatform.ddal.command.ddl.CreateIndex)1 DefineCommand (com.wplatform.ddal.command.ddl.DefineCommand)1 TableMate (com.wplatform.ddal.dbobject.table.TableMate)1 TableNode (com.wplatform.ddal.dispatch.rule.TableNode)1 Map (java.util.Map)1