Search in sources :

Example 56 with ConglomerateDescriptor

use of org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor in project derby by apache.

the class FromBaseTable method supersetOfUniqueIndex.

/**
 * Determine whether or not the columns marked as true in
 * the passed in join table matrix are a superset of any single column unique index
 * on this table.
 * This is useful for distinct elimination
 * based on a uniqueness condition.
 *
 * @param tableColMap	The columns to consider
 *
 * @return Whether or not the columns marked as true for one at least
 * 	one table are a superset
 */
protected boolean supersetOfUniqueIndex(JBitSet[] tableColMap) throws StandardException {
    ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors();
    /* Cycle through the ConglomerateDescriptors */
    for (int index = 0; index < cds.length; index++) {
        ConglomerateDescriptor cd = cds[index];
        if (!cd.isIndex()) {
            continue;
        }
        IndexDescriptor id = cd.getIndexDescriptor();
        if (!id.isUnique()) {
            continue;
        }
        int[] keyColumns = id.baseColumnPositions();
        int numBits = tableColMap[0].size();
        JBitSet keyMap = new JBitSet(numBits);
        JBitSet resMap = new JBitSet(numBits);
        int inner = 0;
        for (; inner < keyColumns.length; inner++) {
            keyMap.set(keyColumns[inner]);
        }
        int table = 0;
        for (; table < tableColMap.length; table++) {
            resMap.setTo(tableColMap[table]);
            resMap.and(keyMap);
            if (keyMap.equals(resMap)) {
                tableColMap[table].set(0);
                return true;
            }
        }
    }
    return false;
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet) IndexDescriptor(org.apache.derby.catalog.IndexDescriptor) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)

Example 57 with ConglomerateDescriptor

use of org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor in project derby by apache.

the class LockTableNode method bindStatement.

/**
 * Bind this LockTableNode.  This means looking up the table,
 * verifying it exists and getting the heap conglomerate number.
 *
 * @exception StandardException		Thrown on error
 */
@Override
public void bindStatement() throws StandardException {
    CompilerContext cc = getCompilerContext();
    ConglomerateDescriptor cd;
    SchemaDescriptor sd;
    String schemaName = tableName.getSchemaName();
    sd = getSchemaDescriptor(schemaName);
    // Users are not allowed to lock system tables
    if (sd.isSystemSchema()) {
        throw StandardException.newException(SQLState.LANG_NO_USER_DDL_IN_SYSTEM_SCHEMA, statementToString(), schemaName);
    }
    lockTableDescriptor = getTableDescriptor(tableName.getTableName(), sd);
    if (lockTableDescriptor == null) {
        // Check if the reference is for a synonym.
        TableName synonymTab = resolveTableToSynonym(tableName);
        if (synonymTab == null)
            throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName);
        tableName = synonymTab;
        sd = getSchemaDescriptor(tableName.getSchemaName());
        lockTableDescriptor = getTableDescriptor(synonymTab.getTableName(), sd);
        if (lockTableDescriptor == null)
            throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, tableName);
    }
    // throw an exception if user is attempting to lock a temporary table
    if (lockTableDescriptor.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
        throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
    }
    conglomerateNumber = lockTableDescriptor.getHeapConglomerateId();
    /* Get the base conglomerate descriptor */
    cd = lockTableDescriptor.getConglomerateDescriptor(conglomerateNumber);
    /* Statement is dependent on the TableDescriptor and ConglomerateDescriptor */
    cc.createDependency(lockTableDescriptor);
    cc.createDependency(cd);
    if (isPrivilegeCollectionRequired()) {
        // need SELECT privilege to perform lock table statement.
        cc.pushCurrentPrivType(Authorizer.SELECT_PRIV);
        cc.addRequiredTablePriv(lockTableDescriptor);
        cc.popCurrentPrivType();
    }
}
Also used : SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)

Example 58 with ConglomerateDescriptor

use of org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor in project derby by apache.

the class OptimizerImpl method ruleBasedCostOptimizable.

/**
 * This method decides whether the given conglomerate descriptor is
 * cheapest based on rules, rather than based on cost estimates.
 * The rules are:
 *
 *		Covering matching indexes are preferred above all
 *		Non-covering matching indexes are next in order of preference
 *		Covering non-matching indexes are next in order of preference
 *		Heap scans are next in order of preference
 *		Non-covering, non-matching indexes are last in order of
 *		preference.
 *
 * In the current language architecture, there will always be a
 * heap, so a non-covering, non-matching index scan will never be
 * chosen.  However, the optimizer may see a non-covering, non-matching
 * index first, in which case it will choose it temporarily as the
 * best conglomerate seen so far.
 *
 * NOTE: This method sets the cost in the optimizable, even though it
 * doesn't use the cost to determine which access path to choose.  There
 * are two reasons for this: the cost might be needed to determine join
 * order, and the cost information is copied to the query plan.
 */
