use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DataDictionaryImpl method addSPSParams.
/**
* Add a column in SYS.SYSCOLUMNS for each parameter in the
* parameter list.
*/
private void addSPSParams(SPSDescriptor spsd, TransactionController tc) throws StandardException {
UUID uuid = spsd.getUUID();
DataTypeDescriptor[] params = spsd.getParams();
Object[] parameterDefaults = spsd.getParameterDefaults();
if (params == null)
return;
/* Create the columns */
int pdlSize = params.length;
for (int index = 0; index < pdlSize; index++) {
int parameterId = index + 1;
// RESOLVEAUTOINCREMENT
ColumnDescriptor cd = new ColumnDescriptor("PARAM" + parameterId, // position
parameterId, params[index], (// default
(parameterDefaults == null) || (index >= parameterDefaults.length)) ? (DataValueDescriptor) null : (DataValueDescriptor) parameterDefaults[index], (DefaultInfo) null, uuid, (UUID) null, 0, 0, 0, false);
addDescriptor(cd, null, SYSCOLUMNS_CATALOG_NUM, // no chance of duplicates here
false, tc);
}
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DataDictionaryImpl method getTriggerActionString.
public String getTriggerActionString(Visitable actionStmt, String oldReferencingName, String newReferencingName, String triggerDefinition, int[] referencedCols, int[] referencedColsInTriggerAction, int actionOffset, TableDescriptor triggerTableDescriptor, int triggerEventMask, boolean createTriggerTime, List<int[]> replacements, int[] cols) throws StandardException {
boolean in10_9_orHigherVersion = checkVersion(DataDictionary.DD_VERSION_DERBY_10_9, null);
StringBuilder newText = new StringBuilder();
int start = 0;
// Total Number of columns in the trigger table
int numberOfColsInTriggerTable = triggerTableDescriptor.getNumberOfColumns();
int[] triggerColsAndTriggerActionCols = new int[numberOfColsInTriggerTable];
SortedSet<ColumnReference> refs = getTransitionVariables(actionStmt, oldReferencingName, newReferencingName);
triggerColsAndTriggerActionCols = cols;
// (SELECT c FROM new TriggerOldTransitionTable OLD)
for (ColumnReference ref : refs) {
TableName tableName = ref.getQualifiedTableName();
int tableBeginOffset = tableName.getBeginOffset() - actionOffset;
String colName = ref.getColumnName();
// Add whatever we've seen after the previous replacement.
newText.append(triggerDefinition, start, tableBeginOffset);
int colPositionInRuntimeResultSet = -1;
ColumnDescriptor triggerColDesc = triggerTableDescriptor.getColumnDescriptor(colName);
// column in the trigger table.
if (triggerColDesc == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, tableName + "." + colName);
}
int colPositionInTriggerTable = triggerColDesc.getPosition();
// is 2. That is what the following code is doing.
if (in10_9_orHigherVersion && triggerColsAndTriggerActionCols != null) {
for (int j = 0; j < triggerColsAndTriggerActionCols.length; j++) {
if (triggerColsAndTriggerActionCols[j] == colPositionInTriggerTable)
colPositionInRuntimeResultSet = j + 1;
}
} else
colPositionInRuntimeResultSet = colPositionInTriggerTable;
// Add the replacement code that accesses a value in the
// transition variable.
final int replacementOffset = newText.length();
newText.append(genColumnReferenceSQL(triggerTableDescriptor, colName, tableName.getTableName(), tableName.getTableName().equals(oldReferencingName), colPositionInRuntimeResultSet));
start = ref.getEndOffset() + 1 - actionOffset;
if (replacements != null) {
// Record that we have made a change.
replacements.add(new int[] { // offset to replaced text
tableBeginOffset, // offset to token after replaced text
start, // offset to replacement
replacementOffset, // offset to token after replacement
newText.length() });
}
}
// By this point, we are finished transforming the trigger action if
// it has any references to old/new transition variables.
newText.append(triggerDefinition, start, triggerDefinition.length());
return newText.toString();
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DataDictionaryImpl method genColumnReferenceSQL.
/*
** Make sure the given column name is found in the trigger
** target table. Generate the appropriate SQL to get it.
**
** @return a string that is used to get the column using
** getObject() on the desired result set and CAST it back
** to the proper type in the SQL domain.
**
** @exception StandardException on invalid column name
*/
private String genColumnReferenceSQL(TableDescriptor td, String colName, String tabName, boolean isOldTable, int colPositionInRuntimeResultSet) throws StandardException {
ColumnDescriptor colDesc = null;
if ((colDesc = td.getColumnDescriptor(colName)) == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, tabName + "." + colName);
}
/*
** Generate something like this:
**
** CAST (org.apache.derby.iapi.db.Factory::
** getTriggerExecutionContext().getNewRow().
** getObject(<colPosition>) AS DECIMAL(6,2))
**
** Column position is used to avoid the wrong column being
** selected problem (DERBY-1258) caused by the case insensitive
** JDBC rules for fetching a column by name.
**
** The cast back to the SQL Domain may seem redundant
** but we need it to make the column reference appear
** EXACTLY like a regular column reference, so we need
** the object in the SQL Domain and we need to have the
** type information. Thus a user should be able to do
** something like
**
** CREATE TRIGGER ... INSERT INTO T length(Column), ...
**
*/
DataTypeDescriptor dts = colDesc.getType();
TypeId typeId = dts.getTypeId();
if (!typeId.isXMLTypeId()) {
StringBuffer methodCall = new StringBuffer();
methodCall.append("CAST (org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().");
methodCall.append(isOldTable ? "getOldRow()" : "getNewRow()");
methodCall.append(".getObject(");
methodCall.append(colPositionInRuntimeResultSet);
methodCall.append(") AS ");
/*
** getSQLString() returns <typeName>
** for user types, so call getSQLTypeName in that
** case.
*/
methodCall.append((typeId.userType() ? typeId.getSQLTypeName() : dts.getSQLstring()));
methodCall.append(") ");
return methodCall.toString();
} else {
/* DERBY-2350
**
** Triggers currently use jdbc 1.2 to access columns. The default
** uses getObject() which is not supported for an XML type until
** jdbc 4. In the meantime use getString() and then call
** XMLPARSE() on the string to get the type. See Derby issue and
** http://wiki.apache.org/db-derby/TriggerImplementation , for
** better long term solutions. Long term I think changing the
** trigger architecture to not rely on jdbc, but instead on an
** internal direct access interface to execution nodes would be
** best future direction, but believe such a change appropriate
** for a major release, not a bug fix.
**
** Rather than the above described code generation, use the
** following for XML types to generate an XML column from the
** old or new row.
**
** XMLPARSE(DOCUMENT
** CAST (org.apache.derby.iapi.db.Factory::
** getTriggerExecutionContext().getNewRow().
** getString(<colPosition>) AS CLOB)
** PRESERVE WHITESPACE)
*/
StringBuffer methodCall = new StringBuffer();
methodCall.append("XMLPARSE(DOCUMENT CAST( ");
methodCall.append("org.apache.derby.iapi.db.Factory::getTriggerExecutionContext().");
methodCall.append(isOldTable ? "getOldRow()" : "getNewRow()");
methodCall.append(".getString(");
methodCall.append(colPositionInRuntimeResultSet);
methodCall.append(") AS CLOB) PRESERVE WHITESPACE ) ");
return methodCall.toString();
}
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class SYSCOLUMNSRowFactory method buildDescriptor.
// /////////////////////////////////////////////////////////////////////////
//
// ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN OF CatalogRowFactory
//
// /////////////////////////////////////////////////////////////////////////
/**
* Make a ColumnDescriptor out of a SYSCOLUMNS row
*
* @param row a SYSCOLUMNS row
* @param parentTupleDescriptor The UniqueTupleDescriptor for the object that is tied
* to this column
* @param dd dataDictionary
*
* @return a column descriptor equivalent to a SYSCOLUMNS row
*
* @exception StandardException thrown on failure
*/
public TupleDescriptor buildDescriptor(ExecRow row, TupleDescriptor parentTupleDescriptor, DataDictionary dd) throws StandardException {
if (SanityManager.DEBUG) {
int expectedCols = dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_14, null) ? SYSCOLUMNS_COLUMN_COUNT : (SYSCOLUMNS_COLUMN_COUNT - 1);
SanityManager.ASSERT(row.nColumns() == expectedCols, "Wrong number of columns for a SYSCOLUMNS row");
}
int columnNumber;
String columnName;
String defaultID;
DefaultInfoImpl defaultInfo = null;
ColumnDescriptor colDesc;
DataValueDescriptor defaultValue = null;
UUID defaultUUID = null;
UUID uuid = null;
UUIDFactory uuidFactory = getUUIDFactory();
long autoincStart, autoincInc, autoincValue;
boolean autoincCycle = false;
DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
/*
** We're going to be getting the UUID for this sucka
** so make sure it is a UniqueTupleDescriptor.
*/
if (parentTupleDescriptor != null) {
if (SanityManager.DEBUG) {
if (!(parentTupleDescriptor instanceof UniqueTupleDescriptor)) {
SanityManager.THROWASSERT(parentTupleDescriptor.getClass().getName() + " not instanceof UniqueTupleDescriptor");
}
}
uuid = ((UniqueTupleDescriptor) parentTupleDescriptor).getUUID();
} else {
/* 1st column is REFERENCEID (char(36)) */
uuid = uuidFactory.recreateUUID(row.getColumn(SYSCOLUMNS_REFERENCEID).getString());
}
/* NOTE: We get columns 5 and 6 next in order to work around
* a 1.3.0 HotSpot bug. (#4361550)
*/
// 5th column is COLUMNDEFAULT (serialiazable)
Object object = row.getColumn(SYSCOLUMNS_COLUMNDEFAULT).getObject();
if (object instanceof DataValueDescriptor) {
defaultValue = (DataValueDescriptor) object;
} else if (object instanceof DefaultInfoImpl) {
defaultInfo = (DefaultInfoImpl) object;
defaultValue = defaultInfo.getDefaultValue();
}
/* 6th column is DEFAULTID (char(36)) */
defaultID = row.getColumn(SYSCOLUMNS_COLUMNDEFAULTID).getString();
if (defaultID != null) {
defaultUUID = uuidFactory.recreateUUID(defaultID);
}
/* 2nd column is COLUMNNAME (varchar(128)) */
columnName = row.getColumn(SYSCOLUMNS_COLUMNNAME).getString();
/* 3rd column is COLUMNNUMBER (int) */
columnNumber = row.getColumn(SYSCOLUMNS_COLUMNNUMBER).getInt();
/* 4th column is COLUMNDATATYPE */
/*
** What is stored in the column is a TypeDescriptorImpl, which
** points to a BaseTypeIdImpl. These are simple types that are
** intended to be movable to the client, so they don't have
** the entire implementation. We need to wrap them in DataTypeServices
** and TypeId objects that contain the full implementations for
** language processing.
*/
TypeDescriptor catalogType = (TypeDescriptor) row.getColumn(SYSCOLUMNS_COLUMNDATATYPE).getObject();
DataTypeDescriptor dataTypeServices = DataTypeDescriptor.getType(catalogType);
/* 7th column is AUTOINCREMENTVALUE (long) */
autoincValue = row.getColumn(SYSCOLUMNS_AUTOINCREMENTVALUE).getLong();
/* 8th column is AUTOINCREMENTSTART (long) */
autoincStart = row.getColumn(SYSCOLUMNS_AUTOINCREMENTSTART).getLong();
/* 9th column is AUTOINCREMENTINC (long) */
autoincInc = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC).getLong();
if (row.nColumns() >= 10) {
DataValueDescriptor col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINCCYCLE);
autoincCycle = col.getBoolean();
}
DataValueDescriptor col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTSTART);
autoincStart = col.getLong();
col = row.getColumn(SYSCOLUMNS_AUTOINCREMENTINC);
autoincInc = col.getLong();
// Hard upgraded tables <=10.13 come with a false autoincCyle before they are first
// explicitly set with cycle or no cycle command.
colDesc = new ColumnDescriptor(columnName, columnNumber, dataTypeServices, defaultValue, defaultInfo, uuid, defaultUUID, autoincStart, autoincInc, autoincValue, autoincCycle);
return colDesc;
}
Aggregations