Skip to content

Commit e6aee63

Browse files
author
Craig L Russell
committed
Improve usability of connect, openSession and createTable
allow the mappings parameter to be optional with a callback allow the mappings parameter to be a TableMapping for createTable, generate SPARSE_FIELDS column If a user specifies a TableMapping on connect, the mapping is cached in the session factory and used for functions taking a String tableName. If a user specifies a TableMapping on openSession, the mapping is cached in the session and used for functions taking a String tableName. If a user specifies a TableMapping on a specific function (e.g. find, persist), the mapping is used only for that call and is not cached. SessionFactory.js if there is only one parameter, and it a function (not a mapped constructor) then assume it is a callback allow openSession to cache a session-specific table handler allow openSession to use a TableMapping as a mapping parameter Session.js add property tableHandlers to cache session-specific table handlers SQLBuilder.js if there is a SPARSE_FIELDS definition, create its column with createTable mappings add tests for improved mappings parameter support ConnectTest.js jones.connect with callback but no table mapping jones.connect with table mapping and verify table handler is cached in session factory jones.openSession with table mapping and verify table handler is cached in session sessionFactory.openSession with table mapping and verify table handler is cached in sessionFactory jones.openSession with callback but no table mappings sessionFactory.openSession with callback but no table mappings utilities.js rework fail_openSession for readability TableMapping.js add “return this” to a couple of functions to allow function chaining UserContext.js create new resolveTableMappings function that can be called from SessionFactory.openSession reorganize getTableHandler to allow table mappings to be used jones.js allow openSession to cache a session-specific table handler allow openSession to use a TableMapping as a mapping parameter
1 parent c18ec98 commit e6aee63

File tree

12 files changed

+717
-141
lines changed

12 files changed

+717
-141
lines changed

database-jones/Adapter/api/Session.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2012, 2015 Oracle and/or its affiliates. All rights
2+
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights
33
reserved.
44
55
This program is free software; you can redistribute it and/or
@@ -33,6 +33,7 @@ function Session(index, sessionFactory, dbSession) {
3333
this.closed = false;
3434
this.tx = new transaction.Transaction(this);
3535
this.projections = {};
36+
this.tableHandlers = {};
3637
}
3738

3839

database-jones/Adapter/api/SessionFactory.js

+94-19
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,46 @@ SessionFactory.prototype.inspect = function() {
6565
numberOfMappings + " mappings, " + numberOfSessions + " sessions.]]\n";
6666
};
6767