private void ruleBasedCostOptimizable(Optimizable optimizable, TableDescriptor td, ConglomerateDescriptor cd, OptimizablePredicateList predList, CostEstimate outerCost) throws StandardException {
    /* CHOOSE BEST CONGLOMERATE HERE */
    AccessPath bestAp = optimizable.getBestAccessPath();
    /*
		** If there is more than one conglomerate descriptor
		** choose any index that is potentially useful.
		*/
    if (predList != null && predList.useful(optimizable, cd)) {
        /*
			** Do not let a non-covering matching index scan supplant a
			** covering matching index scan.
			*/
        boolean newCoveringIndex = optimizable.isCoveringIndex(cd);
        if ((!bestAp.getCoveringIndexScan()) || bestAp.getNonMatchingIndexScan() || newCoveringIndex) {
            bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
            bestAp.setConglomerateDescriptor(cd);
            bestAp.setNonMatchingIndexScan(false);
            bestAp.setCoveringIndexScan(newCoveringIndex);
            bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
            optimizable.rememberJoinStrategyAsBest(bestAp);
        }
        return;
    }
    /* Remember the "last" covering index.
		 * NOTE - Since we don't have costing, we just go for the
		 * last one since that's as good as any
		 */
    if (optimizable.isCoveringIndex(cd)) {
        bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
        bestAp.setConglomerateDescriptor(cd);
        bestAp.setNonMatchingIndexScan(true);
        bestAp.setCoveringIndexScan(true);
        bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
        optimizable.rememberJoinStrategyAsBest(bestAp);
        return;
    }
    /*
		** If this is the heap, and the best conglomerate so far is a
		** non-covering, non-matching index scan, pick the heap.
		*/
    if ((!bestAp.getCoveringIndexScan()) && bestAp.getNonMatchingIndexScan() && (!cd.isIndex())) {
        bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
        bestAp.setConglomerateDescriptor(cd);
        bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
        optimizable.rememberJoinStrategyAsBest(bestAp);
        /*
			** No need to set non-matching index scan and covering
			** index scan, as these are already correct.
			*/
        return;
    }
    /*
		** If all else fails, and no conglomerate has been picked yet,
		** pick this one.
		*/
    ConglomerateDescriptor bestConglomerateDescriptor = bestAp.getConglomerateDescriptor();
    if (bestConglomerateDescriptor == null) {
        bestAp.setCostEstimate(estimateTotalCost(predList, cd, outerCost, optimizable));
        bestAp.setConglomerateDescriptor(cd);
        /*
			** We have determined above that this index is neither covering
			** nor matching.
			*/
        bestAp.setCoveringIndexScan(false);
        bestAp.setNonMatchingIndexScan(cd.isIndex());
        bestAp.setLockMode(optimizable.getCurrentAccessPath().getLockMode());
        optimizable.rememberJoinStrategyAsBest(bestAp);
    }
}
Also used : AccessPath(org.apache.derby.iapi.sql.compile.AccessPath) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)

Example 59 with ConglomerateDescriptor

use of org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor in project derby by apache.

the class HashJoinStrategy method feasible.

/**
 * @see JoinStrategy#feasible
 *
 * @exception StandardException		Thrown on error
 */
