use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class ResultColumnList method expandToAll.
/**
* Expand this ResultColumnList by adding all columns from the given
* table that are not in this list. The result is sorted by column
* position.
*
* @param td The TableDescriptor for the table in question
* @param tableName The name of the table as given in the query
*
* @return A new ResultColumnList expanded to include all columns in
* the given table.
*
* @exception StandardException Thrown on error
*/
ResultColumnList expandToAll(TableDescriptor td, TableName tableName) throws StandardException {
ResultColumn rc;
ColumnDescriptor cd;
ResultColumnList retval;
ResultColumn[] originalRCS;
int posn;
/* Get a new ResultColumnList */
retval = new ResultColumnList(getContextManager());
/*
** Form a sorted array of the ResultColumns
*/
originalRCS = getSortedByPosition();
posn = 0;
/* Iterate through the ColumnDescriptors for the given table */
ColumnDescriptorList cdl = td.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++) {
cd = cdl.elementAt(index);
if ((posn < originalRCS.length) && (cd.getPosition() == originalRCS[posn].getColumnPosition())) {
rc = originalRCS[posn];
posn++;
} else {
/* Build a ResultColumn/ColumnReference pair for the column */
rc = makeColumnReferenceFromName(tableName, cd.getColumnName());
/* Bind the new ResultColumn */
rc.bindResultColumnByPosition(td, cd.getPosition());
}
/* Add the ResultColumn to the list */
retval.addResultColumn(rc);
}
if (SanityManager.DEBUG)
SanityManager.ASSERT(posn == originalRCS.length, "ResultColumns in original list not added to expanded ResultColumnList");
return retval;
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class ResultColumnList method getStreamStorableColIds.
/**
* Return an array holding the 0 based heap offsets of
* the StreamStorable columns in this ResultColumnList.
* This returns null if this list does not contain any
* StreamStorableColumns. The list this returns does not
* contain duplicates. This should only be used for
* a resultColumnList the refers to a single heap
* such as the target for an Insert, Update or Delete.
* @param heapColCount the number of heap columns
* @exception StandardException Thrown on error
*/
int[] getStreamStorableColIds(int heapColCount) throws StandardException {
// @#$
// System.out.println("getStreamStorableColids");
int ssCount = 0;
// Should be table length.
boolean[] isSS = new boolean[heapColCount];
for (ResultColumn rc : this) {
if (rc.getTypeId().streamStorable()) {
// System.out.println(" streamStorable=true");
ColumnDescriptor cd = rc.getTableColumnDescriptor();
isSS[cd.getPosition() - 1] = true;
}
}
for (int ix = 0; ix < isSS.length; ix++) if (isSS[ix])
ssCount++;
if (ssCount == 0)
return null;
int[] result = new int[ssCount];
int resultOffset = 0;
for (int heapOffset = 0; heapOffset < isSS.length; heapOffset++) {
if (isSS[heapOffset])
result[resultOffset++] = heapOffset;
}
return result;
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class ResultColumnList method getResultColumn.
/**
* Return a result column, if any found, which contains in its
* expression/{VCN,CR} chain a result column with the given
* columnNumber from a FromTable with the given tableNumber.
* <p/>
* Used by the optimizer preprocess phase when it is flattening queries,
* which has to use the pair {table number, column number} to
* uniquely distinguish the column desired in situations where the same
* table may appear multiple times in the queries with separate correlation
* names, and/or column names from different tables may be the same (hence
* looking up by column name will not always work), cf DERBY-4679.
* <p/>
* {@code columnName} is used to assert that we find the right column.
* If we found a match on (tn, cn) but columnName is wrong, return null.
* Once we trust table numbers and column numbers to always be correct,
* cf. DERBY-4695, we could remove this parameter.
*
* @param tableNumber the table number to look for
* @param columnNumber the column number to look for
* @param columnName name of the desired column
*/
public ResultColumn getResultColumn(int tableNumber, int columnNumber, String columnName) {
int size = size();
for (int index = 0; index < size; index++) {
ResultColumn resultColumn = elementAt(index);
ResultColumn rc = resultColumn;
while (rc != null) {
ValueNode exp = rc.getExpression();
if (exp instanceof VirtualColumnNode) {
VirtualColumnNode vcn = (VirtualColumnNode) exp;
ResultSetNode rsn = vcn.getSourceResultSet();
if (rsn instanceof FromTable) {
FromTable ft = (FromTable) rsn;
if (ft.getTableNumber() == tableNumber) {
// We have the right table, now try to match the
// column number. Looking at a join, for a base
// table participant, we will find the correct
// column position in the
// JOIN's ColumnDescriptor. Normally, we could just
// call rc.getColumnPosition, but this doesn't work
// if we have a join with a subquery participant
// (it would give us the virtualColumnId one level
// too high up, since the column descriptor is null
// in that case inside a JOIN's RC.
//
// If FromTable is a FromSubquery we need to look
// at the JOIN RC's source column to match the
// table column number. However, at that level, the
// table number would be that of the underlying
// SELECT (for example), rather than the
// FromSubquery's, so we need to match the table
// number one level above, cf the test cases in
// JoinTest#testDerby_4679 which have subqueries.
ColumnDescriptor cd = rc.getTableColumnDescriptor();
if (SanityManager.DEBUG) {
SanityManager.ASSERT(cd != null || ft instanceof FromSubquery);
}
if ((cd != null && cd.getPosition() == columnNumber) || (vcn.getSourceColumn().getColumnPosition() == columnNumber)) {
// fixed.
if (columnName.equals(vcn.getSourceColumn().getName())) {
resultColumn.setReferenced();
return resultColumn;
} else {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(false, "wrong (tn,cn) for column " + columnName + " found: this pair points to " + vcn.getSourceColumn().getName());
}
// remapColumnReferencesToExpressions
return null;
}
} else {
rc = vcn.getSourceColumn();
}
} else {
rc = vcn.getSourceColumn();
}
} else {
rc = null;
}
} else if (exp instanceof ColumnReference) {
ColumnReference cr = (ColumnReference) exp;
if (cr.getTableNumber() == tableNumber && cr.getColumnNumber() == columnNumber) {
// Found matching (t,c) within this top resultColumn
resultColumn.setReferenced();
return resultColumn;
} else {
rc = null;
}
} else {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(exp instanceof BaseColumnNode, "expected BaseColumnNode, found: " + exp.getClass());
}
rc = null;
}
}
}
return null;
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class ResultColumnList method getColumnPositions.
/**
* Get an array of column positions (1-based) for all the columns
* in this RCL. Assumes that all the columns are in the passed-in
* table
*
* @return the array of strings
*
* @exception throws StandardException on error
*/
int[] getColumnPositions(TableDescriptor td) throws StandardException {
int size = size();
int[] myPositions = new int[size];
String columnName;
ColumnDescriptor cd;
for (int index = 0; index < size; index++) {
ResultColumn resultColumn = elementAt(index);
columnName = resultColumn.getName();
cd = td.getColumnDescriptor(columnName);
if (cd == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, columnName, td.getQualifiedName());
}
myPositions[index] = cd.getPosition();
}
return myPositions;
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class ResultSetNode method generateProjectRestrictForInsert.
/**
* Generate a ProjectRestrictNode to put on top of this node if it's the
* source for an insert, and the RCL needs reordering and/or addition of
* columns in order to match the target RCL.
*
* @param target the target node for the insert
* @param colMap int array representation of correspondence between
* RCLs - colmap[i] = -1 -> missing in current RCL
* colmap[i] = j -> targetRCL(i) <-> thisRCL(j+1)
* @return a ProjectRestrictNode whos RCL matches the target RCL
*/
private ResultSetNode generateProjectRestrictForInsert(InsertNode target, int[] colMap) throws StandardException {
// our newResultCols are put into the bound form straight away.
ResultColumnList newResultCols = new ResultColumnList(getContextManager());
int numTargetColumns = target.resultColumnList.size();
/* Create a massaged version of the source RCL.
* (Much simpler to build new list and then assign to source,
* rather than massage the source list in place.)
*/
for (int index = 0; index < numTargetColumns; index++) {
ResultColumn newResultColumn;
ResultColumn oldResultColumn;
ColumnReference newColumnReference;
if (colMap[index] != -1) {
// getResultColumn uses 1-based positioning, so offset the
// colMap entry appropriately
oldResultColumn = resultColumns.getResultColumn(colMap[index] + 1);
newColumnReference = new ColumnReference(oldResultColumn.getName(), null, getContextManager());
DataTypeDescriptor dtd = oldResultColumn.getType();
if (dtd == null) {
ColumnDescriptor cd = target.targetTableDescriptor.getColumnDescriptor(index + 1);
dtd = cd.getType();
}
/* The ColumnReference points to the source of the value */
newColumnReference.setSource(oldResultColumn);
// colMap entry is 0-based, columnId is 1-based.
newColumnReference.setType(dtd);
// Source of an insert, so nesting levels must be 0
newColumnReference.setNestingLevel(0);
newColumnReference.setSourceLevel(0);
// because the insert already copied the target table's
// column descriptors into the result, we grab it from there.
// alternatively, we could do what the else clause does,
// and look it up in the DD again.
newResultColumn = new ResultColumn(dtd, newColumnReference, getContextManager());
} else {
newResultColumn = genNewRCForInsert(target.targetTableDescriptor, target.targetVTI, index + 1, target.getDataDictionary());
}
newResultCols.addResultColumn(newResultColumn);
}
/* The generated ProjectRestrictNode now has the ResultColumnList
* in the order that the InsertNode expects.
* NOTE: This code here is an exception to several "rules":
* o This is the only ProjectRestrictNode that is currently
* generated outside of preprocess().
* o The UnionNode is the only node which is not at the
* top of the query tree which has ColumnReferences under
* its ResultColumnList prior to expression push down.
*/
return new ProjectRestrictNode(this, newResultCols, null, null, null, null, null, getContextManager());
}
Aggregations