68-
//openSession(Function(Object error, Session session, ...) callback, ...);
69-
// Open new session or get one from a pool
70-
SessionFactory.prototype.openSession = function() {
71-
var context = new UserContext.UserContext(arguments, 2, 2, null, this);
68+
/** Determine if a parameter is a possible mappings. Possible mappings include null, undefined,
69+
* array, string, mapped constructor function, or TableMapping object.
70+
* @param fn possible mapping
71+
* @return true if the parameter may be a mappings
72+
*/
73+
function isMappings(fn) {
74+
if (fn === null) {return true;}
75+
if (fn === undefined) {return true;}
76+
if (Array.isArray(fn)) {return true;}
77+
if (typeof fn === 'string') {return true;}
78+
if (typeof fn === 'function') {
79+
if (fn.prototype.jones) {
80+
return true;
81+
}
82+
}
83+
if (typeof fn === 'object') {
84+
if (fn.constructor && fn.constructor.name === 'TableMapping') {
85+
return true;
86+
}
87+
}
88+
return false;
89+
}
90+
91+
/** openSession(Object mappings, Function(Object error, Session session, ...) callback, ...);
92+
* Open new session or get one from a pool.
93+
* @param mappings a table name, mapped constructor, or array of them
94+
* @return promise
95+
*/
96+
SessionFactory.prototype.openSession = function(mappings, callback) {
97+
// if only one argument, it might be a mappings or a callback
98+
var args = arguments;
99+
if (arguments.length === 1 && !isMappings(mappings)) {
100+
args[1] = mappings;
101+
args[0] = null;
102+
}
103+
var context = new UserContext.UserContext(args, 2, 2, null, this);
104+
context.cacheTableHandlerInSession = true;
105+
context.user_mappings = args[0];
72106
// delegate to context for execution
107+
if(udebug.is_detail()) {udebug.log_detail('SessionFactory.openSession with mappings ', context.user_mappings);}
73108
return context.openSession();
74109
};
75110

@@ -301,6 +336,8 @@ function createTableInternal(tableMapping, sessionFactory, session, callback) {
301336
* otherwise, error.
302337
* - Domain Object:
303338
* get constructor from domain object prototype. goto constructor algorithm.
339+
* - TableMapping:
340+
* get table name from mapping. get metadata for table. get DBTableHandler for mapping.
304341
*/
305342
SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTableNameOrConstructor, session, onTableHandler) {
306343
var sessionFactory = this;
@@ -339,25 +376,40 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
339376
tableMetadata.registerInvalidateCallback(invalidateCallback);
340377
}
341378
// we have the table metadata; now create the default table handler if not cached
342-
if (sessionFactory.tableHandlers[tableKey] === undefined) {
379+
// do not use the existing cached table handler if processing a new table mapping
380+
if (userContext.tableIndicatorType === 'tablemapping' ||
381+
(session.tableHandlers[tableKey] === undefined &&
382+
sessionFactory.tableHandlers[tableKey] === undefined)) {
343383
if(udebug.is_detail()) { udebug.log_detail('creating the default table handler for ', tableKey); }
344384
dbTableHandler = new DBTableHandler(tableMetadata, tableMapping);
345385
if (dbTableHandler.isValid) {
346-
// cache the table handler for the table name case
347-
udebug.log('caching the default table handler in the session factory for', tableKey);
348-
sessionFactory.tableHandlers[tableKey] = dbTableHandler;
349-
invalidateCallback = function() {
350-
// use " = undefined" here to keep tableKey in the tableHandlers object
351-
udebug.log('invalidateCallback called for session factory default table handlers for', tableKey);
352-
sessionFactory.tableHandlers[tableKey] = undefined;
353-
};
354-
tableMetadata.registerInvalidateCallback(invalidateCallback);
386+
// cache the table handler for the table name and table mapping cases
387+
if (userContext.cacheTableHandlerInSessionFactory) {
388+
udebug.log('caching the default table handler in the session factory for', tableKey);
389+
sessionFactory.tableHandlers[tableKey] = dbTableHandler;
390+
invalidateCallback = function() {
391+
// use " = undefined" here to keep tableKey in the tableHandlers object
392+
udebug.log('invalidateCallback called for session factory default table handlers for', tableKey);
393+
sessionFactory.tableHandlers[tableKey] = undefined;
394+
};
395+
tableMetadata.registerInvalidateCallback(invalidateCallback);
396+
}
397+
if (userContext.cacheTableHandlerInSession) {
398+
udebug.log('caching the default table handler in the session for', tableKey);
399+
session.tableHandlers[tableKey] = dbTableHandler;
400+
invalidateCallback = function() {
401+
// use " = undefined" here to keep tableKey in the tableHandlers object
402+
udebug.log('invalidateCallback called for session default table handlers for', tableKey);
403+
session.tableHandlers[tableKey] = undefined;
404+
};
405+
tableMetadata.registerInvalidateCallback(invalidateCallback);
406+
}
355407
} else {
356408
err = new Error(dbTableHandler.errorMessages);
357409
udebug.log('onExistingTableMetadata got invalid dbTableHandler', dbTableHandler.errorMessages);
358410
}
359411
} else {
360-
dbTableHandler = sessionFactory.tableHandlers[tableKey];
412+
dbTableHandler = session.tableHandlers[tableKey] || sessionFactory.tableHandlers[tableKey];
361413
udebug.log('onExistingTableMetadata got default dbTableHandler but' +
362414
' someone else put it in the cache first for ', tableKey);
363415
}
@@ -413,8 +465,9 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
413465

414466
function onTableMetadata(err, tableMetadata) {
415467
if (err) {
468+
// get default tableMapping if not already specified
469+
tableMapping = tableMapping || sessionFactory.tableMappings[tableSpecification.qualifiedTableName];
416470
// create the schema if it does not already exist and user flag allows it
417-
tableMapping = sessionFactory.tableMappings[tableSpecification.qualifiedTableName];
418471
if (!tableMapping && session.allowCreateUnmappedTable) {
419472
udebug.log('getTableHandler.onTableMetadata creating table for',tableSpecification.qualifiedTableName);
420473
// create the table from the default table mapping
@@ -456,8 +509,8 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
456509

457510
tableSpecification = getTableSpecification(sessionFactory.properties.database, domainObjectTableNameOrConstructor);
458511
tableKey = tableSpecification.qualifiedTableName;
459-
// look up in table name to default table handler hash
460-
dbTableHandler = sessionFactory.tableHandlers[tableKey];
512+
// look up in table name to default table handler hash in session and session factory
513+
dbTableHandler = session.tableHandlers[tableKey] || sessionFactory.tableHandlers[tableKey];
461514
if (dbTableHandler === undefined) {
462515
if(udebug.is_detail()) {
463516
udebug.log_detail('tableIndicatorTypeString for table name did not find cached dbTableHandler for table', tableKey);
@@ -474,6 +527,21 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
474527
}
475528
}
476529

530+
// handle the case where the parameter is the user-defined TableMapping
531+
function tableIndicatorTypeTableMapping() {
532+
if(udebug.is_detail()) { udebug.log_detail('tableIndicatorTypeTableMapping for', domainObjectTableNameOrConstructor); }
533+
tableMapping = domainObjectTableNameOrConstructor;
534+
if (tableMapping.database) {
535+
databaseDotTable = tableMapping.database + '.' + tableMapping.table;
536+
} else {
537+
databaseDotTable = tableMapping.table;
538+
}
539+
tableSpecification = getTableSpecification(sessionFactory.properties.database, databaseDotTable);
540+
tableKey = tableSpecification.qualifiedTableName;
541+
// create a new table handler for the table with the user-defined TableHandler
542+
createTableHandler(tableSpecification, session.dbSession, onTableHandler);
543+
}
544+
477545
function tableIndicatorTypeFunction() {
478546
constructorJones = userContext.handlerCtor.prototype.jones;
479547
// parameter is a constructor; it must have been annotated already
@@ -509,6 +577,10 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
509577

510578
// start of getTableHandler
511579
tableIndicatorType = typeof domainObjectTableNameOrConstructor;
580+
if (tableIndicatorType === 'object' && domainObjectTableNameOrConstructor.constructor.name === 'TableMapping') {
581+
tableIndicatorType = 'tablemapping';
582+
}
583+
userContext.tableIndicatorType = tableIndicatorType;
512584
if (tableIndicatorType === 'string') {
513585
userContext.handlerCtor = undefined;
514586
tableIndicatorTypeString();
@@ -518,8 +590,11 @@ SessionFactory.prototype.getTableHandler = function(userContext, domainObjectTab
518590
} else if (tableIndicatorType === 'object') {
519591
userContext.handlerCtor = domainObjectTableNameOrConstructor.constructor;
520592
tableIndicatorTypeFunction();
593+
} else if (tableIndicatorType === 'tablemapping') {
594+
userContext.handlerCtor = undefined;
595+
tableIndicatorTypeTableMapping();
521596
} else {
522-
err = new Error('User error: parameter must be a domain object, string, or constructor function.');
597+
err = new Error('User error: parameter must be a domain object, string, TableMapping or constructor function.');
523598
onTableHandler(err, null);
524599
}
525600
};

database-jones/Adapter/api/TableMapping.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2015, Oracle and/or its affiliates. All rights
2+
Copyright (c) 2015, 2106, Oracle and/or its affiliates. All rights
33
reserved.
44
55
This program is free software; you can redistribute it and/or
@@ -537,6 +537,7 @@ TableMapping.prototype.fieldIsNotSparse = function(fieldName) {
537537
if (this.excludedFieldNames.indexOf(fieldName) === -1) {
538538
this.excludedFieldNames.push(fieldName);
539539
}
540+
return this;
540541
};
541542

542543
/** excludeFields(fieldNames)
@@ -563,6 +564,7 @@ TableMapping.prototype.excludeFields = function() {
563564
fieldNames + '\"';
564565
}
565566
}
567+
return this;
566568
};
567569

568570

0 commit comments

Comments
 (0)