Open kaltinril opened 9 years ago
Can you give the code example that returns the error code? Which adapter are you using? What does your Employee constructor look like?
In this bit:
var mapping = new nosql.TableMapping('employees').applyToClass(Employee);
... note that applyToClass() returns your constructor, not the mapping. So that should work better as two lines:
var mapping = new nosql.TableMapping('employees');
mapping.applyToClass(Employee);
@CraigLRussell ,
We are using NDB, node.js, mysql-js (Obviously), mysql-cluster on Ubuntu.
All examples except "Example of standard 1 line syntax" fail. So we are able to run session.find, and we are able to run session.executeQuery, we are just not able to get it to work if we try to manually map columns and add a Converter for a column that has an ENUM.
Tonight after work I'll gather the complete code for a failure and post that here, including the definition for Employees.
@jdduncan ,
The line you are referring to works, that is the working example line.
@kaltinril,
I think the problem is in your openSession call where you pass mappings to validate. The documentation for the mappings parameter is:
The reason the first example works is that the result of applyToClass is, as JD says, the Constructor not the mapping. Passing the constructor to openSession works.
So instead of openSession(props, mapping...) try openSession(props, Employee...)
I think the parameter name "mappings" is a poor name for what it really requires, which is a table name or constructor function. I'm open to suggestions for changing the documentation to reflect what the parameter really is (and for a better error message). Perhaps validations? And if we detect that what was passed was actually a table mapping, return a message like "validations should only contain table names or constructors, not table mappings".
Note that a mapping cannot be validated by itself. A mapping can only be applied to a constructor function; the combination of constructor plus mapping is what is validated.
@CraigLRussell ,
It looks like there were multiple issues going on.
Thank you for taking the time to look at this. We have been banging our heads against the wall reading all documentation, reviewing tests, and reading examples. Your suggestions allowed us to create multiple tests and eventually lead to the following items, including one complete working example.
This happened because of the information on the Converter page which states to use a function and prototype:
function Converter() {}:
Converter.prototype = {
"toDB" : function(obj) { },
"fromDB" : function(val) { }
};
Using the function doesn't cause an error, however, the converter doesn't work and we see "\u0002" or "\u0001" instead of "M" or "F".
The correct syntax was to create an object:
var Converter = {
toDB : function(obj) { return obj},
fromDB : function(val) {
if (val === '\u0001')
return 'M';
else
return 'F';
}
};
In the documentation on the Complete documentation for top level API, connect and openSession both use the word "Mapping". As you've stated it is misleading.
If you are willing to update that information in the documentation that would help greatly. Our suggestion is to name it "constructor". Validations seems like it wouldn't be clear that the user needs to pass the Table Constructor in.
We tried reading the information on the TableMapping page and use that information to create a complete mapping in a single statement, however it is not working.
Complete example that does not work
var nosql = require('mysql-js');
var dbProperties = nosql.ConnectionProperties('ndb');
dbProperties.database = 'employees';
var Employee = function(id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
};
var Converter = {
toDB : function(obj) { return obj},
fromDB : function(val) {
if (val === '\u0001')
return 'M';
else
return 'F';
}
};
var mapping = new nosql.TableMapping({
table: 'employees',
mapAllColumns: true, //fails even if this line is commented out
//fails even when not an array
fields: [{
fieldName: 'gender',
columnName: 'gender',
converter: Converter
}]
});
mapping.applyToClass(Employee);
//check results of find
var onFind = function(err, result) {
console.log('onFind.');
if (err) {
console.log(err);
} else {
console.log('Found: ' + JSON.stringify(result));
}
};
var onSession = function(err, session) {
console.log('onSession.');
if (err) {
console.log('Error onSession.');
console.log(err);
process.exit(0);
} else {
// Find an employee
session.find(Employee, '418606', onFind); //Male
session.find(Employee, '410493', onFind); //Female
}
};
// connect to the database
nosql.openSession(dbProperties, Employee, onSession); //test with constructor
When we try this we get the following error:
Mismatch between number of mapped fields and columns for ]
The section under TableMapping for mapAllColumns says it should map everything but the column we put in fields.
See the excerpt below:
Create a default FieldMapping for all columns not listed in fields[]. Specifies that all columns, not explicitly mapped, should be given a default mapping to a field of the same name. @property mapAllColumns @type Boolean @default true
-- DDL/DML for below test
CREATE DATABASE IF NOT EXISTS employees
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
CREATE TABLE employees (
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender ENUM ('M','F') NOT NULL,
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
) engine=ndb;
INSERT INTO employees (emp_no,birth_date,first_name,last_name,gender,hire_date) VALUES
(410493, '1960-06-01','Lalit','Nyanchama','F','1990-12-22'),
(418606, '1965-01-11','Michael','Otillio','M','1994-0105');
COMMIT;
The following Javascript is our end result that works without external files being imported with require().
var nosql = require('mysql-js');
var dbProperties = nosql.ConnectionProperties('ndb');
dbProperties.database = 'employees';
var Employee = function(id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
};
var Converter = {
toDB : function(obj) { return obj},
fromDB : function(val) {
if (val === '\u0001')
return 'M';
else
return 'F';
}
};
var mapping = new nosql.TableMapping('employees');
mapping.mapField('gender','gender', Converter, true);
mapping.applyToClass(Employee);
//check results of find
var onFind = function(err, result) {
console.log('onFind.');
if (err) {
console.log(err);
} else {
console.log('Found: ' + JSON.stringify(result));
}
};
var onSession = function(err, session) {
console.log('onSession.');
if (err) {
console.log('Error onSession.');
console.log(err);
process.exit(0);
} else {
// Find an employee
session.find(Employee, '418606', onFind); //Male
session.find(Employee, '410493', onFind); //Female
}
};
// connect to the database
nosql.openSession(dbProperties, Employee, onSession); //test with constructor
CC the other person working with me: @frigidplanet
@kaltinril @frigidplanet Here's a note, and it reveals a bit of our weakness at making mysql and ndb appear the same. With the mysql adapter you would not need a converter for ENUM at all. But with the NDB adapter your toDB() also needs to change the string to a number. NDBAPI is completely ignorant about the ENUM column; it sees it as (I think) just a TINYINT.
@jdduncan, Thank you for the feedback , we do understand that. We were only testing the read (Select) [find/executeQuery] portion, and have not yet planned on learning and testing the write (Insert) [persist] portion.
NOTE: the toDB() isn't related to any of the issues we faced.
@CraigLRussell This issue has brought up some possibilities for documentation improvements. If you let me know when those are ready I'll push them here to github ASAP.
@kaltinril @firgidplanet
I'd like to get a trace of this program. I cannot get the strange error message.
Mismatch between number of mapped fields and columns for ]
The message comes from DBTableHandler:
this.appendErrorMessage('Mismatch between number of mapped fields and columns for ' + ctor.prototype.constructor.name);
So it claims that the constructor is named ']' which doesn't make sense.
We should add a section to readme.md explaining how to get trace information.
The example code is wrong: var mapping = new nosql.TableMapping("webapp.users"); nosql.connect(properties, mapping, onConnectedCallback);
It should be: var mapping = new nosql.TableMapping("webapp.users"); nosql.connect(properties, "webapp.users", onConnectedCallback);
Hi,
I added this line towards the top of your test code (but under the require('mysql-js')):
unified_debug.level_debug();
Then I ran the script, and got an error from onSession. Towards the end of the output I see this line:
DBDictionaryImpl.cpp listIndexes() returned -1
This seems to indicate a bug in our code. I will start looking at it, but I would be interested if you see the same thing.
On further examination, I saw that last error because I had not actually managed to create the employees table :)
That unified_debug line might still help track down the problem, though. Here's what I get when I run the test code now:
$ node test.js
Connected to cluster as node id: 4
onSession.
onFind.
Found: {"hire_date":"0-00-00","gender":"M","last_name":"Otillio","first_name":"Michael","birth_date":"1965-01-11","emp_no":418606}
onFind.
Found: {"hire_date":"1990-12-22","gender":"F","last_name":"Nyanchama","first_name":"Lalit","birth_date":"1960-06-01","emp_no":410493}
Sorry for the late reply.
Here is the output from the failure with that added debug line.
Additionaly here is the _ndb_mgm -e show_ command output:
~/mysqlscripts$ ndb_mgm -e show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)] 2 node(s)
id=1 @127.0.0.1 (mysql-5.6.22 ndb-7.3.8, Nodegroup: 0, *)
id=2 @127.0.0.1 (mysql-5.6.22 ndb-7.3.8, Nodegroup: 0)
[ndb_mgmd(MGM)] 1 node(s)
id=49 @127.0.0.1 (mysql-5.6.22 ndb-7.3.8)
[mysqld(API)] 2 node(s)
id=50 @127.0.0.1 (mysql-5.6.22 ndb-7.3.8)
id=51 (not connected, accepting connect from localhost)
prompt$ node test8.js
mynode.js ConnectionProperties [default for ndb]
ndb_service_provider.js getFactoryKey
UserContext.js connect connection does not exist; creating factory for ndb://localhost:1186 database employees
ndb_service_provider.js connect
JsWrapper.h Constructor wrapping Ndb_cluster_connection: 0x15565a0
NdbConnection.js connect() onConnected rval = 0
Connected to cluster as node id: 51
NdbConnectionPool.js DBConnectionPool.connect onConnected
NdbConnectionPool.js prefetchSession
UserContext.js dbConnectionPool created for ndb://localhost:1186 database employees
UserContext.js connect createFactory creating factory for ndb://localhost:1186 database employees
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f2ae00008c0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f2ad40008c0
UserContext.js UserContext.getTableHandler did not find cached tableHandler for constructor. function (id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
}
UserContext.js TableHandlerFactory.createTableHandler for employees employees
QueuedAsyncCall.js enqueue # 1 getTableMetadata - run immediate
DBDictionaryImpl.cpp GetTableCall::run() [employees.employees]
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f2af4002fe0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f2ae0007a20
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f2ad4007a20
NdbConnectionPool.js prefetchSession adding to session pool.
DBDictionaryImpl.cpp per_table_ndb employees.employees 0x7f2ad8000bd0
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
DBDictionaryImpl.cpp GetTableCall::doAsyncCallback: return_val 0
JsWrapper.h Constructor wrapping const NdbDictionary::Table: 0x7f2ad80169b0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad8016d50
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad8017130
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad80171d0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad8016e60
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad802a270
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f2ad802a310
DBDictionaryImpl.cpp Creating Primary Key Record
JsWrapper.h Constructor wrapping Record: 0x1515100
JsWrapper.h Constructor wrapping const NdbDictionary::Index: 0x7f2ad8004c40
DBDictionaryImpl.cpp Creating Index Record (PRIMARY)
JsWrapper.h Constructor wrapping Record: 0x15315e0
DBDictionaryImpl.cpp Creating Table Record
JsWrapper.h Constructor wrapping Record: 0x1518220
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
JsWrapper.h Constructor wrapping Ndb: 0x7f2ad8000bd0
NdbAutoIncrement.js New cache for table employees
NdbConnectionPool.js GroupCallback for employees.employees with 1 user callbacks
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js new completed
onSession.
Error onSession.
[Error:
Error:
Mismatch between number of mapped fields and columns for ]
It looks like we have code in DBTableHandler that assumes all of your foreign keys have been mapped into the application.
@kaltinril @firgidplanet One suggestion to make debugging easier: Don't use anonymous domain object constructors. Instead of: var Employee = function(id, ...
Use this: function Employee(id, ...
The difference is subtle but by using named constructor functions, our error messages will have more context for you.
function Employee(){} undefined Employee.name 'Employee' var x = function() {} undefined x.name ''
What happens if you simply comment out the check that produces this error message? It is at lines 255-257 of Adapter/impl/common/DBTableHandler.js.
@CraigLRussell ,
Here is the test with function Employee(id,... instead.
node test8.js
mynode.js ConnectionProperties [default for ndb]
ndb_service_provider.js getFactoryKey
UserContext.js connect connection does not exist; creating factory for ndb://localhost:1186 database employees
ndb_service_provider.js connect
JsWrapper.h Constructor wrapping Ndb_cluster_connection: 0x2160d40
NdbConnection.js connect() onConnected rval = 0
Connected to cluster as node id: 51
NdbConnectionPool.js DBConnectionPool.connect onConnected
NdbConnectionPool.js prefetchSession
UserContext.js dbConnectionPool created for ndb://localhost:1186 database employees
UserContext.js connect createFactory creating factory for ndb://localhost:1186 database employees
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7fb1bc0008c0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7fb1b00008c0
UserContext.js UserContext.getTableHandler did not find cached tableHandler for constructor. function Employee(id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
}
UserContext.js TableHandlerFactory.createTableHandler for employees employees
QueuedAsyncCall.js enqueue # 1 getTableMetadata - run immediate
DBDictionaryImpl.cpp GetTableCall::run() [employees.employees]
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7fb1d0002fe0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7fb1bc007a20
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7fb1b0007a20
NdbConnectionPool.js prefetchSession adding to session pool.
DBDictionaryImpl.cpp per_table_ndb employees.employees 0x7fb1b4000bd0
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
DBDictionaryImpl.cpp GetTableCall::doAsyncCallback: return_val 0
JsWrapper.h Constructor wrapping const NdbDictionary::Table: 0x7fb1b40169b0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b4016d50
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b4017130
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b40171d0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b4016e60
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b402a270
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7fb1b402a310
DBDictionaryImpl.cpp Creating Primary Key Record
JsWrapper.h Constructor wrapping Record: 0x215f100
JsWrapper.h Constructor wrapping const NdbDictionary::Index: 0x7fb1b4004c40
DBDictionaryImpl.cpp Creating Index Record (PRIMARY)
JsWrapper.h Constructor wrapping Record: 0x217b5e0
DBDictionaryImpl.cpp Creating Table Record
JsWrapper.h Constructor wrapping Record: 0x2162220
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
JsWrapper.h Constructor wrapping Ndb: 0x7fb1b4000bd0
NdbAutoIncrement.js New cache for table employees
NdbConnectionPool.js GroupCallback for employees.employees with 1 user callbacks
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js new completed
onSession.
Error onSession.
[Error:
Error:
Mismatch between number of mapped fields and columns for Employee]
@jdduncan,
Mine shows line 251-253.
251 if (nMappedFields !== this.fieldNumberToColumnMap.length + this.relationshipFields.length) {
252 this.appendErrorMessage('Mismatch between number of mapped fields and columns for ' + ctor.prototype.constructor.name);
253 }
When I try to run my test after editing this file (And even putting the original file back), I get the following error. Do I need to compile the code or run some command after editing the file?
EDIT Sorry, this was my own issue, I moved a folder and forgot to update the LD_LIBRARY_PATH.
removed.... as was my own issue and not related to this.
I had my library linked to an old install attempt, after correcting my library path, here is the output with the check commented out:
sudo vi /etc/ld.so.conf.d/randomLibs.conf
sudo ldconfig -v
node test8.js
mynode.js ConnectionProperties [default for ndb]
ndb_service_provider.js getFactoryKey
UserContext.js connect connection does not exist; creating factory for ndb://localhost:1186 database employees
ndb_service_provider.js connect
JsWrapper.h Constructor wrapping Ndb_cluster_connection: 0x1a67d40
NdbConnection.js connect() onConnected rval = 0
Connected to cluster as node id: 51
NdbConnectionPool.js DBConnectionPool.connect onConnected
NdbConnectionPool.js prefetchSession
UserContext.js dbConnectionPool created for ndb://localhost:1186 database employees
UserContext.js connect createFactory creating factory for ndb://localhost:1186 database employees
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f6ca40008c0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f6c980008c0
UserContext.js UserContext.getTableHandler did not find cached tableHandler for constructor. function Employee(id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
}
UserContext.js TableHandlerFactory.createTableHandler for employees employees
QueuedAsyncCall.js enqueue # 1 getTableMetadata - run immediate
DBDictionaryImpl.cpp GetTableCall::run() [employees.employees]
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f6cb8003030
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f6ca4007a20
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f6c98007a20
NdbConnectionPool.js prefetchSession adding to session pool.
DBDictionaryImpl.cpp per_table_ndb employees.employees 0x7f6c9c000bd0
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
DBDictionaryImpl.cpp GetTableCall::doAsyncCallback: return_val 0
JsWrapper.h Constructor wrapping const NdbDictionary::Table: 0x7f6c9c0169b0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c016d50
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c017130
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c0171d0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c016e60
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c02a270
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f6c9c02a310
DBDictionaryImpl.cpp Creating Primary Key Record
JsWrapper.h Constructor wrapping Record: 0x1a66100
JsWrapper.h Constructor wrapping const NdbDictionary::Index: 0x7f6c9c004c40
DBDictionaryImpl.cpp Creating Index Record (PRIMARY)
JsWrapper.h Constructor wrapping Record: 0x1a825e0
DBDictionaryImpl.cpp Creating Table Record
JsWrapper.h Constructor wrapping Record: 0x1a69220
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
JsWrapper.h Constructor wrapping Ndb: 0x7f6c9c000bd0
NdbAutoIncrement.js New cache for table employees
NdbConnectionPool.js GroupCallback for employees.employees with 1 user callbacks
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js new completed
onSession.
DBTableHandler.js getIndexHandler
DBTableHandler.js chooseIndex
NdbTransactionHandler.js NEW (tx1)
NdbSession.js buildReadOperation
DBDictionaryImpl.cpp Enter: getRecordForMapping - line 788
JsWrapper.h Constructor wrapping Record: 0x1a6e3b0
DBDictionaryImpl.cpp Leave: getRecordForMapping
ValueObject.cpp Enter: getValueObjectConstructor - line 154
JsWrapper.h Constructor wrapping ColumnHandlerSet: 0x1aa57a0
ValueObject.cpp Leave: getValueObjectConstructor
NdbTransactionHandler.js Execute -- AutoCommit (tx1)
NdbTransactionHandler.js internal execute
NdbSession.js seizeTransactionContext immediate 1
DBSessionImpl.cpp FreeList: (nil), nContexts: 0, maxNdbTransactions: 4
JsWrapper.h Constructor wrapping DBTransactionContext: 0x1a6a940
JsWrapper.h Constructor wrapping DBOperationSet: 0x1aab170
NdbAutoIncrement.js New Handler 0 / 1
NdbTransactionHandler.js executeNonScan prepare 1 operations (tx1)
DBOperationHelper.cpp Non-VO read -- mask: 0 lobs: 0
DBOperationSet_wrapper.cpp DBOperationSet wrapper
JsWrapper.h Constructor wrapping DBOperationSet: 0x1a83d00
QueuedAsyncCall.js enqueue # 2 execute_commit - run immediate
NdbTransactionHandler.js run() (tx1) queue position: 0
DBTransactionContext.cpp START TRANSACTION [with hint] TC Node 2
DBOperationSet.cpp prepare read [ok]
DBTableHandler.js getIndexHandler
DBTableHandler.js chooseIndex
NdbTransactionHandler.js NEW (tx2)
NdbSession.js buildReadOperation
NdbTransactionHandler.js Execute -- AutoCommit (tx2)
NdbTransactionHandler.js internal execute
NdbSession.js seizeTransactionContext immediate 2
DBSessionImpl.cpp FreeList: (nil), nContexts: 1, maxNdbTransactions: 4
JsWrapper.h Constructor wrapping DBTransactionContext: 0x1a2f2c0
JsWrapper.h Constructor wrapping DBOperationSet: 0x1a9f4b0
NdbAutoIncrement.js New Handler 0 / 1
NdbTransactionHandler.js executeNonScan prepare 1 operations (tx2)
DBOperationHelper.cpp Non-VO read -- mask: 0 lobs: 0
DBOperationSet_wrapper.cpp DBOperationSet wrapper
JsWrapper.h Constructor wrapping DBOperationSet: 0x1a96590
QueuedAsyncCall.js enqueue # 3 execute_commit - position 1
NdbTransactionHandler.js run() (tx2) queue position: 1
DBTransactionContext.cpp EXECUTE sync : Commit 1 operation & close transaction => return: 0 error: 0
DBTransactionContext.cpp START TRANSACTION [with hint] TC Node 2
DBOperationSet.cpp prepare read [ok]
DBTransactionContext.cpp EXECUTE sync : Commit 1 operation & close transaction => return: 0 error: 0
NdbTransactionHandler.js onExecute commit (tx1) success: true
DBSessionImpl.cpp releaseTransaction status: closed
NdbOperation.js completeExecutedOps mode: 2 operations: 1
DBOperationSet_wrapper.cpp Enter: readBlobResults - line 161
DBOperationSet_wrapper.cpp Leave: readBlobResults
NdbOperation.js buildOperationResult
NdbOperation.js buildValueObject
NdbRecordObject.cpp ___Constructor___ [6 col, bufsz 103, 0 blobs]
JsWrapper.h Constructor wrapping NdbRecordObject: 0x1a92ec0
UserContext.js find.findOnResult
onFind.
Found: {"hire_date":"1994-01-05","gender":"\u0002","last_name":"Otillio","first_name":"Michaela","birth_date":"1965-01-11","emp_no":418606}
NdbOperation.js completeExecutedOps done
DBOperationSet.cpp DBOperationSet destructor [size 1]
JsWrapper.h Constructor wrapping DBOperationSet: (nil)
NdbTransactionHandler.js onExecute commit (tx2) success: true
DBSessionImpl.cpp releaseTransaction status: closed
NdbOperation.js completeExecutedOps mode: 2 operations: 1
DBOperationSet_wrapper.cpp Enter: readBlobResults - line 161
DBOperationSet_wrapper.cpp Leave: readBlobResults
NdbOperation.js buildOperationResult
NdbOperation.js buildValueObject
NdbRecordObject.cpp ___Constructor___ [6 col, bufsz 103, 0 blobs]
JsWrapper.h Constructor wrapping NdbRecordObject: 0x1a83d00
UserContext.js find.findOnResult
onFind.
Found: {"hire_date":"1990-12-22","gender":"\u0002","last_name":"Nyanchama","first_name":"Lalit","birth_date":"1960-06-01","emp_no":410493}
NdbOperation.js completeExecutedOps done
DBOperationSet.cpp DBOperationSet destructor [size 1]
JsWrapper.h Constructor wrapping DBOperationSet: (nil)
When I try to run my test after editing this file (And even putting the original file back), I get the following error. Do I need to compile the code or run some command after editing the file?
No, nothing like that should be required. I think this error is unrelated to editing.
The error here appears to be that LD_LIBRARY_PATH needs to be set to MySQL Cluster's lib directory, so that the JavaScript code can link with libndbclient.
By the way, the only difference I have noticed so far between my environment (where your code works) and yours (where it doesn't) is that your database has some foreign keys defined that reference the employees table.
Thanks again for all the support as we work through this.
Here is the full DDL for the database. I slightly modified it since it didn't work for NDB out of the box. The actual source is here.
Is it necessary to include the foreign key relationships in the mapping? I had assumed that if 'mapAllColumns: true' was included in the TableMapping then it would automatically include all the necessary mappings that weren't overridden via FieldMapping or meta.
-- Sample employee database
-- See changelog table for details
-- Copyright (C) 2007,2008, MySQL AB
--
-- Original data created by Fusheng Wang and Carlo Zaniolo
-- http://www.cs.aau.dk/TimeCenter/software.htm
-- http://www.cs.aau.dk/TimeCenter/Data/employeeTemporalDataSet.zip
--
-- Current schema by Giuseppe Maxia
-- Data conversion from XML to relational by Patrick Crews
--
-- This work is licensed under the
-- Creative Commons Attribution-Share Alike 3.0 Unported License.
-- To view a copy of this license, visit
-- http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to
-- Creative Commons, 171 Second Street, Suite 300, San Francisco,
-- California, 94105, USA.
--
-- DISCLAIMER
-- To the best of our knowledge, this data is fabricated, and
-- it does not correspond to real people.
-- Any similarity to existing people is purely coincidental.
--
DROP DATABASE IF EXISTS employees;
CREATE DATABASE IF NOT EXISTS employees
DEFAULT CHARACTER SET utf8
DEFAULT COLLATE utf8_general_ci;
USE employees;
DROP TABLE IF EXISTS dept_emp,
dept_manager,
titles,
salaries,
employees,
departments;
set default_storage_engine = ndb;
CREATE TABLE employees (
emp_no INT NOT NULL,
birth_date DATE NOT NULL,
first_name VARCHAR(14) NOT NULL,
last_name VARCHAR(16) NOT NULL,
gender ENUM ('M','F') NOT NULL,
hire_date DATE NOT NULL,
PRIMARY KEY (emp_no)
);
CREATE TABLE departments (
dept_no CHAR(4) NOT NULL,
dept_name VARCHAR(40) NOT NULL,
PRIMARY KEY (dept_no),
UNIQUE KEY (dept_name)
);
CREATE TABLE dept_manager (
dept_no CHAR(4) NOT NULL,
emp_no INT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
KEY (emp_no),
KEY (dept_no),
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES departments (dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no,dept_no)
);
CREATE TABLE dept_emp (
emp_no INT NOT NULL,
dept_no CHAR(4) NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
KEY (emp_no),
KEY (dept_no),
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
FOREIGN KEY (dept_no) REFERENCES departments (dept_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no,dept_no)
);
CREATE TABLE titles (
emp_no INT NOT NULL,
title VARCHAR(50) NOT NULL,
from_date DATE NOT NULL,
to_date DATE,
KEY (emp_no),
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no,title, from_date)
);
CREATE TABLE salaries (
emp_no INT NOT NULL,
salary INT NOT NULL,
from_date DATE NOT NULL,
to_date DATE NOT NULL,
KEY (emp_no),
FOREIGN KEY (emp_no) REFERENCES employees (emp_no) ON DELETE CASCADE,
PRIMARY KEY (emp_no, from_date)
);
@jdduncan , you are correct that error was my fault (The LD_LIBRARY_PATH one).
I've been unable to reproduce the error: Mismatch between number of mapped fields and columns for ]
But I've added some more code that should help isolate the problem if it still occurs. Once it's been pushed, can you try again?
@CraigLRussell , sure sounds good. Let us know which files to replace, and/or, if we need to just do a sudo apt-get upgrade.
I just pushed the latest changes up to github. This push includes: Converter, Mynode, and Tablemapping under API-documentation/ TableMapping.js and UserContext.js under Adapter/api/ DBTableHandler.js under Adapter/impl/common/
I'll try it again tonight when I get off work, but it didn't work for me.
~/nodejs$ node test8.js
/usr/lib/node_modules/mysql-js/Adapter/api/TableMapping.js:27
doc = require(path.join(mynode.fs.api_doc_dir, "TableMapping"));
^
ReferenceError: mynode is not defined
at Object.<anonymous> (/usr/lib/node_modules/mysql-js/Adapter/api/TableMapping.js:27:38)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/usr/lib/node_modules/mysql-js/Adapter/api/mynode.js:24:22)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
@jdduncan , @CraigLRussell ,
I went ahead and just copied everything from github, not just the files that you changed, and now it works and doesn't give the error, and converts the ENUM.
So I can only suspect or guess that the version we had, that is available "in the wild" and not on github, is older or not up to date. Or, my original copy of the updated files didn't work and copying everything did. Or, you fixed it with your changes :)
~/nodejs$ node test8.js
mynode.js ConnectionProperties [default for ndb]
TableMapping.js TableMapping.isValidFieldMapping persistent undefined; setting persistent to true
ndb_service_provider.js getFactoryKey
UserContext.js connect connection does not exist; creating factory for ndb://localhost:1186 database employees
ndb_service_provider.js connect
JsWrapper.h Constructor wrapping Ndb_cluster_connection: 0x1f30f50
NdbConnection.js connect() onConnected rval = 0
Connected to cluster as node id: 51
NdbConnectionPool.js DBConnectionPool.connect onConnected
NdbConnectionPool.js prefetchSession
UserContext.js dbConnectionPool created for ndb://localhost:1186 database employees
UserContext.js connect createFactory creating factory for ndb://localhost:1186 database employees
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f0bcc0008c0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f0bc00008c0
UserContext.js UserContext.getTableHandler did not find cached tableHandler for constructor. function Employee(id, birthDate, fName, lName, gender, hireDate) {
if (id) this.emp_no = id;
if (birthDate) this.birth_date = birthDate;
if (fName) this.first_name = fName;
if (lName) this.last_name = lName;
if (gender) this.gender = gender;
if (hireDate) this.hire_date = hireDate;
}
UserContext.js TableHandlerFactory.createTableHandler for employees employees
QueuedAsyncCall.js enqueue # 1 getTableMetadata - run immediate
DBDictionaryImpl.cpp GetTableCall::run() [employees.employees]
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f0be0002fe0
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f0bcc007a20
NdbConnectionPool.js prefetchSession adding to session pool.
JsWrapper.h Constructor wrapping DBSessionImpl: 0x7f0bc0007a20
NdbConnectionPool.js prefetchSession adding to session pool.
DBDictionaryImpl.cpp per_table_ndb employees.employees 0x7f0bc4000bd0
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
DBDictionaryImpl.cpp GetTableCall::doAsyncCallback: return_val 0
JsWrapper.h Constructor wrapping const NdbDictionary::Table: 0x7f0bc40169b0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc4016d50
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc4017130
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc40171d0
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc4016e60
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc402a270
JsWrapper.h Constructor wrapping const NdbDictionary::Column: 0x7f0bc402a310
DBDictionaryImpl.cpp Creating Primary Key Record
JsWrapper.h Constructor wrapping Record: 0x202b180
JsWrapper.h Constructor wrapping const NdbDictionary::Index: 0x7f0bc4004c40
DBDictionaryImpl.cpp Creating Index Record (PRIMARY)
JsWrapper.h Constructor wrapping Record: 0x1f314d0
DBDictionaryImpl.cpp Creating Table Record
JsWrapper.h Constructor wrapping Record: 0x204eea0
DBDictionaryImpl.cpp getForeignKey for 10/16/FK_10_17 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_manager
DBDictionaryImpl.cpp getForeignKey for 10/22/FK_10_23 returned 0
DBDictionaryImpl.cpp splitName for => employees dept_emp
DBDictionaryImpl.cpp getForeignKey for 10/28/FK_10_29 returned 0
DBDictionaryImpl.cpp splitName for => employees titles
DBDictionaryImpl.cpp getForeignKey for 10/32/FK_10_34 returned 0
DBDictionaryImpl.cpp splitName for => employees salaries
JsWrapper.h Constructor wrapping Ndb: 0x7f0bc4000bd0
NdbAutoIncrement.js New cache for table employees
NdbConnectionPool.js GroupCallback for employees.employees with 1 user callbacks
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js new completed
UserContext.js UserContext caching the table handler in the session factory.
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js DBIndexHandler constructor
DBTableHandler.js new completed
onSession.
DBTableHandler.js getIndexHandler
DBTableHandler.js chooseIndex
NdbTransactionHandler.js NEW (tx1)
NdbSession.js buildReadOperation
DBDictionaryImpl.cpp Enter: getRecordForMapping - line 788
JsWrapper.h Constructor wrapping Record: 0x204efa0
DBDictionaryImpl.cpp Leave: getRecordForMapping
ValueObject.cpp Enter: getValueObjectConstructor - line 154
JsWrapper.h Constructor wrapping ColumnHandlerSet: 0x1f32680
ValueObject.cpp Leave: getValueObjectConstructor
NdbTransactionHandler.js Execute -- AutoCommit (tx1)
NdbTransactionHandler.js internal execute
NdbSession.js seizeTransactionContext immediate 1
DBSessionImpl.cpp FreeList: (nil), nContexts: 0, maxNdbTransactions: 4
JsWrapper.h Constructor wrapping DBTransactionContext: 0x1f30bf0
JsWrapper.h Constructor wrapping DBOperationSet: 0x1f31530
NdbAutoIncrement.js New Handler 0 / 1
NdbTransactionHandler.js executeNonScan prepare 1 operations (tx1)
DBOperationHelper.cpp Non-VO read -- mask: 0 lobs: 0
DBOperationSet_wrapper.cpp DBOperationSet wrapper
JsWrapper.h Constructor wrapping DBOperationSet: 0x202c410
QueuedAsyncCall.js enqueue # 2 execute_commit - run immediate
NdbTransactionHandler.js run() (tx1) queue position: 0
DBTransactionContext.cpp START TRANSACTION [with hint] TC Node 2
DBTableHandler.js getIndexHandler
DBTableHandler.js chooseIndex
DBOperationSet.cpp prepare read [ok]
NdbTransactionHandler.js NEW (tx2)
NdbSession.js buildReadOperation
DBTransactionContext.cpp EXECUTE sync : Commit 1 operation & close transaction => return: 0 error: 0
NdbTransactionHandler.js Execute -- AutoCommit (tx2)
NdbTransactionHandler.js internal execute
NdbSession.js seizeTransactionContext immediate 2
DBSessionImpl.cpp FreeList: (nil), nContexts: 1, maxNdbTransactions: 4
JsWrapper.h Constructor wrapping DBTransactionContext: 0x202c870
JsWrapper.h Constructor wrapping DBOperationSet: 0x202b740
NdbAutoIncrement.js New Handler 0 / 1
NdbTransactionHandler.js executeNonScan prepare 1 operations (tx2)
DBOperationHelper.cpp Non-VO read -- mask: 0 lobs: 0
DBOperationSet_wrapper.cpp DBOperationSet wrapper
JsWrapper.h Constructor wrapping DBOperationSet: 0x204d8c0
QueuedAsyncCall.js enqueue # 3 execute_commit - position 1
NdbTransactionHandler.js run() (tx2) queue position: 1
DBTransactionContext.cpp START TRANSACTION [with hint] TC Node 2
DBOperationSet.cpp prepare read [ok]
NdbTransactionHandler.js onExecute commit (tx1) success: true
DBTransactionContext.cpp EXECUTE sync : Commit 1 operation & close transaction => return: 0 error: 0
DBSessionImpl.cpp releaseTransaction status: closed
NdbOperation.js completeExecutedOps mode: 2 operations: 1
DBOperationSet_wrapper.cpp Enter: readBlobResults - line 161
DBOperationSet_wrapper.cpp Leave: readBlobResults
NdbOperation.js buildOperationResult
NdbOperation.js buildValueObject
NdbRecordObject.cpp ___Constructor___ [6 col, bufsz 103, 0 blobs]
JsWrapper.h Constructor wrapping NdbRecordObject: 0x1f94d80
ColumnProxy.cpp set gender
UserContext.js find.findOnResult
onFind.
Found: {"hire_date":"1994-01-05","gender":"F","last_name":"Otillio","first_name":"Michaela","birth_date":"1965-01-11","emp_no":418606}
NdbOperation.js completeExecutedOps done
DBOperationSet.cpp DBOperationSet destructor [size 1]
JsWrapper.h Constructor wrapping DBOperationSet: (nil)
NdbTransactionHandler.js onExecute commit (tx2) success: true
DBSessionImpl.cpp releaseTransaction status: closed
NdbOperation.js completeExecutedOps mode: 2 operations: 1
DBOperationSet_wrapper.cpp Enter: readBlobResults - line 161
DBOperationSet_wrapper.cpp Leave: readBlobResults
NdbOperation.js buildOperationResult
NdbOperation.js buildValueObject
NdbRecordObject.cpp ___Constructor___ [6 col, bufsz 103, 0 blobs]
JsWrapper.h Constructor wrapping NdbRecordObject: 0x202c410
ColumnProxy.cpp set gender
UserContext.js find.findOnResult
onFind.
Found: {"hire_date":"1990-12-22","gender":"F","last_name":"Nyanchama","first_name":"Lalit","birth_date":"1960-06-01","emp_no":410493}
NdbOperation.js completeExecutedOps done
DBOperationSet.cpp DBOperationSet destructor [size 1]
JsWrapper.h Constructor wrapping DBOperationSet: (nil)
@kaltinril That's great. Just one question before we close this issue: where did you get the code that had the problem? From github? npm?
Trying to map a table to an object, so that I can also use a Converter, but even doing basic TableMapping is not working.
All attempts produce a flavor of "Unknown table mapping"
Please see the code examples below.
Example of error message:
unknown table mapping {table: employees, fields; []}
Example of standard 1 line syntax:
The following works, and we can use session.find and session.executeQuery. However, it doesn't allow us to override the mapping with a converter for the gender database field that is an ENUM.
Examples of TableMapping with just tablename defined:
Example Converter for ENUM of 'M', 'F':
Example using Converter in one statement:
Example of TableMapping and adding custom field mapping after: