use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class ConsistencyChecker method checkTable.
/**
* Check the named table, ensuring that all of its indexes are consistent
* with the base table.
* Use this
* method only within an SQL-J statement; do not call it directly.
* <P>When tables are consistent, the method returns true. Otherwise, the method throws an exception.
* <p>To check the consistency of a single table:
* <p><code>
* VALUES ConsistencyChecker::checkTable(<i>SchemaName</i>, <i>TableName</i>)</code></p>
* <P>For example, to check the consistency of the table <i>APP.Flights</i>:
* <p><code>
* VALUES ConsistencyChecker::checkTable('APP', 'FLIGHTS')</code></p>
* <p>To check the consistency of all of the tables in the 'APP' schema,
* stopping at the first failure:
*
* <P><code>SELECT tablename, ConsistencyChecker::checkTable(<br>
* 'APP', tablename)<br>
* FROM sys.sysschemas s, sys.systables t
* WHERE s.schemaname = 'APP' AND s.schemaid = t.schemaid</code>
*
* <p> To check the consistency of an entire database, stopping at the first failure:
*
* <p><code>SELECT schemaname, tablename,<br>
* ConsistencyChecker::checkTable(schemaname, tablename)<br>
* FROM sys.sysschemas s, sys.systables t<br>
* WHERE s.schemaid = t.schemaid</code>
*
* @param schemaName The schema name of the table.
* @param tableName The name of the table
*
* @return true, if the table is consistent, exception thrown if inconsistent
*
* @exception SQLException Thrown if some inconsistency
* is found, or if some unexpected
* exception is thrown..
*/
public static boolean checkTable(String schemaName, String tableName) throws SQLException {
DataDictionary dd;
TableDescriptor td;
long baseRowCount = -1;
TransactionController tc;
ConglomerateDescriptor heapCD;
ConglomerateDescriptor indexCD;
ExecRow baseRow;
ExecRow indexRow;
RowLocation rl = null;
RowLocation scanRL = null;
ScanController scan = null;
int[] baseColumnPositions;
int baseColumns = 0;
DataValueFactory dvf;
long indexRows;
ConglomerateController baseCC = null;
ConglomerateController indexCC = null;
SchemaDescriptor sd;
ConstraintDescriptor constraintDesc;
LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();
tc = lcc.getTransactionExecute();
try {
// make sure that application code doesn't bypass security checks
// by calling this public entry point
SecurityUtil.authorize(Securable.CHECK_TABLE);
dd = lcc.getDataDictionary();
dvf = lcc.getDataValueFactory();
ExecutionFactory ef = lcc.getLanguageConnectionFactory().getExecutionFactory();
sd = dd.getSchemaDescriptor(schemaName, tc, true);
td = dd.getTableDescriptor(tableName, sd, tc);
if (td == null) {
throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, schemaName + "." + tableName);
}
/* Skip views */
if (td.getTableType() == TableDescriptor.VIEW_TYPE) {
return true;
}
/* Open the heap for reading */
baseCC = tc.openConglomerate(td.getHeapConglomerateId(), false, 0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
/* Check the consistency of the heap */
baseCC.checkConsistency();
heapCD = td.getConglomerateDescriptor(td.getHeapConglomerateId());
/* Get a row template for the base table */
baseRow = ef.getValueRow(td.getNumberOfColumns());
/* Fill the row with nulls of the correct type */
ColumnDescriptorList cdl = td.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++) {
ColumnDescriptor cd = (ColumnDescriptor) cdl.elementAt(index);
baseRow.setColumn(cd.getPosition(), cd.getType().getNull());
}
/* Look at all the indexes on the table */
ConglomerateDescriptor[] cds = td.getConglomerateDescriptors();
for (int index = 0; index < cds.length; index++) {
indexCD = cds[index];
/* Skip the heap */
if (!indexCD.isIndex())
continue;
/* Check the internal consistency of the index */
indexCC = tc.openConglomerate(indexCD.getConglomerateNumber(), false, 0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE);
indexCC.checkConsistency();
indexCC.close();
indexCC = null;
if (indexCD.isConstraint()) {
constraintDesc = dd.getConstraintDescriptor(td, indexCD.getUUID());
if (constraintDesc == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "CONSTRAINT for INDEX", indexCD.getConglomerateName());
}
}
/*
** Set the base row count when we get to the first index.
** We do this here, rather than outside the index loop, so
** we won't do the work of counting the rows in the base table
** if there are no indexes to check.
*/
if (baseRowCount < 0) {
scan = tc.openScan(heapCD.getConglomerateNumber(), // hold
false, // not forUpdate
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, RowUtil.EMPTY_ROW_BITSET, // startKeyValue
null, // not used with null start posn.
0, // qualifier
null, // stopKeyValue
null, // not used with null stop posn.
0);
/* Also, get the row location template for index rows */
rl = scan.newRowLocationTemplate();
scanRL = scan.newRowLocationTemplate();
for (baseRowCount = 0; scan.next(); baseRowCount++) ;
/* Empty statement */
scan.close();
scan = null;
}
baseColumnPositions = indexCD.getIndexDescriptor().baseColumnPositions();
baseColumns = baseColumnPositions.length;
FormatableBitSet indexColsBitSet = new FormatableBitSet();
for (int i = 0; i < baseColumns; i++) {
indexColsBitSet.grow(baseColumnPositions[i]);
indexColsBitSet.set(baseColumnPositions[i] - 1);
}
/* Get one row template for the index scan, and one for the fetch */
indexRow = ef.getValueRow(baseColumns + 1);
/* Fill the row with nulls of the correct type */
for (int column = 0; column < baseColumns; column++) {
/* Column positions in the data dictionary are one-based */
ColumnDescriptor cd = td.getColumnDescriptor(baseColumnPositions[column]);
indexRow.setColumn(column + 1, cd.getType().getNull());
}
/* Set the row location in the last column of the index row */
indexRow.setColumn(baseColumns + 1, rl);
/* Do a full scan of the index */
scan = tc.openScan(indexCD.getConglomerateNumber(), // hold
false, // not forUpdate
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, (FormatableBitSet) null, // startKeyValue
null, // not used with null start posn.
0, // qualifier
null, // stopKeyValue
null, // not used with null stop posn.
0);
DataValueDescriptor[] baseRowIndexOrder = new DataValueDescriptor[baseColumns];
DataValueDescriptor[] baseObjectArray = baseRow.getRowArray();
for (int i = 0; i < baseColumns; i++) {
baseRowIndexOrder[i] = baseObjectArray[baseColumnPositions[i] - 1];
}
/* Get the index rows and count them */
for (indexRows = 0; scan.fetchNext(indexRow.getRowArray()); indexRows++) {
/*
** Get the base row using the RowLocation in the index row,
** which is in the last column.
*/
RowLocation baseRL = (RowLocation) indexRow.getColumn(baseColumns + 1);
boolean base_row_exists = baseCC.fetch(baseRL, baseObjectArray, indexColsBitSet);
/* Throw exception if fetch() returns false */
if (!base_row_exists) {
String indexName = indexCD.getConglomerateName();
throw StandardException.newException(SQLState.LANG_INCONSISTENT_ROW_LOCATION, (schemaName + "." + tableName), indexName, baseRL.toString(), indexRow.toString());
}
/* Compare all the column values */
for (int column = 0; column < baseColumns; column++) {
DataValueDescriptor indexColumn = indexRow.getColumn(column + 1);
DataValueDescriptor baseColumn = baseRowIndexOrder[column];
/*
** With this form of compare(), null is considered equal
** to null.
*/
if (indexColumn.compare(baseColumn) != 0) {
ColumnDescriptor cd = td.getColumnDescriptor(baseColumnPositions[column]);
throw StandardException.newException(SQLState.LANG_INDEX_COLUMN_NOT_EQUAL, indexCD.getConglomerateName(), td.getSchemaName(), td.getName(), baseRL.toString(), cd.getColumnName(), indexColumn.toString(), baseColumn.toString(), indexRow.toString());
}
}
}
/* Clean up after the index scan */
scan.close();
scan = null;
/*
** The index is supposed to have the same number of rows as the
** base conglomerate.
*/
if (indexRows != baseRowCount) {
throw StandardException.newException(SQLState.LANG_INDEX_ROW_COUNT_MISMATCH, indexCD.getConglomerateName(), td.getSchemaName(), td.getName(), Long.toString(indexRows), Long.toString(baseRowCount));
}
}
/* check that all constraints have backing index */
ConstraintDescriptorList constraintDescList = dd.getConstraintDescriptors(td);
for (int index = 0; index < constraintDescList.size(); index++) {
constraintDesc = constraintDescList.elementAt(index);
if (constraintDesc.hasBackingIndex()) {
ConglomerateDescriptor conglomDesc;
conglomDesc = td.getConglomerateDescriptor(constraintDesc.getConglomerateId());
if (conglomDesc == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "INDEX for CONSTRAINT", constraintDesc.getConstraintName());
}
}
}
} catch (StandardException se) {
throw PublicAPI.wrapStandardException(se);
} finally {
try {
/* Clean up before we leave */
if (baseCC != null) {
baseCC.close();
baseCC = null;
}
if (indexCC != null) {
indexCC.close();
indexCC = null;
}
if (scan != null) {
scan.close();
scan = null;
}
} catch (StandardException se) {
throw PublicAPI.wrapStandardException(se);
}
}
return true;
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class EmbedConnection method checkUserIsNotARole.
/**
* If applicable, check that we don't connect with a user name
* that equals a role.
*
* @exception SQLException Will throw if the current authorization
* id in {@code lcc} (which is already normalized to
* case normal form - CNF) equals an existing role name
* (which is also stored in CNF).
*/
private void checkUserIsNotARole() throws SQLException {
TransactionResourceImpl tr = getTR();
try {
tr.startTransaction();
LanguageConnectionContext lcc = tr.getLcc();
String username = lcc.getSessionUserId();
DataDictionary dd = lcc.getDataDictionary();
// introduced in 10.4):
if (lcc.usesSqlAuthorization() && dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) {
TransactionController tc = lcc.getTransactionExecute();
String failedString = MessageService.getTextMessage(MessageId.AUTH_INVALID);
if (dd.getRoleDefinitionDescriptor(username) != null) {
throw newSQLException(SQLState.NET_CONNECT_AUTH_FAILED, failedString);
}
}
tr.rollback();
InterruptStatus.restoreIntrFlagIfSeen(lcc);
} catch (StandardException e) {
try {
tr.rollback();
} catch (StandardException ee) {
}
throw handleException(e);
}
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class EmbedDatabaseMetaData method prepareSPS.
/*
** Given a SPS name and a query text it returns a
** java.sql.PreparedStatement for the SPS. If the SPS
** doeesn't exist is created.
**
*/
private PreparedStatement prepareSPS(String spsName, String spsText, boolean net) throws StandardException, SQLException {
LanguageConnectionContext lcc = getLanguageConnectionContext();
/* We now need to do this in sub transaction because we could possibly recompile SPS
* later, and the recompile is in a sub transaction, and will update the SYSSTATEMENTS
* entry. Don't want to block.
*/
lcc.beginNestedTransaction(true);
DataDictionary dd = getLanguageConnectionContext().getDataDictionary();
SPSDescriptor spsd = dd.getSPSDescriptor(spsName, net ? dd.getSysIBMSchemaDescriptor() : dd.getSystemSchemaDescriptor());
lcc.commitNestedTransaction();
if (spsd == null) {
throw Util.notImplemented(spsName);
}
/* manish:
There should be a nicer way of getting a
java.sql.PreparedStatement from an SPS descriptor!
*/
/*
** It is unnecessarily expensive to get the
** the statement, and then send an EXECUTE
** statement, but we have no (easy) way of turning
** the statement into a java.sql.PreparedStatement.
*/
String queryText = "EXECUTE STATEMENT " + (net ? "SYSIBM" : "SYS") + ".\"" + spsName + "\"";
return getEmbedConnection().prepareMetaDataStatement(queryText);
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class DatabaseContextImpl method cleanupOnError.
public void cleanupOnError(Throwable t) {
if (!(t instanceof StandardException))
return;
StandardException se = (StandardException) t;
// going away.
if (se.getSeverity() < ExceptionSeverity.SESSION_SEVERITY)
return;
popMe();
if (se.getSeverity() >= ExceptionSeverity.DATABASE_SEVERITY) {
// DERBY-5108: Shut down the istat daemon thread before shutting
// down the various modules belonging to the database. An active
// istat daemon thread at the time of shutdown may result in
// containers being reopened after the container cache has been
// shut down. On certain platforms, this results in database
// files that can't be deleted until the VM exits.
DataDictionary dd = db.getDataDictionary();
// dd is null if the db is an active slave db (replication)
if (dd != null) {
dd.disableIndexStatsRefresher();
}
}
if (se.getSeverity() == ExceptionSeverity.DATABASE_SEVERITY) {
getContextService().notifyAllActiveThreads(this);
// This may be called multiple times, but is short-circuited
// in the monitor.
getMonitor().shutdown(db);
}
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class AggregateNode method bindExpression.
/**
* Bind this operator. Determine the type of the subexpression,
* and pass that into the UserAggregate.
*
* @param fromList The query's FROM list
* @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 {
DataDictionary dd = getDataDictionary();
DataTypeDescriptor dts = null;
ClassFactory cf;
cf = getClassFactory();
classInspector = cf.getClassInspector();
boolean noSchema = true;
if (userAggregateName != null) {
noSchema = (userAggregateName.getSchemaName() == null);
userAggregateName.bind();
}
// bind it now.
if (userAggregateName != null && uad == null) {
String schemaName = userAggregateName.getSchemaName();
AliasDescriptor ad = resolveAggregate(dd, getSchemaDescriptor(schemaName, true), userAggregateName.getTableName(), noSchema);
if (ad == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, AliasDescriptor.getAliasType(AliasInfo.ALIAS_TYPE_AGGREGATE_AS_CHAR), userAggregateName.getTableName());
}
setUserDefinedAggregate(new UserAggregateDefinition(ad));
aggregateName = ad.getJavaClassName();
}
instantiateAggDef();
// if this is a user-defined aggregate
if (isUserDefinedAggregate()) {
AliasDescriptor ad = ((UserAggregateDefinition) uad).getAliasDescriptor();
boolean isModernBuiltinAggregate = SchemaDescriptor.STD_SYSTEM_SCHEMA_NAME.equals(ad.getSchemaName());
if (distinct && isModernBuiltinAggregate) {
throw StandardException.newException(SQLState.LANG_BAD_DISTINCT_AGG);
}
// set up dependency on the user-defined aggregate and compile a check for USAGE
// priv if needed
getCompilerContext().createDependency(ad);
if (isPrivilegeCollectionRequired()) {
//
if (!isModernBuiltinAggregate) {
getCompilerContext().addRequiredUsagePriv(ad);
}
}
}
// Add ourselves to the list of aggregates before we do anything else.
aggregates.add(this);
CompilerContext cc = getCompilerContext();
// operand being null means a count(*)
if (operand != null) {
int previousReliability = orReliability(CompilerContext.AGGREGATE_RESTRICTION);
bindOperand(fromList, subqueryList, aggregates);
cc.setReliability(previousReliability);
/*
** Make sure that we don't have an aggregate
** IMMEDIATELY below us. Don't search below
** any ResultSetNodes.
*/
HasNodeVisitor visitor = new HasNodeVisitor(this.getClass(), ResultSetNode.class);
operand.accept(visitor);
if (visitor.hasNode()) {
throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_CONTAINS_AGGREGATE, getSQLName());
}
// Also forbid any window function inside an aggregate unless in
// subquery, cf. SQL 2003, section 10.9, SR 7 a).
SelectNode.checkNoWindowFunctions(operand, aggregateName);
/*
** Check the type of the operand. Make sure that the user
** defined aggregate can handle the operand datatype.
*/
dts = operand.getTypeServices();
/* Convert count(nonNullableColumn) to count(*) */
if (uad instanceof CountAggregateDefinition && !dts.isNullable()) {
setOperator(aggregateName);
setMethodName(aggregateName);
}
/*
** If we have a distinct, then the value expression
** MUST implement Orderable because we are going
** to process it using it as part of a sort.
*/
if (distinct) {
/*
** For now, we check to see if orderable() returns
** true for this type. In the future we may need
** to check to see if the type implements Orderable
**
*/
if (!operand.getTypeId().orderable(cf)) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, dts.getTypeId().getSQLTypeName());
}
}
/*
** Don't allow an untyped null
*/
if (operand instanceof UntypedNullConstantNode) {
throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE_NULL, getSQLName());
}
}
/*
** Ask the aggregate definition whether it can handle
** the input datatype.
*/
aggregatorClassName = new StringBuffer();
DataTypeDescriptor resultType = uad.getAggregator(dts, aggregatorClassName);
if (resultType == null) {
throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE, getSQLName(), operand.getTypeId().getSQLTypeName());
}
// coerced to the expected input type of the aggregator.
if (isUserDefinedAggregate()) {
ValueNode castNode = ((UserAggregateDefinition) uad).castInputValue(operand, getContextManager());
if (castNode != null) {
operand = castNode.bindExpression(fromList, subqueryList, aggregates);
}
}
checkAggregatorClassName(aggregatorClassName.toString());
setType(resultType);
return this;
}
Aggregations