use of org.apache.derby.catalog.types.DefaultInfoImpl in project derby by apache.
the class ResultSetNode method genNewRCForInsert.
/**
* Generate the RC/expression for an unspecified column in an insert.
* Use the default if one exists.
*
* @param targetTD Target TableDescriptor if the target is not a VTI, null if a VTI.
* @param targetVTI Target description if it is a VTI, null if not a VTI
* @param columnNumber The column number
* @param dataDictionary The DataDictionary
* @return The RC/expression for the unspecified column.
*
* @exception StandardException Thrown on error
*/
private ResultColumn genNewRCForInsert(TableDescriptor targetTD, FromVTI targetVTI, int columnNumber, DataDictionary dataDictionary) throws StandardException {
ResultColumn newResultColumn;
if (targetVTI != null) {
newResultColumn = targetVTI.getResultColumns().getResultColumn(columnNumber);
newResultColumn = newResultColumn.cloneMe();
newResultColumn.setExpressionToNullNode();
} else {
// column position is 1-based, index is 0-based.
ColumnDescriptor colDesc = targetTD.getColumnDescriptor(columnNumber);
DataTypeDescriptor colType = colDesc.getType();
// Check for defaults
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) colDesc.getDefaultInfo();
// if it have defaultInfo and not be autoincrement.
if (defaultInfo != null && !colDesc.isAutoincrement()) {
// RESOLVEPARAMETER - skip the tree if we have the value
/*
if (defaultInfo.getDefaultValue() != null)
{
}
else
*/
{
if (colDesc.hasGenerationClause()) {
// later on we will revisit the generated columns and bind
// their generation clauses
newResultColumn = createGeneratedColumn(targetTD, colDesc);
} else {
// Generate the tree for the default
String defaultText = defaultInfo.getDefaultText();
ValueNode defaultTree = parseDefault(defaultText);
defaultTree = defaultTree.bindExpression(getFromList(), (SubqueryList) null, (List<AggregateNode>) null);
newResultColumn = new ResultColumn(defaultTree.getTypeServices(), defaultTree, getContextManager());
}
DefaultDescriptor defaultDescriptor = colDesc.getDefaultDescriptor(dataDictionary);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(defaultDescriptor != null, "defaultDescriptor expected to be non-null");
}
getCompilerContext().createDependency(defaultDescriptor);
}
} else if (colDesc.isAutoincrement()) {
newResultColumn = new ResultColumn(colDesc, null, getContextManager());
newResultColumn.setAutoincrementGenerated();
} else {
newResultColumn = new ResultColumn(colType, getNullNode(colType), getContextManager());
}
}
// Mark the new RC as generated for an unmatched column in an insert
newResultColumn.markGeneratedForUnmatchedColumnInInsert();
return newResultColumn;
}
use of org.apache.derby.catalog.types.DefaultInfoImpl in project derby by apache.
the class ColumnDefinitionNode method validateDefault.
/**
* Check the validity of the default for this node.
*
* @param td The TableDescriptor.
*
* @exception StandardException Thrown on error
*/
void validateDefault(DataDictionary dd, TableDescriptor td) throws StandardException {
if (defaultNode == null)
return;
// Examin whether default value is autoincrement.
if (isAutoincrement) {
defaultInfo = createDefaultInfoOfAutoInc();
return;
}
// Judged as default value is constant value.
CompilerContext cc = getCompilerContext();
ValueNode defaultTree = defaultNode.getDefaultTree();
/* bind the default.
* Verify that it does not contain any ColumnReferences or subqueries
* and that it is type compatable with the column.
*/
final int previousReliability = cc.getReliability();
try {
/*
Defaults cannot have dependencies as they
should just be constants. Code used to exist
to handle dependencies in defaults, now this
is under sanity to ensure no dependencies exist.
*/
ProviderList apl = null;
ProviderList prevAPL = null;
if (SanityManager.DEBUG) {
apl = new ProviderList();
prevAPL = cc.getCurrentAuxiliaryProviderList();
cc.setCurrentAuxiliaryProviderList(apl);
}
// Tell the compiler context to only allow deterministic nodes
cc.setReliability(CompilerContext.DEFAULT_RESTRICTION);
defaultTree = defaultTree.bindExpression(new FromList(getOptimizerFactory().doJoinOrderOptimization(), getContextManager()), (SubqueryList) null, (List<AggregateNode>) null);
TypeId columnTypeId = getType().getTypeId();
TypeId defaultTypeId = defaultTree.getTypeId();
// before checking for 'not storable' errors (42821).
if (!defaultTypeIsValid(columnTypeId, getType(), defaultTypeId, defaultTree, defaultNode.getDefaultText())) {
throw StandardException.newException(SQLState.LANG_DB2_INVALID_DEFAULT_VALUE, this.name);
}
// Now check 'not storable' errors.
if (!getTypeCompiler(columnTypeId).storable(defaultTypeId, getClassFactory())) {
throw StandardException.newException(SQLState.LANG_NOT_STORABLE, columnTypeId.getSQLTypeName(), defaultTypeId.getSQLTypeName());
}
// Save off the default text
// RESOLVEDEFAULT - Convert to constant if possible
defaultInfo = new DefaultInfoImpl(false, defaultNode.getDefaultText(), defaultValue);
if (SanityManager.DEBUG) {
/* Save the APL off in the constraint node */
if (apl.size() > 0) {
SanityManager.THROWASSERT("DEFAULT clause has unexpected dependencies");
}
// Restore the previous AuxiliaryProviderList
cc.setCurrentAuxiliaryProviderList(prevAPL);
}
} finally {
cc.setReliability(previousReliability);
}
}
use of org.apache.derby.catalog.types.DefaultInfoImpl in project derby by apache.
the class TableElementList method bindAndValidateGenerationClauses.
/**
* Bind and validate all of the generation clauses in this list against
* the specified FromList.
*
* @param sd Schema where the table lives.
* @param fromList The FromList in question.
* @param generatedColumns Bitmap of generated columns in the table. Vacuous for CREATE TABLE, but may be non-trivial for ALTER TABLE. This routine may set bits for new generated columns.
* @param baseTable Table descriptor if this is an ALTER TABLE statement.
*
* @exception StandardException Thrown on error
*/
void bindAndValidateGenerationClauses(SchemaDescriptor sd, FromList fromList, FormatableBitSet generatedColumns, TableDescriptor baseTable) throws StandardException {
FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
ResultColumnList tableColumns = table.getResultColumns();
int columnCount = table.getResultColumns().size();
// complain if a generation clause references another generated column
findIllegalGenerationReferences(fromList, baseTable);
generatedColumns.grow(columnCount + 1);
CompilerContext cc = getCompilerContext();
ArrayList<AggregateNode> aggregates = new ArrayList<AggregateNode>();
for (TableElementNode element : this) {
ColumnDefinitionNode cdn;
GenerationClauseNode generationClauseNode;
ValueNode generationTree;
if (!(element instanceof ColumnDefinitionNode)) {
continue;
}
cdn = (ColumnDefinitionNode) element;
if (!cdn.hasGenerationClause()) {
continue;
}
generationClauseNode = cdn.getGenerationClauseNode();
// bind the generation clause
final int previousReliability = cc.getReliability();
ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
try {
/* Each generation clause can have its own set of dependencies.
* These dependencies need to be shared with the prepared
* statement as well. We create a new auxiliary provider list
* for the generation clause, "push" it on the compiler context
* by swapping it with the current auxiliary provider list
* and the "pop" it when we're done by restoring the old
* auxiliary provider list.
*/
ProviderList apl = new ProviderList();
cc.setCurrentAuxiliaryProviderList(apl);
// Tell the compiler context to forbid subqueries and
// non-deterministic functions.
cc.setReliability(CompilerContext.GENERATION_CLAUSE_RESTRICTION);
generationTree = generationClauseNode.bindExpression(fromList, (SubqueryList) null, aggregates);
SelectNode.checkNoWindowFunctions(generationClauseNode, "generation clause");
//
// If the user did not declare a type for this column, then the column type defaults
// to the type of the generation clause.
// However, if the user did declare a type for this column, then the
// type of the generation clause must be assignable to the declared
// type.
//
DataTypeDescriptor generationClauseType = generationTree.getTypeServices();
DataTypeDescriptor declaredType = cdn.getType();
if (declaredType == null) {
cdn.setType(generationClauseType);
//
// Poke the type into the FromTable so that constraints will
// compile.
//
tableColumns.getResultColumn(cdn.getColumnName(), false).setType(generationClauseType);
//
// We skipped these steps earlier on because we didn't have
// a datatype. Now that we have a datatype, revisit these
// steps.
//
setCollationTypeOnCharacterStringColumn(sd, cdn);
cdn.checkUserType(table.getTableDescriptor());
} else {
TypeId declaredTypeId = declaredType.getTypeId();
TypeId resolvedTypeId = generationClauseType.getTypeId();
if (!getTypeCompiler(resolvedTypeId).convertible(declaredTypeId, false)) {
throw StandardException.newException(SQLState.LANG_UNASSIGNABLE_GENERATION_CLAUSE, cdn.getName(), resolvedTypeId.getSQLTypeName());
}
}
// no aggregates, please
if (!aggregates.isEmpty()) {
throw StandardException.newException(SQLState.LANG_AGGREGATE_IN_GENERATION_CLAUSE, cdn.getName());
}
/* Save the APL off in the constraint node */
if (apl.size() > 0) {
generationClauseNode.setAuxiliaryProviderList(apl);
}
} finally {
// Restore previous compiler state
cc.setCurrentAuxiliaryProviderList(prevAPL);
cc.setReliability(previousReliability);
}
/* We have a valid generation clause, now build an array of
* 1-based columnIds that the clause references.
*/
ResultColumnList rcl = table.getResultColumns();
int numReferenced = rcl.countReferencedColumns();
int[] generationClauseColumnReferences = new int[numReferenced];
int position = rcl.getPosition(cdn.getColumnName(), 1);
generatedColumns.set(position);
rcl.recordColumnReferences(generationClauseColumnReferences, 1);
String[] referencedColumnNames = new String[numReferenced];
for (int i = 0; i < numReferenced; i++) {
referencedColumnNames[i] = rcl.elementAt(generationClauseColumnReferences[i] - 1).getName();
}
String currentSchemaName = getLanguageConnectionContext().getCurrentSchemaName();
DefaultInfoImpl dii = new DefaultInfoImpl(generationClauseNode.getExpressionText(), referencedColumnNames, currentSchemaName);
cdn.setDefaultInfo(dii);
/* Clear the column references in the RCL so each generation clause
* starts with a clean list.
*/
rcl.clearColumnReferences();
}
}
use of org.apache.derby.catalog.types.DefaultInfoImpl in project derby by apache.
the class ResultColumnList method replaceOrForbidDefaults.
/**
* Replace any DEFAULTs with the associated tree for the default if
* allowed, or flag.
*
* @param ttd The TableDescriptor for the target table.
* @param tcl The RCL for the target table.
* @param allowDefaults true if allowed
*
* @exception StandardException Thrown on error
*/
void replaceOrForbidDefaults(TableDescriptor ttd, ResultColumnList tcl, boolean allowDefaults) throws StandardException {
int size = size();
for (int index = 0; index < size; index++) {
ResultColumn rc = elementAt(index);
if (rc.isDefaultColumn()) {
if (!allowDefaults) {
throw StandardException.newException(SQLState.LANG_INVALID_USE_OF_DEFAULT);
}
// DefaultNode defaultNode = (DefaultNode) rc.getExpression();
// Get ColumnDescriptor by name or by position?
ColumnDescriptor cd = null;
if (tcl == null) {
cd = ttd.getColumnDescriptor(index + 1);
} else if (index < tcl.size()) {
ResultColumn trc = tcl.elementAt(index);
cd = ttd.getColumnDescriptor(trc.getName());
}
// Too many RCs if no ColumnDescriptor
if (cd == null) {
throw StandardException.newException(SQLState.LANG_TOO_MANY_RESULT_COLUMNS, ttd.getQualifiedName());
}
if (cd.isAutoincrement()) {
rc.setAutoincrementGenerated();
}
// end of if ()
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo();
//
if ((defaultInfo != null) && !defaultInfo.isGeneratedColumn()) {
setDefault(rc, cd, defaultInfo);
} else {
rc.setExpression(new UntypedNullConstantNode(getContextManager()));
rc.setWasDefaultColumn(true);
}
rc.setDefaultColumn(false);
}
}
}
use of org.apache.derby.catalog.types.DefaultInfoImpl in project derby by apache.
the class DefaultNode method bindExpression.
/**
* Bind this expression. This means binding the sub-expressions,
* as well as figuring out what the return type is for this expression.
* In this case, there are no sub-expressions, and the return type
* is already known, so this is just a stub.
*
* @param fromList The FROM list for the query this
* expression is in, for binding columns.
* @param subqueryList The subquery list being built as we find SubqueryNodes
* @param aggregates The aggregate list being built as we find AggregateNodes
*
* @return The new top of the expression tree.
*
* @exception StandardException Thrown on failure
*/
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
ColumnDescriptor cd;
TableDescriptor td;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(fromList.size() != 0, "fromList expected to be non-empty");
if (!(fromList.elementAt(0) instanceof FromBaseTable)) {
SanityManager.THROWASSERT("fromList.elementAt(0) expected to be instanceof FromBaseTable, not " + fromList.elementAt(0).getClass().getName());
}
}
// Get the TableDescriptor for the target table
td = ((FromBaseTable) fromList.elementAt(0)).getTableDescriptor();
// Get the ColumnDescriptor for the column
cd = td.getColumnDescriptor(columnName);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(cd != null, "cd expected to be non-null");
}
/* If we have the default text, then parse and bind it and
* return the tree.
*/
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo();
if (defaultInfo != null) {
String defaultTxt = defaultInfo.getDefaultText();
ValueNode defaultTre = parseDefault(defaultTxt, getLanguageConnectionContext(), getCompilerContext());
/* Query is dependent on the DefaultDescriptor */
DefaultDescriptor defaultDescriptor = cd.getDefaultDescriptor(getDataDictionary());
getCompilerContext().createDependency(defaultDescriptor);
return defaultTre.bindExpression(fromList, subqueryList, aggregates);
} else {
// Default is null
return new UntypedNullConstantNode(getContextManager());
}
}
Aggregations