public boolean feasible(Optimizable innerTable, OptimizablePredicateList predList, Optimizer optimizer) throws StandardException {
    ConglomerateDescriptor cd = null;
    /* If the innerTable is a VTI, then we
		 * must check to see if there are any
		 * join columns in the VTI's parameters.
		 * If so, then hash join is not feasible.
		 */
    if (!innerTable.isMaterializable()) {
        if (innerTable.optimizerTracingIsOn()) {
            innerTable.getOptimizerTracer().traceSkipUnmaterializableHashJoin();
        }
        return false;
    }
    /* Don't consider hash join on the target table of an update/delete.
		 * RESOLVE - this is a temporary restriction.  Problem is that we
		 * do not put RIDs into the row in the hash table when scanning
		 * the heap and we need them for a target table.
		 */
    if (innerTable.isTargetTable()) {
        return false;
    }
    /* If the predicate given by the user _directly_ references
		 * any of the base tables _beneath_ this node, then we
		 * cannot safely use the predicate for a hash because the
		 * predicate correlates two nodes at different nesting levels. 
		 * If we did a hash join in this case, materialization of
		 * innerTable could lead to incorrect results--and in particular,
		 * results that are missing rows.  We can check for this by
		 * looking at the predicates' reference maps, which are set based
		 * on the initial query (as part of pre-processing).  Note that
		 * by the time we get here, it's possible that a predicate's
		 * reference map holds table numbers that do not agree with the
		 * table numbers of the column references used by the predicate.
		 * That's okay--this occurs as a result of "remapping" predicates
		 * that have been pushed down the query tree.  And in fact
		 * it's a good thing because, by looking at the column reference's
		 * own table numbers instead of the predicate's referenced map,
		 * we are more readily able to find equijoin predicates that
		 * we otherwise would not have found.
		 *
		 * Note: do not perform this check if innerTable is a FromBaseTable
		 * because a base table does not have a "subtree" to speak of.
		 */
    if ((predList != null) && (predList.size() > 0) && !(innerTable instanceof FromBaseTable)) {
        FromTable ft = (FromTable) innerTable;
        // First get a list of all of the base tables in the subtree
        // below innerTable.
        JBitSet tNums = new JBitSet(ft.getReferencedTableMap().size());
        BaseTableNumbersVisitor btnVis = new BaseTableNumbersVisitor(tNums);
        ft.accept(btnVis);
        // Now get a list of all table numbers referenced by the
        // join predicates that we'll be searching.
        JBitSet pNums = new JBitSet(tNums.size());
        for (int i = 0; i < predList.size(); i++) {
            Predicate pred = (Predicate) predList.getOptPredicate(i);
            if (pred.isJoinPredicate())
                pNums.or(pred.getReferencedSet());
        }
        // If tNums and pNums have anything in common, then at
        // least one predicate in the list refers directly to
        // a base table beneath this node (as opposed to referring
        // just to this node), which means it's not safe to do a
        // hash join.
        tNums.and(pNums);
        if (tNums.getFirstSetBit() != -1)
            return false;
    }
    if (innerTable.isBaseTable()) {
        /* Must have an equijoin on a column in the conglomerate */
        cd = innerTable.getCurrentAccessPath().getConglomerateDescriptor();
    }
    /* Look for equijoins in the predicate list */
    int[] hashKeyColumns = findHashKeyColumns(innerTable, cd, predList);
    if (SanityManager.DEBUG) {
        if (innerTable.optimizerTracingIsOn()) {
            if (hashKeyColumns == null) {
                innerTable.getOptimizerTracer().traceSkipHashJoinNoHashKeys();
            } else {
                innerTable.getOptimizerTracer().traceHashKeyColumns(ArrayUtil.copy(hashKeyColumns));
            }
        }
    }
    if (hashKeyColumns == null) {
        return false;
    }
    return true;
}
Also used : JBitSet(org.apache.derby.iapi.util.JBitSet) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Example 60 with ConglomerateDescriptor

use of org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor in project derby by apache.

the class InsertNode method getAffectedIndexes.

/**
 * Get the list of indexes on the table being inserted into.  This
 * is used by INSERT.  This is an optimized version of what
 * UPDATE and DELETE use.
 *
 * @param td	TableDescriptor for the table being inserted into
 *				or deleted from
 *
 * @exception StandardException		Thrown on error
 */
private void getAffectedIndexes(TableDescriptor td) throws StandardException {
    IndexLister indexLister = td.getIndexLister();
    indicesToMaintain = indexLister.getDistinctIndexRowGenerators();
    indexConglomerateNumbers = indexLister.getDistinctIndexConglomerateNumbers();
    indexNames = indexLister.getDistinctIndexNames();
    /* Add dependencies on all indexes in the list */
    ConglomerateDescriptor[] cds = td.getConglomerateDescriptors();
    CompilerContext cc = getCompilerContext();
    for (int index = 0; index < cds.length; index++) {
        cc.createDependency(cds[index]);
    }
}
Also used : CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) IndexLister(org.apache.derby.iapi.sql.dictionary.IndexLister) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)

Aggregations

ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)66 TableDescriptor (org.apache.derby.iapi.sql.dictionary.TableDescriptor)19 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)17 TransactionController (org.apache.derby.iapi.store.access.TransactionController)13 Properties (java.util.Properties)12 UUID (org.apache.derby.catalog.UUID)12 ConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor)12 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)12 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)11 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)11 IndexRowGenerator (org.apache.derby.iapi.sql.dictionary.IndexRowGenerator)10 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)10 ColumnDescriptor (org.apache.derby.iapi.sql.dictionary.ColumnDescriptor)8 ConglomerateController (org.apache.derby.iapi.store.access.ConglomerateController)8 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)8 DependencyManager (org.apache.derby.iapi.sql.depend.DependencyManager)7 ColumnDescriptorList (org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList)7 RowLocation (org.apache.derby.iapi.types.RowLocation)6 ArrayList (java.util.ArrayList)5 IndexDescriptor (org.apache.derby.catalog.IndexDescriptor)5