use of org.apache.derby.iapi.sql.depend.ProviderList in project derby by apache.
the class TableElementList method bindAndValidateCheckConstraints.
/**
* Bind and validate all of the check constraints in this list against
* the specified FromList.
*
* @param fromList The FromList in question.
*
* @exception StandardException Thrown on error
*/
void bindAndValidateCheckConstraints(FromList fromList) throws StandardException {
FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
CompilerContext cc = getCompilerContext();
ArrayList<AggregateNode> aggregates = new ArrayList<AggregateNode>();
for (TableElementNode element : this) {
ConstraintDefinitionNode cdn;
ValueNode checkTree;
if (!(element instanceof ConstraintDefinitionNode)) {
continue;
}
cdn = (ConstraintDefinitionNode) element;
if (cdn.getConstraintType() != DataDictionary.CHECK_CONSTRAINT) {
continue;
}
checkTree = cdn.getCheckCondition();
// bind the check condition
// verify that it evaluates to a boolean
final int previousReliability = cc.getReliability();
try {
/* Each check constraint 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 check constraint, "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();
ProviderList prevAPL = cc.getCurrentAuxiliaryProviderList();
cc.setCurrentAuxiliaryProviderList(apl);
// Tell the compiler context to only allow deterministic nodes
cc.setReliability(CompilerContext.CHECK_CONSTRAINT);
checkTree = checkTree.bindExpression(fromList, (SubqueryList) null, aggregates);
// no aggregates, please
if (!aggregates.isEmpty()) {
throw StandardException.newException(SQLState.LANG_INVALID_CHECK_CONSTRAINT, cdn.getConstraintText());
}
checkTree = checkTree.checkIsBoolean();
cdn.setCheckCondition(checkTree);
/* Save the APL off in the constraint node */
if (apl.size() > 0) {
cdn.setAuxiliaryProviderList(apl);
}
// Restore the previous AuxiliaryProviderList
cc.setCurrentAuxiliaryProviderList(prevAPL);
} finally {
cc.setReliability(previousReliability);
}
/* We have a valid check constraint.
* Now we build a list with only the referenced columns and
* copy it to the cdn. Thus we can build the array of
* column names for the referenced columns during generate().
*/
ResultColumnList rcl = table.getResultColumns();
int numReferenced = rcl.countReferencedColumns();
ResultColumnList refRCL = new ResultColumnList(getContextManager());
rcl.copyReferencedColumnsToNewList(refRCL);
/* A column check constraint can only refer to that column. If this is a
* column constraint, we should have an RCL with that column
*/
if (cdn.getColumnList() != null) {
String colName = cdn.getColumnList().elementAt(0).getName();
if (numReferenced > 1 || !colName.equals(refRCL.elementAt(0).getName()))
throw StandardException.newException(SQLState.LANG_DB2_INVALID_CHECK_CONSTRAINT, colName);
}
cdn.setColumnList(refRCL);
/* Clear the column references in the RCL so each check constraint
* starts with a clean list.
*/
rcl.clearColumnReferences();
// Make sure all names are schema qualified (DERBY-6362)
cdn.qualifyNames();
}
}
use of org.apache.derby.iapi.sql.depend.ProviderList 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.iapi.sql.depend.ProviderList in project derby by apache.
the class CreateViewNode method bindViewDefinition.
/**
* Bind the query expression for a view definition.
*
* @param dataDictionary The DataDictionary to use to look up
* columns, tables, etc.
*
* @return Array of providers that this view depends on.
*
* @exception StandardException Thrown on error
*/
private ProviderInfo[] bindViewDefinition(DataDictionary dataDictionary, CompilerContext compilerContext, LanguageConnectionContext lcc, OptimizerFactory optimizerFactory, ResultSetNode queryExpr, ContextManager cm) throws StandardException {
FromList fromList = new FromList(optimizerFactory.doJoinOrderOptimization(), cm);
ProviderList prevAPL = compilerContext.getCurrentAuxiliaryProviderList();
ProviderList apl = new ProviderList();
try {
compilerContext.setCurrentAuxiliaryProviderList(apl);
compilerContext.pushCurrentPrivType(Authorizer.SELECT_PRIV);
/* Bind the tables in the queryExpression */
queryExpr = queryExpr.bindNonVTITables(dataDictionary, fromList);
queryExpr = queryExpr.bindVTITables(fromList);
/* Bind the expressions under the resultSet */
queryExpr.bindExpressions(fromList);
// cannot define views on temporary tables
if (queryExpr instanceof SelectNode) {
// If attempting to reference a SESSION schema table (temporary or permanent) in the view, throw an exception
if (queryExpr.referencesSessionSchema())
throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);
}
// bind the query expression
queryExpr.bindResultColumns(fromList);
// rejects any untyped nulls in the RCL
// e.g.: CREATE VIEW v1 AS VALUES NULL
queryExpr.bindUntypedNullsToResultColumns(null);
} finally {
compilerContext.popCurrentPrivType();
compilerContext.setCurrentAuxiliaryProviderList(prevAPL);
}
DependencyManager dm = dataDictionary.getDependencyManager();
ProviderInfo[] provInfo = dm.getPersistentProviderInfos(apl);
// need to clear the column info in case the same table descriptor
// is reused, eg., in multiple target only view definition
dm.clearColumnInfoInProviders(apl);
/* Verify that all underlying ResultSets reclaimed their FromList */
if (SanityManager.DEBUG) {
SanityManager.ASSERT(fromList.size() == 0, "fromList.size() is expected to be 0, not " + fromList.size() + " on return from RS.bindExpressions()");
}
return provInfo;
}
Aggregations