use of org.apache.derby.iapi.sql.compile.CompilerContext in project derby by apache.
the class RenameNode method bindStatement.
// We inherit the generate() method from DDLStatementNode.
/**
* Bind this node. This means doing any static error checking that
* can be done before actually renaming the table/column/index.
*
* For a table rename: looking up the from table, verifying it exists
* verifying it's not a system table, verifying it's not view
* and looking up to table, verifying it doesn't exist.
*
* For a column rename: looking up the table, verifying it exists,
* verifying it's not a system table, verifying it's not view, verifying
* the from column exists, verifying the to column doesn't exist.
*
* For a index rename: looking up the table, verifying it exists,
* verifying it's not a system table, verifying it's not view, verifying
* the from index exists, verifying the to index doesn't exist.
*
* @exception StandardException Thrown on error
*/
@Override
public void bindStatement() throws StandardException {
CompilerContext cc = getCompilerContext();
DataDictionary dd = getDataDictionary();
ConglomerateDescriptor cd;
SchemaDescriptor sd;
/* in case of rename index, the only thing we get from parser is
* current and new index names with no information about the
* table it belongs to. This is because index names are unique
* within a schema and hence then is no need to qualify an index
* name with a table name which we have to do for rename column.
* But from the index name, using the data dictionary, you can
* find the table it belongs to. Since most of the checking
* in bind is done using table descriptor, in the following if
* statement, we are trying to get the table information from the
* index name so it is available for the rest of he bind code.
*/
TableName baseTable;
if (renamingWhat == StatementType.RENAME_INDEX) {
sd = getSchemaDescriptor((String) null);
ConglomerateDescriptor indexDescriptor = dd.getConglomerateDescriptor(oldObjectName, sd, false);
if (indexDescriptor == null)
throw StandardException.newException(SQLState.LANG_INDEX_NOT_FOUND, oldObjectName);
/* Get the table descriptor */
td = dd.getTableDescriptor(indexDescriptor.getTableID());
initAndCheck(makeTableName(td.getSchemaName(), td.getName()));
} else
sd = getSchemaDescriptor();
td = getTableDescriptor();
// throw an exception if user is attempting a rename on temporary table
if (td.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
}
switch(this.renamingWhat) {
case StatementType.RENAME_TABLE:
/* Verify that new table name does not exist in the database */
TableDescriptor tabDesc = getTableDescriptor(newObjectName, sd);
if (tabDesc != null)
throw descriptorExistsException(tabDesc, sd);
renameTableBind(dd);
break;
case StatementType.RENAME_COLUMN:
renameColumnBind(dd);
break;
case StatementType.RENAME_INDEX:
ConglomerateDescriptor conglomDesc = dd.getConglomerateDescriptor(newObjectName, sd, false);
if (conglomDesc != null)
throw descriptorExistsException(conglomDesc, sd);
break;
default:
if (SanityManager.DEBUG)
SanityManager.THROWASSERT("Unexpected rename action in RenameNode");
break;
}
conglomerateNumber = td.getHeapConglomerateId();
/* Get the base conglomerate descriptor */
cd = td.getConglomerateDescriptor(conglomerateNumber);
/* Statement is dependent on the TableDescriptor and ConglomerateDescriptor */
cc.createDependency(td);
cc.createDependency(cd);
}
use of org.apache.derby.iapi.sql.compile.CompilerContext in project derby by apache.
the class FromBaseTable method genProjectRestrict.
/**
* Put a ProjectRestrictNode on top of each FromTable in the FromList.
* ColumnReferences must continue to point to the same ResultColumn, so
* that ResultColumn must percolate up to the new PRN. However,
* that ResultColumn will point to a new expression, a VirtualColumnNode,
* which points to the FromTable and the ResultColumn that is the source for
* the ColumnReference.
* (The new PRN will have the original of the ResultColumnList and
* the ResultColumns from that list. The FromTable will get shallow copies
* of the ResultColumnList and its ResultColumns. ResultColumn.expression
* will remain at the FromTable, with the PRN getting a new
* VirtualColumnNode for each ResultColumn.expression.)
* We then project out the non-referenced columns. If there are no referenced
* columns, then the PRN's ResultColumnList will consist of a single ResultColumn
* whose expression is 1.
*
* @param numTables Number of tables in the DML Statement
*
* @return The generated ProjectRestrictNode atop the original FromTable.
*
* @exception StandardException Thrown on error
*/
@Override
protected ResultSetNode genProjectRestrict(int numTables) throws StandardException {
/* We get a shallow copy of the ResultColumnList and its
* ResultColumns. (Copy maintains ResultColumn.expression for now.)
*/
ResultColumnList prRCList = getResultColumns();
setResultColumns(getResultColumns().copyListAndObjects());
getResultColumns().setIndexRow(baseConglomerateDescriptor.getConglomerateNumber(), forUpdate());
/* Replace ResultColumn.expression with new VirtualColumnNodes
* in the ProjectRestrictNode's ResultColumnList. (VirtualColumnNodes include
* pointers to source ResultSetNode, this, and source ResultColumn.)
* NOTE: We don't want to mark the underlying RCs as referenced, otherwise
* we won't be able to project out any of them.
*/
prRCList.genVirtualColumnNodes(this, getResultColumns(), false);
/* Project out any unreferenced columns. If there are no referenced
* columns, generate and bind a single ResultColumn whose expression is 1.
*/
prRCList.doProjection();
/* Finally, we create the new ProjectRestrictNode */
ProjectRestrictNode result = new ProjectRestrictNode(this, prRCList, null, /* Restriction */
null, /* Restriction as PredicateList */
null, /* Project subquery list */
null, /* Restrict subquery list */
null, getContextManager());
if (isValidatingCheckConstraint()) {
CompilerContext cc = getCompilerContext();
if ((cc.getReliability() & // Internal feature: throw if used on app level
CompilerContext.INTERNAL_SQL_ILLEGAL) != 0) {
throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, "validateCheckConstraint");
}
result.setValidatingCheckConstraints(targetTableUUIDString);
}
return result;
}
use of org.apache.derby.iapi.sql.compile.CompilerContext in project derby by apache.
the class FromBaseTable method bindNonVTITables.
/**
* Bind the table in this FromBaseTable.
* This is where view resolution occurs
*
* @param dataDictionary The DataDictionary to use for binding
* @param fromListParam FromList to use/append to.
*
* @return ResultSetNode The FromTable for the table or resolved view.
*
* @exception StandardException Thrown on error
*/
@Override
ResultSetNode bindNonVTITables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException {
tableName.bind();
TableDescriptor tabDescr = bindTableDescriptor();
if (tabDescr.getTableType() == TableDescriptor.VTI_TYPE) {
ResultSetNode vtiNode = mapTableAsVTI(tabDescr, getCorrelationName(), getResultColumns(), getProperties(), getContextManager());
return vtiNode.bindNonVTITables(dataDictionary, fromListParam);
}
ResultColumnList derivedRCL = getResultColumns();
// make sure there's a restriction list
restrictionList = new PredicateList(getContextManager());
baseTableRestrictionList = new PredicateList(getContextManager());
CompilerContext compilerContext = getCompilerContext();
/* Generate the ResultColumnList */
setResultColumns(genResultColList());
templateColumns = getResultColumns();
/* Resolve the view, if this is a view */
if (tabDescr.getTableType() == TableDescriptor.VIEW_TYPE) {
FromSubquery fsq;
ResultSetNode rsn;
ViewDescriptor vd;
CreateViewNode cvn;
SchemaDescriptor compSchema;
/* Get the associated ViewDescriptor so that we can get
* the view definition text.
*/
vd = dataDictionary.getViewDescriptor(tabDescr);
/*
** Set the default compilation schema to be whatever
** this schema this view was originally compiled against.
** That way we pick up the same tables no matter what
** schema we are running against.
*/
compSchema = dataDictionary.getSchemaDescriptor(vd.getCompSchemaId(), null);
compilerContext.pushCompilationSchema(compSchema);
try {
/* This represents a view - query is dependent on the ViewDescriptor */
compilerContext.createDependency(vd);
cvn = (CreateViewNode) parseStatement(vd.getViewText(), false);
rsn = cvn.getParsedQueryExpression();
/* If the view contains a '*' then we mark the views derived column list
* so that the view will still work, and return the expected results,
* if any of the tables referenced in the view have columns added to
* them via ALTER TABLE. The expected results means that the view
* will always return the same # of columns.
*/
if (rsn.getResultColumns().containsAllResultColumn()) {
getResultColumns().setCountMismatchAllowed(true);
}
// checking.
for (ResultColumn rc : getResultColumns()) {
if (isPrivilegeCollectionRequired()) {
compilerContext.addRequiredColumnPriv(rc.getTableColumnDescriptor());
}
}
fsq = new FromSubquery(rsn, cvn.getOrderByList(), cvn.getOffset(), cvn.getFetchFirst(), cvn.hasJDBClimitClause(), (correlationName != null) ? correlationName : getOrigTableName().getTableName(), getResultColumns(), tableProperties, getContextManager());
// Transfer the nesting level to the new FromSubquery
fsq.setLevel(level);
// We are getting ready to bind the query underneath the view. Since
// that query is going to run with definer's privileges, we do not
// need to collect any privilege requirement for that query.
// Following call is marking the query to run with definer
// privileges. This marking will make sure that we do not collect
// any privilege requirement for it.
CollectNodesVisitor<QueryTreeNode> cnv = new CollectNodesVisitor<QueryTreeNode>(QueryTreeNode.class);
fsq.accept(cnv);
for (QueryTreeNode node : cnv.getList()) {
node.disablePrivilegeCollection();
}
fsq.setOrigTableName(this.getOrigTableName());
// since we reset the compilation schema when we return, we
// need to save it for use when we bind expressions:
fsq.setOrigCompilationSchema(compSchema);
ResultSetNode fsqBound = fsq.bindNonVTITables(dataDictionary, fromListParam);
/* Do error checking on derived column list and update "exposed"
* column names if valid.
*/
if (derivedRCL != null) {
fsqBound.getResultColumns().propagateDCLInfo(derivedRCL, origTableName.getFullTableName());
}
return fsqBound;
} finally {
compilerContext.popCompilationSchema();
}
} else {
/* This represents a table - query is dependent on the TableDescriptor */
compilerContext.createDependency(tabDescr);
/* Get the base conglomerate descriptor */
baseConglomerateDescriptor = tabDescr.getConglomerateDescriptor(tabDescr.getHeapConglomerateId());
// probably doesn't exist anymore.
if (baseConglomerateDescriptor == null) {
throw StandardException.newException(SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST, Long.valueOf(tabDescr.getHeapConglomerateId()));
}
/* Build the 0-based array of base column names. */
columnNames = getResultColumns().getColumnNames();
/* Do error checking on derived column list and update "exposed"
* column names if valid.
*/
if (derivedRCL != null) {
getResultColumns().propagateDCLInfo(derivedRCL, origTableName.getFullTableName());
}
/* Assign the tableNumber */
if (// allow re-bind, in which case use old number
tableNumber == -1)
tableNumber = compilerContext.getNextTableNumber();
}
//
// Only the DBO can select from SYS.SYSUSERS.
//
authorizeSYSUSERS = dataDictionary.usesSqlAuthorization() && tabDescr.getUUID().toString().equals(SYSUSERSRowFactory.SYSUSERS_UUID);
if (authorizeSYSUSERS) {
String databaseOwner = dataDictionary.getAuthorizationDatabaseOwner();
String currentUser = getLanguageConnectionContext().getStatementContext().getSQLSessionContext().getCurrentUser();
if (!databaseOwner.equals(currentUser)) {
throw StandardException.newException(SQLState.DBO_ONLY);
}
}
return this;
}
use of org.apache.derby.iapi.sql.compile.CompilerContext 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.iapi.sql.compile.CompilerContext in project derby by apache.
the class ConditionalNode method bindExpression.
/**
* Bind this expression. This means binding the sub-expressions,
* as well as figuring out what the return type is for this expression.
*
* @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 error
*/
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
CompilerContext cc = getCompilerContext();
int previousReliability = orReliability(CompilerContext.CONDITIONAL_RESTRICTION);
ValueNodeList caseOperandParameters = bindCaseOperand(cc, fromList, subqueryList, aggregates);
testConditions.bindExpression(fromList, subqueryList, aggregates);
// parameter), find out which type best describes it.
if (caseOperandParameters != null) {
// when testConditions was bound.
for (ValueNode vn : caseOperandParameters) {
// Check that this parameter is comparable to all the other
// parameters in the list. This indirectly checks whether
// all when operands have compatible types.
caseOperandParameters.comparable(vn);
// Replace the dummy parameter node with the actual case
// operand.
testConditions.accept(new ReplaceNodeVisitor(vn, caseOperand));
}
// Finally, after we have determined that all the when operands
// are compatible, and we have reinserted the case operand into
// the tree, set the type of the case operand to the dominant
// type of all the when operands.
caseOperand.setType(caseOperandParameters.getDominantTypeServices());
}
thenElseList.bindExpression(fromList, subqueryList, aggregates);
// Find the type of the first typed value in thenElseList and cast
// all untyped NULL values to that type. We don't need to find the
// dominant type here, since a top-level cast to that type will be
// added later, if necessary.
DataTypeDescriptor nullType = thenElseList.getTypeServices();
if (nullType == null) {
// an error.
throw StandardException.newException(SQLState.LANG_ALL_RESULT_EXPRESSIONS_UNTYPED);
} else {
recastNullNodes(nullType, fromList, subqueryList, aggregates);
}
// Set the result type of this conditional to be the dominant type
// of the result expressions.
setType(thenElseList.getDominantTypeServices());
/* testCondition must be a boolean expression.
* If it is a ? parameter on the left, then set type to boolean,
* otherwise verify that the result type is boolean.
*/
testConditions.setParameterDescriptor(new DataTypeDescriptor(TypeId.BOOLEAN_ID, true));
for (ValueNode testCondition : testConditions) {
if (!testCondition.getTypeServices().getTypeId().equals(TypeId.BOOLEAN_ID)) {
throw StandardException.newException(SQLState.LANG_CONDITIONAL_NON_BOOLEAN);
}
}
// Set the type of the parameters.
thenElseList.setParameterDescriptor(getTypeServices());
/* The then and else expressions must be type compatible */
ClassInspector cu = getClassFactory().getClassInspector();
/*
** If it is comparable, then we are ok. Note that we
** could in fact allow any expressions that are convertible()
** since we are going to generate a cast node, but that might
** be confusing to users...
*/
for (ValueNode expr : thenElseList) {
DataTypeDescriptor dtd = expr.getTypeServices();
String javaTypeName = dtd.getTypeId().getCorrespondingJavaTypeName();
String resultJavaTypeName = getTypeId().getCorrespondingJavaTypeName();
if (!dtd.comparable(getTypeServices(), false, getClassFactory()) && !cu.assignableTo(javaTypeName, resultJavaTypeName) && !cu.assignableTo(resultJavaTypeName, javaTypeName)) {
throw StandardException.newException(SQLState.LANG_NOT_TYPE_COMPATIBLE, dtd.getTypeId().getSQLTypeName(), getTypeId().getSQLTypeName());
}
}
// The result is nullable if and only if at least one of the result
// expressions is nullable (DERBY-6567).
setNullability(thenElseList.isNullable());
/*
** Generate a CastNode if necessary and
** stick it over the original expression
*/
TypeId condTypeId = getTypeId();
for (int i = 0; i < thenElseList.size(); i++) {
ValueNode expr = thenElseList.elementAt(i);
if (expr.getTypeId().typePrecedence() != condTypeId.typePrecedence()) {
// Cast to dominant type.
ValueNode cast = new CastNode(expr, getTypeServices(), getContextManager());
cast = cast.bindExpression(fromList, subqueryList, aggregates);
thenElseList.setElementAt(cast, i);
}
}
cc.setReliability(previousReliability);
return this;
}
Aggregations