in database-jones/Adapter/common/DBTableHandler.js [418:614]
function DBTableHandler(dbtable, tablemapping, ctor) {
var i, // an iterator
field, // a field
col, // a column
id, // a column id number
index, // a DBIndex
columnNames, // array of the mapped column names
foreignKey, // foreign key object from dbTable
priv; // our DBTableHandlerPrivate
var dbTableHandler = this;
var invalidateCallback;
stats.constructor_calls++;
if(! ( dbtable && dbtable.columns)) {
stats.return_null++;
return null;
}
if(stats.created[dbtable.name] === undefined) {
stats.created[dbtable.name] = 1;
} else {
stats.created[dbtable.name]++;
}
/* Default properties */
priv = new DBTableHandlerPrivate(this, dbtable.columns.length);
this._private = priv;
this.dbTable = dbtable;
this.ValueObject = null;
this.errorMessages = "";
this.isValid = true;
this.autoIncFieldName = null;
this.autoIncColumnNumber = null;
this.numberOfLobColumns = 0;
this.newObjectConstructor = ctor;
this.dbIndexHandlers = [];
this.foreignKeyMap = {};
this.sparseContainer = null;
this.is1to1 = true;
this.relationshipFields = [];
if(tablemapping) {
if(tablemapping.isValid()) {
stats.explicit_mappings++;
} else {
this.errorMessages = tablemapping.error;
this.isValid = false;
return;
}
}
else { // Create a default mapping
stats.default_mappings++;
tablemapping = new TableMapping(this.dbTable.name);
tablemapping.database = this.dbTable.database;
}
/* Make a copy of the mapping and store it as the "resolved" mapping */
this.resolvedMapping = new TableMapping(tablemapping);
this.resolvedMapping.mapAllColumns = false; // all fields will be present
/* Build an array of column names. This will establish column order. */
columnNames = [];
function addColumnName(name) {
if(name && getColumnByName(dbtable, name) && columnNames.indexOf(name) === -1) {
columnNames.push(name);
}
}
if(tablemapping.mapAllColumns) { // Use all columns from dictionary
for(i = 0 ; i < dbtable.columns.length ; i++) {
columnNames.push(dbtable.columns[i].name);
}
} else { // Use all mapped columns plus any sparse container column
for(i = 0 ; i < tablemapping.fields.length ; i++) {
field = tablemapping.fields[i];
if(field.persistent) {
if(field.toManyColumns) {
field.toManyColumns.forEach(addColumnName);
} else {
addColumnName(field.columnName || field.fieldName);
}
}
}
addColumnName(dbtable.sparseContainer);
}
udebug.log("DBTableHandler columns", columnNames);
/* Build the array of columns.
*/
for(id = 0 ; id < columnNames.length ; id++) {
priv.addColumn(getColumnByName(dbtable, columnNames[id]),
tablemapping.columnConverterMap);
}
/* Build the array of mapped fields. */
/* Start with persistent fields from the TableMapping */
for(i = 0; i < this.resolvedMapping.fields.length ; i++) {
field = this.resolvedMapping.fields[i];
if(field.persistent) {
priv.addField(field);
}
}
/* Add a default field mapping for any yet-unmapped columns */
if(tablemapping.mapAllColumns) {
for(i = 0 ; i < priv.columns.length ; i++) {
if(! priv.columns[i].isMapped) {
field = priv.columnMetadata[i].name;
if(priv.fields[field]) {
priv.columns[i].setUnmappable();
} else {
this.resolvedMapping.mapField({"fieldName":field,"columnName":field});
priv.addField(this.resolvedMapping.getFieldMapping(field));
}
}
}
}
/* Iterate over all columns.
* Set internal pointers for notable columns.
*/
for(id = 0 ; id < columnNames.length ; id++) {
col = columnNames[id];
if(this.resolvedMapping.sparseContainer &&
this.resolvedMapping.sparseContainer.columnName === col) {
this.sparseContainer = col;
priv.setSparseColumn(id, this.resolvedMapping);
} else if(dbtable.sparseContainer === col && ! priv.columns[id].isMapped) {
this.resolvedMapping.mapSparseFields(col);
this.sparseContainer = col;
priv.setSparseColumn(id, this.resolvedMapping);
}
if(priv.columnMetadata[id].isAutoincrement) {
this.autoIncColumnNumber = i;
this.autoIncFieldName = priv.columns[id].fieldNames[0];
}
if(priv.columnMetadata[id].isLob) {
this.numberOfLobColumns++;
}
if(priv.columns[id].isShared || priv.columns[id].isPartial) {
this.is1to1 = false;
}
}
/* Iterate over all field mappings.
* Build the array of relationshipFields.
* For all persistent fields, resolve field.columnName.
*/
for(i = 0 ; i < this.resolvedMapping.fields.length ; i++) {
field = this.resolvedMapping.fields[i];
if(field.relationship) {
this.relationshipFields.push(field);
} else if(field.persistent) {
if(field.columnName) {
if(! this._private.getColumnMappingByName(field.columnName)) {
this.resolvedMapping.error += "Column " + field.columnName + " does not exist\n";
}
} else if(! field.toManyColumns) {
if(this._private.getColumnMappingByName(field.fieldName)) {
field.columnName = field.fieldName;
} else if(this.sparseContainer) {
field.columnName = this.sparseContainer;
} else {
this.resolvedMapping.error += "No column mapped for field " + field.fieldName + "\n";
}
}
}
if(field.columnName !== this.sparseContainer) {
this.resolvedMapping.fieldIsNotSparse(field.fieldName);
}
}
// build a dbIndexHandler for each usable dbIndex
for (i = 0; i < this.dbTable.indexes.length; ++i) {
index = this.dbTable.indexes[i];
if(this.hasColumnsFromTable(index.columnNumbers)) {
this.dbIndexHandlers.push(new DBIndexHandler(this, index));
}
}
// build foreign key map
for (i = 0; i < this.dbTable.foreignKeys.length; ++i) {
foreignKey = this.dbTable.foreignKeys[i];
this.foreignKeyMap[foreignKey.name] = foreignKey;
}
// set the invalidate callback if this db table handler is valid
if (dbTableHandler.isValid) {
invalidateCallback = function() {
udebug.log('invalidateCallback called for dbTableHandler',
ctor?'for constructor '+ctor.name:'default', 'for table', dbtable.database+'.'+dbtable.name);
dbTableHandler.isValid = false;
};
dbtable.registerInvalidateCallback(invalidateCallback);
}
udebug.log("Constructor completed -- ", this);
}