├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── .gitignore ├── .npmignore ├── README.md ├── bin ├── startdbs └── stopdbs ├── drivers ├── derby.jar ├── derbyclient.jar ├── derbynet.jar ├── derbyrun.jar ├── derbyshared.jar ├── derbytools.jar ├── hsqldb.jar └── sqltool.jar ├── index.js ├── lib ├── callablestatement.js ├── connection.js ├── databasemetadata.js ├── drivermanager.js ├── jdbc.js ├── jinst.js ├── pool.js ├── preparedstatement.js ├── resultset.js ├── resultsetmetadata.js ├── sqlwarning.js └── statement.js ├── package.json ├── test ├── sqltool.rc ├── test-connection.js ├── test-derby.js ├── test-drivermanager.js ├── test-hsqldb.js ├── test-multi.js ├── test-pool-maxidle.js ├── test-pool.js ├── test-properties-config.js ├── test-statement-adjust.js ├── test-storedproc.js ├── test-txn.js └── test-user-password-url.js └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: crazysacx -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: CI 4 | 5 | jobs: 6 | node-jdbc: 7 | name: node-jdbc 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: 12 | - ubuntu-latest 13 | node_version: 14 | - 12 15 | - 14 16 | - 15 17 | - 16 18 | java_version: 19 | - 8 20 | - 9 21 | - 10 22 | - 11 23 | - 12 24 | - 13 25 | - 14 26 | - 15 27 | arch: 28 | - x64 29 | steps: 30 | - name: 🧶 Get yarn cache directory path 🧶 31 | id: yarn-cache-dir-path 32 | run: echo "::set-output name=dir::$(yarn config get cacheFolder)" 33 | - name: 💵 Cache 💵 34 | uses: actions/cache@v2 35 | id: yarn-cache 36 | with: 37 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 38 | key: ${{ runner.os }}-${{ matrix.node_version }}-yarn-${{ hashFiles('**/yarn.lock') }} 39 | restore-keys: | 40 | ${{ runner.os }}-${{ matrix.node_version }}-yarn- 41 | ${{ runner.os }}-yarn- 42 | - name: ☑️ Checkout ☑️ 43 | uses: actions/checkout@v2 44 | - name: ☕ Java ☕ 45 | uses: actions/setup-java@v1 46 | with: 47 | java-version: ${{ matrix.java_version }} 48 | - name: 🐍 Python 🐍 49 | uses: actions/setup-python@v2 50 | with: 51 | python-version: 3.9 52 | - name: 🔋 Node 🔋 53 | uses: actions/setup-node@v2 54 | with: 55 | node-version: ${{ matrix.node_version }} 56 | - name: 💾 Install 💾 57 | run: yarn install 58 | - name: 🧪 Test (Node ${{ matrix.node_version }}, Java ${{ matrix.java_version }}) 🧪 59 | run: yarn test 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *\#* 2 | *.bmk 3 | *.log 4 | node_modules 5 | mydb.* 6 | .idea/ 7 | .DS_store 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bin 2 | test 3 | .emacs.bmk 4 | drivers 5 | *.log 6 | sqltool.rc 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-jdbc 2 | JDBC API Wrapper for node.js 3 | 4 | ## Looking for a more active maintainer or sponsers 5 | As you've probably noticed, I've not been able to actively maintain this project in a few years. The project looks to be used by 6 | quite a few people, so I'm willing to add collaborators to this project who are interested in more active maintenance. You can 7 | message me at jason.g.ozias@gmail.com. 8 | 9 | If I receieve enough sponsor interest I will switch back to active maintenance of this project. 10 | 11 | [![sponsor](https://img.shields.io/github/sponsors/crazysacx?logo=github-sponsors)](https://github.com/sponsors/CraZySacX) 12 | 13 | ## Latest Version 14 | - 0.7.6 15 | 16 | ## Installation 17 | - Release: ```npm i --save jdbc``` 18 | - Development: ```npm i --save jdbc@next``` (this will install code from the master branch). 19 | 20 | Please visit [node-jdbc](https://www.npmjs.org/package/jdbc) for information on installing with npm. 21 | 22 | ## Status 23 | [![Build Status](https://travis-ci.org/CraZySacX/node-jdbc.svg?branch=master)](https://travis-ci.org/CraZySacX/node-jdbc) 24 | ## Major API Refactor 25 | 26 | - **One Instance to Rule Them All (JVM)** 27 | 28 | [node-java](https://github.com/joeferner/node-java) spins up one JVM instance only. Due to this fact, any JVM options 29 | and classpath setup have to happen before the first java call. I've created a 30 | small wrapper (jinst.js) to help out with this. See below for example 31 | usage. I usually add this to every file that may be an entry point. The 32 | [unit tests](https://github.com/CraZySacX/node-jdbc/tree/master/test) 33 | are setup like this due to the fact that order can't be guaranteed. 34 | 35 | ```javascript 36 | var jinst = require('jdbc/lib/jinst'); 37 | 38 | // isJvmCreated will be true after the first java call. When this happens, the 39 | // options and classpath cannot be adjusted. 40 | if (!jinst.isJvmCreated()) { 41 | // Add all java options required by your project here. You get one chance to 42 | // setup the options before the first java call. 43 | jinst.addOption("-Xrs"); 44 | // Add all jar files required by your project here. You get one chance to 45 | // setup the classpath before the first java call. 46 | jinst.setupClasspath(['./drivers/hsqldb.jar', 47 | './drivers/derby.jar', 48 | './drivers/derbyclient.jar', 49 | './drivers/derbytools.jar']); 50 | } 51 | ``` 52 | 53 | 54 | - **Connection Pooling** 55 | 56 | Everyone gets a pool now. By default with no extra configuration, the pool 57 | is created with one connection that can be reserved/released. Currently, the 58 | pool is configured with two options: `minpoolsize` and `maxpoolsize`. If 59 | `minpoolsize` is set, when the pool is initialized, `minpoolsize` connections 60 | will be created. If `maxpoolsize` is set (the default value is `minpoolsize`), 61 | and you try and reserve a connection and there aren't any available, the pool 62 | will be grown. This can happen until `maxpoolsize` connections have been 63 | reserved. The pool should be initialized after configuration is set with the 64 | `initialize()` function. JDBC connections can then be acquired with the 65 | `reserve()` function and returned to the pool with the `release()` function. 66 | Below is the unit test for the pool that demonstrates this behavior. 67 | 68 | ```javascript 69 | var _ = require('lodash'); 70 | var nodeunit = require('nodeunit'); 71 | var jinst = require('../lib/jinst'); 72 | var Pool = require('../lib/pool'); 73 | 74 | if (!jinst.isJvmCreated()) { 75 | jinst.addOption("-Xrs"); 76 | jinst.setupClasspath(['./drivers/hsqldb.jar', 77 | './drivers/derby.jar', 78 | './drivers/derbyclient.jar', 79 | './drivers/derbytools.jar']); 80 | } 81 | 82 | var config = { 83 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 84 | user : 'SA', 85 | password: '', 86 | minpoolsize: 2, 87 | maxpoolsize: 3 88 | }; 89 | 90 | var testpool = null; 91 | var testconn = null; 92 | 93 | module.exports = { 94 | setUp: function(callback) { 95 | if (testpool === null) { 96 | testpool = new Pool(config); 97 | } 98 | callback(); 99 | }, 100 | testinitialize: function(test) { 101 | // Initialize the pool (create minpoolsize connections) 102 | testpool.initialize(function(err) { 103 | test.expect(1); 104 | test.equal(null, err); 105 | test.done(); 106 | }); 107 | }, 108 | testreserve: function(test) { 109 | // Reserve a connection. 110 | testpool.reserve(function(err, conn) { 111 | test.expect(4); 112 | test.equal(null, err); 113 | test.ok(conn && typeof conn == 'object'); 114 | test.equal(testpool._pool.length, 1); 115 | test.equal(testpool._reserved.length, 1); 116 | testconn = conn; 117 | test.done(); 118 | }); 119 | }, 120 | testrelease: function(test) { 121 | // Release a connection. 122 | testpool.release(testconn, function(err, conn) { 123 | test.expect(3); 124 | test.equal(null, err); 125 | test.equal(testpool._pool.length, 2); 126 | test.equal(testpool._reserved.length, 0); 127 | testconn = null; 128 | test.done(); 129 | }); 130 | }, 131 | testreserverelease: function(test) { 132 | // Reserve then release a connection. 133 | testpool.reserve(function(err, conn) { 134 | if (err) { 135 | console.log(err); 136 | } else { 137 | testpool.release(conn, function(err) { 138 | test.expect(3); 139 | test.equal(null, err); 140 | test.equal(testpool._pool.length, 2); 141 | test.equal(testpool._reserved.length, 0); 142 | test.done(); 143 | }); 144 | } 145 | }); 146 | }, 147 | testreservepastmin: function(test) { 148 | // Reserve connections past minpoolsize. This will grow the pool. 149 | var conns = []; 150 | for(i = 0; i < 3; i++) { 151 | testpool.reserve(function(err, conn) { 152 | conns.push(conn); 153 | if (i == 3) { 154 | test.expect(2); 155 | test.equal(testpool._pool.length, 0); 156 | test.equal(testpool._reserved.length, 3); 157 | _.each(conns, function(conn) { 158 | testpool.release(conn, function(err) {}); 159 | }); 160 | test.done(); 161 | } 162 | }); 163 | } 164 | }, 165 | testovermax: function(test) { 166 | // Reserve connections past maxpoolsize. This will max out the pool, and 167 | // throw an error when the last reserve request is made. 168 | var conns = []; 169 | for(i = 0; i < 4; i++) { 170 | testpool.reserve(function(err, conn) { 171 | if (err) { 172 | if (i == 3) { 173 | test.expect(3); 174 | test.ok(err); 175 | test.equal(testpool._reserved.length, 3); 176 | test.equal(testpool._pool.length, 0); 177 | _.each(conns, function(conn) { 178 | testpool.release(conn, function(err) {}); 179 | }); 180 | test.done(); 181 | } else { 182 | console.log(err); 183 | } 184 | } else { 185 | conns.push(conn); 186 | } 187 | }); 188 | } 189 | } 190 | }; 191 | ``` 192 | 193 | 194 | - **Fully Wrapped Connection API** 195 | 196 | The Java Connection API has almost been completely wrapped. See 197 | [connection.js](https://github.com/CraZySacX/node-jdbc/blob/master/lib/connection.js) 198 | for a full list of functions. 199 | 200 | ```javascript 201 | conn.setAutoCommit(false, function(err) { 202 | if (err) { 203 | callback(err); 204 | } else { 205 | callback(null); 206 | } 207 | }); 208 | ``` 209 | 210 | 211 | - **ResultSet processing separated from statement execution** 212 | 213 | ResultSet processing has been separated from statement execution to allow for 214 | more flexibility. The ResultSet returned from executing a select query can 215 | still be processed into an object array using the `toObjArray()` function on the 216 | resultset object. 217 | 218 | ```javascript 219 | // Select statement example. 220 | conn.createStatement(function(err, statement) { 221 | if (err) { 222 | callback(err); 223 | } else { 224 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 225 | if (err) { 226 | callback(err) 227 | } else { 228 | // Convert the result set to an object array. 229 | resultset.toObjArray(function(err, results) { 230 | if (results.length > 0) { 231 | console.log("ID: " + results[0].ID); 232 | } 233 | callback(null, resultset); 234 | }); 235 | } 236 | }); 237 | } 238 | }); 239 | ``` 240 | - **Oracle and Closing Statements** 241 | 242 | If you are experiencing the "ORA-01000: maximum open cursors exceeded" error, you can avoid it by closing your statements with: 243 | ```javascript 244 | statement.close() 245 | ``` 246 | 247 | - **Automatically Closing Idle Connections** 248 | 249 | If you pass a **maxidle** property in the config for a new connection pool, 250 | `pool.reserve()` will close stale connections, and will return a sufficiently fresh connection, or a new connection. **maxidle** can be number representing the maximum number of milliseconds since a connection was last used, that a connection is still considered alive (without making an extra call to the database to check that the connection is valid). If **maxidle** is a falsy value or is absent from the config, this feature does not come into effect. This feature is useful, when connections are automatically closed from the server side after a certain period of time, and when it is not appropriate to use the connection keepalive feature. 251 | 252 | ## Usage 253 | Some mininal examples are given below. I've also created a 254 | [node-example-jdbc](https://github.com/CraZySacX/node-jdbc-example) project with more thorough examples. 255 | 256 | ### Initialize 257 | ```javascript 258 | var JDBC = require('jdbc'); 259 | var jinst = require('jdbc/lib/jinst'); 260 | 261 | if (!jinst.isJvmCreated()) { 262 | jinst.addOption("-Xrs"); 263 | jinst.setupClasspath(['./drivers/hsqldb.jar', 264 | './drivers/derby.jar', 265 | './drivers/derbyclient.jar', 266 | './drivers/derbytools.jar']); 267 | } 268 | 269 | var config = { 270 | // Required 271 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 272 | 273 | // Optional 274 | drivername: 'my.jdbc.DriverName', 275 | minpoolsize: 10, 276 | maxpoolsize: 100, 277 | 278 | // Note that if you sepecify the user and password as below, they get 279 | // converted to properties and submitted to getConnection that way. That 280 | // means that if your driver doesn't support the 'user' and 'password' 281 | // properties this will not work. You will have to supply the appropriate 282 | // values in the properties object instead. 283 | user: 'SA', 284 | password: '', 285 | properties: {} 286 | }; 287 | 288 | // or user/password in url 289 | // var config = { 290 | // // Required 291 | // url: 'jdbc:hsqldb:hsql://localhost/xdb;user=SA;password=', 292 | // 293 | // // Optional 294 | // drivername: 'my.jdbc.DriverName', 295 | // minpoolsize: 10 296 | // maxpoolsize: 100, 297 | // properties: {} 298 | // }; 299 | 300 | // or user/password in properties 301 | // var config = { 302 | // // Required 303 | // url: 'jdbc:hsqldb:hsql://localhost/xdb', 304 | // 305 | // // Optional 306 | // drivername: 'my.jdbc.DriverName', 307 | // minpoolsize: 10, 308 | // maxpoolsize: 100, 309 | // properties: { 310 | // user: 'SA', 311 | // password: '' 312 | // // Other driver supported properties can be added here as well. 313 | // } 314 | // }; 315 | 316 | var hsqldb = new JDBC(config); 317 | 318 | hsqldb.initialize(function(err) { 319 | if (err) { 320 | console.log(err); 321 | } 322 | }); 323 | ``` 324 | 325 | ### Reserve Connection, Execute Queries, Release Connection 326 | ```javascript 327 | // This assumes initialization as above. 328 | // For series execution. 329 | var asyncjs = require('async'); 330 | 331 | hsqldb.reserve(function(err, connObj) { 332 | // The connection returned from the pool is an object with two fields 333 | // {uuid: , conn: } 334 | if (connObj) { 335 | console.log("Using connection: " + connObj.uuid); 336 | // Grab the Connection for use. 337 | var conn = connObj.conn; 338 | 339 | // Adjust some connection options. See connection.js for a full set of 340 | // supported methods. 341 | asyncjs.series([ 342 | function(callback) { 343 | conn.setAutoCommit(false, function(err) { 344 | if (err) { 345 | callback(err); 346 | } else { 347 | callback(null); 348 | } 349 | }); 350 | }, 351 | function(callback) { 352 | conn.setSchema("test", function(err) { 353 | if (err) { 354 | callback(err); 355 | } else { 356 | callback(null); 357 | } 358 | }); 359 | } 360 | ], function(err, results) { 361 | // Check for errors if need be. 362 | // results is an array. 363 | }); 364 | 365 | // Query the database. 366 | asyncjs.series([ 367 | function(callback) { 368 | // CREATE SQL. 369 | conn.createStatement(function(err, statement) { 370 | if (err) { 371 | callback(err); 372 | } else { 373 | statement.executeUpdate("CREATE TABLE blah " 374 | + "(id int, name varchar(10), date DATE, " 375 | + " time TIME, timestamp TIMESTAMP);", 376 | function(err, count) { 377 | if (err) { 378 | callback(err); 379 | } else { 380 | callback(null, count); 381 | } 382 | }); 383 | } 384 | }); 385 | }, 386 | function(callback) { 387 | conn.createStatement(function(err, statement) { 388 | if (err) { 389 | callback(err); 390 | } else { 391 | statement.executeUpdate("INSERT INTO blah " 392 | + "VALUES (1, 'Jason', CURRENT_DATE, " 393 | + "CURRENT_TIME, CURRENT_TIMESTAMP);", 394 | function(err, count) { 395 | if (err) { 396 | callback(err); 397 | } else { 398 | callback(null, count); 399 | } 400 | }); 401 | } 402 | }); 403 | }, 404 | function(callback) { 405 | // Update statement. 406 | conn.createStatement(function(err, statement) { 407 | if (err) { 408 | callback(err); 409 | } else { 410 | statement.executeUpdate("UPDATE blah " 411 | + "SET id = 2 " 412 | + "WHERE name = 'Jason';", 413 | function(err, count) { 414 | if (err) { 415 | callback(err); 416 | } else { 417 | callback(null, count); 418 | } 419 | }); 420 | } 421 | }); 422 | }, 423 | function(callback) { 424 | // Select statement example. 425 | conn.createStatement(function(err, statement) { 426 | if (err) { 427 | callback(err); 428 | } else { 429 | // Adjust some statement options before use. See statement.js for 430 | // a full listing of supported options. 431 | statement.setFetchSize(100, function(err) { 432 | if (err) { 433 | callback(err); 434 | } else { 435 | statement.executeQuery("SELECT * FROM blah;", 436 | function(err, resultset) { 437 | if (err) { 438 | callback(err) 439 | } else { 440 | resultset.toObjArray(function(err, results) { 441 | if (results.length > 0) { 442 | console.log("ID: " + results[0].ID); 443 | } 444 | callback(null, resultset); 445 | }); 446 | } 447 | }); 448 | } 449 | }); 450 | } 451 | }); 452 | }, 453 | function(callback) { 454 | conn.createStatement(function(err, statement) { 455 | if (err) { 456 | callback(err); 457 | } else { 458 | statement.executeUpdate("DELETE FROM blah " 459 | + "WHERE id = 2;", function(err, count) { 460 | if (err) { 461 | callback(err); 462 | } else { 463 | callback(null, count); 464 | } 465 | }); 466 | } 467 | }); 468 | }, 469 | function(callback) { 470 | conn.createStatement(function(err, statement) { 471 | if (err) { 472 | callback(err); 473 | } else { 474 | statement.executeUpdate("DROP TABLE blah;", function(err, count) { 475 | if (err) { 476 | callback(err); 477 | } else { 478 | callback(null, count); 479 | } 480 | }); 481 | } 482 | }); 483 | } 484 | ], function(err, results) { 485 | // Results can also be processed here. 486 | // Release the connection back to the pool. 487 | hsqldb.release(connObj, function(err) { 488 | if (err) { 489 | console.log(err.message); 490 | } 491 | }); 492 | }); 493 | } 494 | }); 495 | ``` 496 | -------------------------------------------------------------------------------- /bin/startdbs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -cp drivers\/hsqldb.jar org.hsqldb.server.Server --database.0 file:test\/mydb --dbname.0 xdb >test\/hsqldb.log 2>&1 & 3 | java -Dderby.system.home=./test -classpath drivers\/derby.jar:drivers\/derbynet.jar:drivers\/derbytools.jar -jar drivers\/derbyrun.jar server start >test\/derby.log 2>&1 & 4 | sleep 10 5 | -------------------------------------------------------------------------------- /bin/stopdbs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | java -jar drivers/sqltool.jar --rcfile test\/sqltool.rc --sql "SHUTDOWN;" xdb 3 | java -classpath drivers/derby.jar:drivers/derbytools.jar:drivers/derbynet.jar -jar drivers/derbyrun.jar server shutdown 4 | rm -rf test/testdb 5 | rm -rf test/mydb.* 6 | -------------------------------------------------------------------------------- /drivers/derby.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derby.jar -------------------------------------------------------------------------------- /drivers/derbyclient.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derbyclient.jar -------------------------------------------------------------------------------- /drivers/derbynet.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derbynet.jar -------------------------------------------------------------------------------- /drivers/derbyrun.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derbyrun.jar -------------------------------------------------------------------------------- /drivers/derbyshared.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derbyshared.jar -------------------------------------------------------------------------------- /drivers/derbytools.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/derbytools.jar -------------------------------------------------------------------------------- /drivers/hsqldb.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/hsqldb.jar -------------------------------------------------------------------------------- /drivers/sqltool.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CraZySacX/node-jdbc/b54920712af5d60f6918715fb8175f05d0a3b8ac/drivers/sqltool.jar -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./lib/jdbc.js"); 2 | -------------------------------------------------------------------------------- /lib/callablestatement.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require('lodash'); 4 | var PreparedStatement = require('./preparedstatement'); 5 | 6 | function CallableStatement(cs) { 7 | PreparedStatement.call(this, cs); 8 | this._cs = cs; 9 | } 10 | 11 | CallableStatement.prototype = Object.create(PreparedStatement.prototype); 12 | CallableStatement.prototype.constructor = CallableStatement; 13 | 14 | CallableStatement.prototype.getArray = function(arg1, callback) { 15 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 16 | this._cs.getArray(arg1, function(err, result) { 17 | if (err) { 18 | return callback(err); 19 | } else { 20 | return callback(null, result); 21 | } 22 | }); 23 | } else { 24 | return callback(new Error("INVALID ARGUMENTS")); 25 | } 26 | }; 27 | 28 | CallableStatement.prototype.getBigDecimal = function(arg1, callback) { 29 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 30 | this._cs.getBigDecimal(arg1, function(err, result) { 31 | if (err) { 32 | return callback(err); 33 | } else { 34 | return callback(null, result); 35 | } 36 | }); 37 | } else { 38 | return callback(new Error("INVALID ARGUMENTS")); 39 | } 40 | }; 41 | 42 | CallableStatement.prototype.getBlob = function(arg1, callback) { 43 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 44 | this._cs.getBlob(arg1, function(err, result) { 45 | if (err) { 46 | return callback(err); 47 | } else { 48 | return callback(null, result); 49 | } 50 | }); 51 | } else { 52 | return callback(new Error("INVALID ARGUMENTS")); 53 | } 54 | }; 55 | 56 | CallableStatement.prototype.getBoolean = function(arg1, callback) { 57 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 58 | this._cs.getBoolean(arg1, function(err, result) { 59 | if (err) { 60 | return callback(err); 61 | } else { 62 | return callback(null, result); 63 | } 64 | }); 65 | } else { 66 | return callback(new Error("INVALID ARGUMENTS")); 67 | } 68 | }; 69 | 70 | CallableStatement.prototype.getByte = function(arg1, callback) { 71 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 72 | this._cs.getByte(arg1, function(err, result) { 73 | if (err) { 74 | return callback(err); 75 | } else { 76 | return callback(null, result); 77 | } 78 | }); 79 | } else { 80 | return callback(new Error("INVALID ARGUMENTS")); 81 | } 82 | }; 83 | 84 | CallableStatement.prototype.getBytes = function(arg1, callback) { 85 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 86 | this._cs.getBytes(arg1, function(err, result) { 87 | if (err) { 88 | return callback(err); 89 | } else { 90 | return callback(null, result); 91 | } 92 | }); 93 | } else { 94 | return callback(new Error("INVALID ARGUMENTS")); 95 | } 96 | }; 97 | 98 | CallableStatement.prototype.getCharacterStream = function(arg1, callback) { 99 | return callback(new Error("NOT IMPLEMENTED")); 100 | }; 101 | 102 | CallableStatement.prototype.getClob = function(arg1, callback) { 103 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 104 | this._cs.getClob(arg1, function(err, result) { 105 | if (err) { 106 | return callback(err); 107 | } else { 108 | return callback(null, result); 109 | } 110 | }); 111 | } else { 112 | return callback(new Error("INVALID ARGUMENTS")); 113 | } 114 | }; 115 | 116 | CallableStatement.prototype.getDate = function(arg1, arg2, callback) { 117 | // Get arguments as an array 118 | var args = Array.prototype.slice.call(arguments); 119 | 120 | // Pull the callback off the end of the arguments 121 | callback = args.pop(); 122 | 123 | // Check arguments for validity, and return error if invalid 124 | var validArgs = ( 125 | (_.isNumber(args[0]) || _.isString(args[0])) && 126 | (_.isUndefined(args[1]) || _.isObject(args[1])) 127 | ); 128 | if (! validArgs) { 129 | return callback(new Error("INVALID ARGUMENTS")); 130 | } 131 | 132 | // Push a callback handler onto the arguments 133 | args.push(function(err, result) { 134 | if (err) { 135 | return callback(err); 136 | } else { 137 | return callback(null, result); 138 | } 139 | }); 140 | 141 | // Forward modified arguments to _cs.getDate 142 | this._cs.getDate.apply(this._cs, args); 143 | }; 144 | 145 | CallableStatement.prototype.getDouble = function(arg1, callback) { 146 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 147 | this._cs.getDouble(arg1, function(err, result) { 148 | if (err) { 149 | return callback(err); 150 | } else { 151 | return callback(null, result); 152 | } 153 | }); 154 | } else { 155 | return callback(new Error("INVALID ARGUMENTS")); 156 | } 157 | }; 158 | 159 | CallableStatement.prototype.getFloat = function(arg1, callback) { 160 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 161 | this._cs.getFloat(arg1, function(err, result) { 162 | if (err) { 163 | return callback(err); 164 | } else { 165 | return callback(null, result); 166 | } 167 | }); 168 | } else { 169 | return callback(new Error("INVALID ARGUMENTS")); 170 | } 171 | }; 172 | 173 | CallableStatement.prototype.getInt = function(arg1, callback) { 174 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 175 | this._cs.getInt(arg1, function(err, result) { 176 | if (err) { 177 | return callback(err); 178 | } else { 179 | return callback(null, result); 180 | } 181 | }); 182 | } else { 183 | return callback(new Error("INVALID ARGUMENTS")); 184 | } 185 | }; 186 | 187 | CallableStatement.prototype.getLong = function(arg1, callback) { 188 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 189 | this._cs.getLong(arg1, function(err, result) { 190 | if (err) { 191 | return callback(err); 192 | } else { 193 | return callback(null, result); 194 | } 195 | }); 196 | } else { 197 | return callback(new Error("INVALID ARGUMENTS")); 198 | } 199 | }; 200 | 201 | CallableStatement.prototype.getNCharacterStream = function(arg1, callback) { 202 | return callback(new Error("NOT IMPLEMENTED")); 203 | }; 204 | 205 | CallableStatement.prototype.getNClob = function(arg1, callback) { 206 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 207 | this._cs.getNClob(arg1, function(err, result) { 208 | if (err) { 209 | return callback(err); 210 | } else { 211 | return callback(null, result); 212 | } 213 | }); 214 | } else { 215 | return callback(new Error("INVALID ARGUMENTS")); 216 | } 217 | }; 218 | 219 | CallableStatement.prototype.getNString = function(arg1, callback) { 220 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 221 | this._cs.getNString(arg1, function(err, result) { 222 | if (err) { 223 | return callback(err); 224 | } else { 225 | return callback(null, result); 226 | } 227 | }); 228 | } else { 229 | return callback(new Error("INVALID ARGUMENTS")); 230 | } 231 | }; 232 | 233 | CallableStatement.prototype.getLong = function(arg1, callback) { 234 | if (typeof arg1 === 'number' || typeof arg1 === 'string') { 235 | this._cs.getLong(arg1, function(err, result) { 236 | if (err) { 237 | return callback(err); 238 | } else { 239 | return callback(null, result); 240 | } 241 | }); 242 | } else { 243 | return callback(new Error("INVALID ARGUMENTS")); 244 | } 245 | }; 246 | 247 | CallableStatement.prototype.getObject = function(arg1, arg2, callback) { 248 | return callback(new Error("NOT IMPLEMENTED")); 249 | }; 250 | 251 | CallableStatement.prototype.registerOutParameter = function() { 252 | var args = Array.prototype.slice.call(arguments); 253 | var callback = args.pop(); 254 | if ((typeof args[0] == 'number' && typeof args[1] == 'number') || 255 | (typeof args[0] == 'number' && typeof args[1] == 'number' && typeof args[2] == 'number') || 256 | (typeof args[0] == 'number' && typeof args[1] == 'number' && typeof args[2] == 'string') || 257 | (typeof args[0] == 'string' && typeof args[1] == 'number') || 258 | (typeof args[0] == 'string' && typeof args[1] == 'number' && typeof args[2] == 'number') || 259 | (typeof args[0] == 'string' && typeof args[1] == 'number' && typeof args[2] == 'string')) { 260 | args.push(callback); 261 | this._cs.registerOutParameter.apply(this._cs, args); 262 | } else { 263 | return callback(new Error("INVALID ARGUMENTS")); 264 | } 265 | } 266 | 267 | module.exports = CallableStatement; 268 | -------------------------------------------------------------------------------- /lib/connection.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require("lodash"); 4 | var jinst = require("./jinst"); 5 | var CallableStatement = require('./callablestatement'); 6 | var PreparedStatement = require('./preparedstatement'); 7 | var DatabaseMetaData = require('./databasemetadata'); 8 | var Statement = require('./statement'); 9 | var SQLWarning = require('./sqlwarning'); 10 | var java = jinst.getInstance(); 11 | 12 | if (!jinst.isJvmCreated()) { 13 | jinst.addOption("-Xrs"); 14 | } 15 | 16 | function Connection(conn) { 17 | this._conn = conn; 18 | this._txniso = (function() { 19 | var txniso = []; 20 | 21 | txniso[java.getStaticFieldValue("java.sql.Connection", "TRANSACTION_NONE")] = "TRANSACTION_NONE"; 22 | txniso[java.getStaticFieldValue("java.sql.Connection", "TRANSACTION_READ_COMMITTED")] = "TRANSACTION_READ_COMMITTED"; 23 | txniso[java.getStaticFieldValue("java.sql.Connection", "TRANSACTION_READ_UNCOMMITTED")] = "TRANSACTION_READ_UNCOMMITTED"; 24 | txniso[java.getStaticFieldValue("java.sql.Connection", "TRANSACTION_REPEATABLE_READ")] = "TRANSACTION_REPEATABLE_READ"; 25 | txniso[java.getStaticFieldValue("java.sql.Connection", "TRANSACTION_SERIALIZABLE")] = "TRANSACTION_SERIALIZABLE"; 26 | 27 | return txniso; 28 | })(); 29 | } 30 | 31 | Connection.prototype.abort = function(executor, callback) { 32 | return callback(new Error("NOT IMPLEMENTED")); 33 | }; 34 | 35 | Connection.prototype.clearWarnings = function(callback) { 36 | this._conn.clearWarnings(function(err) { 37 | if (err) { 38 | return callback(err); 39 | } else { 40 | return callback(null); 41 | } 42 | }); 43 | }; 44 | 45 | Connection.prototype.close = function(callback) { 46 | var self = this; 47 | 48 | if (self._conn === null) { 49 | return callback(null); 50 | } 51 | 52 | self._conn.close(function(err) { 53 | if (err) { 54 | return callback(err); 55 | } else { 56 | self._conn = null; 57 | return callback(null); 58 | } 59 | }); 60 | }; 61 | 62 | Connection.prototype.commit = function(callback) { 63 | this._conn.commit(function(err) { 64 | if (err) { 65 | return callback(err); 66 | } else { 67 | return callback(null); 68 | } 69 | }); 70 | }; 71 | 72 | Connection.prototype.createArrayOf = function(typename, objarr, callback) { 73 | return callback(new Error("NOT IMPLEMENTED")); 74 | }; 75 | 76 | Connection.prototype.createBlob = function(callback) { 77 | return callback(new Error("NOT IMPLEMENTED")); 78 | }; 79 | 80 | Connection.prototype.createClob = function(callback) { 81 | return callback(new Error("NOT IMPLEMENTED")); 82 | }; 83 | 84 | Connection.prototype.createNClob = function(callback) { 85 | return callback(new Error("NOT IMPLEMENTED")); 86 | }; 87 | 88 | Connection.prototype.createSQLXML = function(callback) { 89 | return callback(new Error("NOT IMPLEMENTED")); 90 | }; 91 | 92 | Connection.prototype.createStatement = function(arg1, arg2, arg3, callback) { 93 | // Get arguments as an array 94 | var args = Array.prototype.slice.call(arguments); 95 | 96 | // Pull the callback off the end of the arguments 97 | callback = args.pop(); 98 | 99 | // Check arguments for validity, and return error if invalid 100 | var invalidArgs = false; 101 | _.forEach(args, function(arg) { 102 | if (! _.isNumber(arg)) { 103 | invalidArgs = true; 104 | // Lodash break 105 | return false; 106 | } 107 | }); 108 | 109 | if (invalidArgs) { 110 | return callback(new Error("INVALID ARGUMENTS")); 111 | } 112 | 113 | // Push a callback handler onto the arguments 114 | args.push(function(err, statement) { 115 | if (err) { 116 | return callback(err); 117 | } else { 118 | return callback(null, new Statement(statement)); 119 | } 120 | }); 121 | 122 | // Forward modified arguments to _conn.createStatement 123 | this._conn.createStatement.apply(this._conn, args); 124 | }; 125 | 126 | Connection.prototype.createStruct = function(typename, attrarr, callback) { 127 | return callback(new Error("NOT IMPLEMENTED")); 128 | }; 129 | 130 | Connection.prototype.getAutoCommit = function(callback) { 131 | this._conn.getAutoCommit(function(err, result) { 132 | if (err) { 133 | return callback(err); 134 | } else { 135 | return callback(null, result); 136 | } 137 | }); 138 | }; 139 | 140 | Connection.prototype.getCatalog = function(callback) { 141 | this._conn.getCatalog(function(err, catalog) { 142 | if (err) { 143 | return callback(err); 144 | } else { 145 | return callback(null, catalog); 146 | } 147 | }); 148 | }; 149 | 150 | Connection.prototype.getClientInfo = function(name, callback) { 151 | // Get arguments as an array 152 | var args = Array.prototype.slice.call(arguments); 153 | 154 | // Pull the callback off the end of the arguments 155 | callback = args.pop(); 156 | 157 | // Push a callback handler onto the arguments 158 | args.push(function(err, result) { 159 | if (err) { 160 | return callback(err); 161 | } else { 162 | return callback(null, result); 163 | } 164 | }); 165 | 166 | // Forward modified arguments to _conn.getClientInfo 167 | this._conn.getClientInfo.apply(this._conn, args); 168 | }; 169 | 170 | Connection.prototype.getHoldability = function(callback) { 171 | this._conn.getClientInfo(function(err, holdability) { 172 | if (err) { 173 | return callback(err); 174 | } else { 175 | return callback(null, holdability); 176 | } 177 | }); 178 | }; 179 | 180 | Connection.prototype.getMetaData = function(callback) { 181 | this._conn.getMetaData(function(err, dbm) { 182 | if (err) { 183 | return callback(err); 184 | } else { 185 | return callback(null, new DatabaseMetaData(dbm)); 186 | } 187 | }); 188 | }; 189 | 190 | Connection.prototype.getNetworkTimeout = function(callback) { 191 | this._conn.getNetworkTimeout(function(err, ms) { 192 | if (err) { 193 | return callback(err); 194 | } else { 195 | return callback(null, ms); 196 | } 197 | }); 198 | }; 199 | 200 | Connection.prototype.getSchema = function(callback) { 201 | this._conn.getSchema(function(err, schema) { 202 | if (err) { 203 | return callback(err); 204 | } else { 205 | return callback(null, schema); 206 | } 207 | }); 208 | }; 209 | 210 | Connection.prototype.getTransactionIsolation = function(callback) { 211 | var self = this; 212 | 213 | self._conn.getTransactionIsolation(function(err, txniso) { 214 | if (err) { 215 | return callback(err); 216 | } else { 217 | return callback(null, self._txniso[txniso]); 218 | } 219 | }); 220 | }; 221 | 222 | Connection.prototype.getTypeMap = function(callback) { 223 | this._conn.getTypeMap(function(err, map) { 224 | if (err) { 225 | return callback(err); 226 | } else { 227 | return callback(null, map); 228 | } 229 | }); 230 | }; 231 | 232 | Connection.prototype.getWarnings = function(callback) { 233 | this._conn.getWarnings(function(err, sqlwarning) { 234 | if (err) { 235 | return callback(err); 236 | } else { 237 | return callback(null, new SQLWarning(sqlwarning)); 238 | } 239 | }); 240 | }; 241 | 242 | Connection.prototype.isClosed = function(callback) { 243 | this._conn.isClosed(function(err, closed) { 244 | if (err) return callback(err); 245 | callback(null, closed); 246 | }); 247 | }; 248 | 249 | Connection.prototype.isClosedSync = function() { 250 | return this._conn.isClosedSync(); 251 | }; 252 | 253 | Connection.prototype.isReadOnly = function(callback) { 254 | this._conn.isReadOnly(function(err, readonly) { 255 | if (err) { 256 | return callback(err); 257 | } else { 258 | return callback(null, readonly); 259 | } 260 | }); 261 | }; 262 | 263 | Connection.prototype.isReadOnlySync = function() { 264 | return this._conn.isReadOnlySync(); 265 | }; 266 | 267 | Connection.prototype.isValid = function(timeout, callback) { 268 | this._conn.isValid(timeout, function(err, valid) { 269 | if (err) { 270 | return callback(err); 271 | } else { 272 | return callback(null, valid); 273 | } 274 | }); 275 | }; 276 | 277 | Connection.prototype.isValidSync = function(timeout) { 278 | return this._conn.isValidSync(timeout); 279 | }; 280 | 281 | Connection.prototype.nativeSQL = function(sql, callback) { 282 | return callback(new Error("NOT IMPLEMENTED")); 283 | }; 284 | 285 | Connection.prototype.prepareCall = function(sql, rstype, rsconcurrency, rsholdability, callback) { 286 | // Get arguments as an array 287 | var args = Array.prototype.slice.call(arguments); 288 | 289 | // Pull the callback off the end of the arguments 290 | callback = args.pop(); 291 | 292 | // Check arguments for validity, and return error if invalid 293 | if (! args[0] || (args[1] && ! args[2])) { 294 | return callback(new Error("INVALID ARGUMENTS")); 295 | } 296 | 297 | // Push a callback handler onto the arguments 298 | args.push(function(err, callablestatement) { 299 | if (err) { 300 | return callback(err); 301 | } else { 302 | return callback(null, new CallableStatement(callablestatement)); 303 | } 304 | }); 305 | 306 | // Forward modified arguments to _conn.prepareCall 307 | this._conn.prepareCall.apply(this._conn, args); 308 | }; 309 | 310 | function allType(array, type) { 311 | _.each(array, function(el) { 312 | if (typeof el !== type) { 313 | return false; 314 | } 315 | }); 316 | 317 | return true; 318 | } 319 | 320 | /** 321 | * @callback prepareStatementCallback 322 | * @param {Error} err - An error message, or null if no error occurred 323 | * @param {PreparedStatement} prepStmt - The prepared statement 324 | */ 325 | 326 | /** 327 | * Creates a prepared statement and returns it via callback. 328 | * 329 | * @param {string} sql - SQL query 330 | * @param {(number | number[] | string[])} [arg1] - autoGeneratedKeys, resultSetType, or an array of numbers or strings 331 | * @param {number} [arg2] - resultSetConcurrency 332 | * @param {number} [arg3] - resultSetHoldability 333 | * @param {prepareStatementCallback} callback - The callback that handles the prepare statement response 334 | */ 335 | Connection.prototype.prepareStatement = function(sql, arg1, arg2, arg3, callback) { 336 | // Get arguments as an array 337 | var args = Array.prototype.slice.call(arguments); 338 | 339 | // Pull the callback off the end of the arguments 340 | callback = args.pop(); 341 | 342 | // Error to return if arguments are invalid 343 | var errMsg = 'INVALID ARGUMENTS'; 344 | 345 | // The first arg (sql) must be present 346 | if (! args[0]) { 347 | return callback(new Error(errMsg)); 348 | } 349 | 350 | // Check arg1, arg2, and arg3 for validity. These arguments must 351 | // be numbers if given, except for the special case when the first 352 | // of these arguments is an array and no other arguments are given. 353 | // In this special case, the array must be a string or number array. 354 | // 355 | // NOTE: _.tail returns all but the first argument, so we are only 356 | // processing arg1, arg2, and arg3; and not sql (or callback, which 357 | // was already removed from the args array). 358 | var invalidArgs = false; 359 | _.forEach(_.tail(args), function(arg, idx) { 360 | // Check for the special case where arg1 can be an array of strings or numbers 361 | // if arg2 and arg3 are not given 362 | if (idx === 0 && _.isArray(arg) && _.isUndefined(args[2]) && _.isUndefined(args[3])) { 363 | if (! (allType(arg, 'string') || allType(arg, 'number'))) { 364 | invalidArgs = true; 365 | 366 | // Lodash break 367 | return false; 368 | } 369 | 370 | // Lodash continue 371 | return; 372 | } 373 | 374 | // Other than the special case above, these args must be numbers 375 | if (! _.isNumber(arg)) { 376 | invalidArgs = true; 377 | 378 | // Lodash break 379 | return false; 380 | } 381 | }); 382 | 383 | if (invalidArgs) { 384 | return callback(new Error(errMsg)); 385 | } 386 | 387 | // Push a callback handler onto the arguments 388 | args.push(function(err, ps) { 389 | if (err) { 390 | return callback(err); 391 | } else { 392 | return callback(null, new PreparedStatement(ps)); 393 | } 394 | }); 395 | 396 | // Forward modified arguments to _conn.prepareStatement 397 | this._conn.prepareStatement.apply(this._conn, args); 398 | }; 399 | 400 | Connection.prototype.releaseSavepoint = function(savepoint, callback) { 401 | this._conn.releaseSavepoint(savepoint, function(err) { 402 | if (err) { 403 | return callback(err); 404 | } else { 405 | return callback(null); 406 | } 407 | }); 408 | }; 409 | 410 | Connection.prototype.rollback = function(savepoint, callback) { 411 | // Get arguments as an array 412 | var args = Array.prototype.slice.call(arguments); 413 | 414 | // Pull the callback off the end of the arguments 415 | callback = args.pop(); 416 | 417 | // Check arguments for validity, and return error if invalid 418 | // if (! _.isObject(args[0])) { 419 | // return callback(new Error("INVALID ARGUMENTS")); 420 | // } 421 | 422 | // Push a callback handler onto the arguments 423 | args.push(function(err) { 424 | if (err) { 425 | return callback(err); 426 | } else { 427 | return callback(null); 428 | } 429 | }); 430 | 431 | // Forward modified arguments to _conn.rollback 432 | this._conn.rollback.apply(this._conn, args); 433 | }; 434 | 435 | Connection.prototype.setAutoCommit = function(autocommit, callback) { 436 | this._conn.setAutoCommit(autocommit, function(err) { 437 | if (err) { 438 | return callback(err); 439 | } else { 440 | return callback(null); 441 | } 442 | }); 443 | }; 444 | 445 | Connection.prototype.setCatalog = function(catalog, callback) { 446 | this._conn.setCatalog(catalog, function(err) { 447 | if (err) { 448 | return callback(err); 449 | } else { 450 | return callback(null); 451 | } 452 | }); 453 | }; 454 | 455 | Connection.prototype.setClientInfo = function(props, name, value, callback) { 456 | // Get arguments as an array 457 | var args = Array.prototype.slice.call(arguments); 458 | 459 | // Pull the callback off the end of the arguments 460 | callback = args.pop(); 461 | 462 | // Check arguments for validity, manipulate the args array appropriately, 463 | // and return error if invalid 464 | if (_.isObject(args[0]) && _.isUndefined(args[1]) && _.isUndefined(args[2])) { 465 | // Do nothing 466 | } else if (_.isNull(args[0]) && _.isString(args[1]) && _.isString(args[2])) { 467 | // Remove first argument (props) from args array 468 | args.shift(); 469 | } else { 470 | return callback(new Error("INVALID ARGUMENTS")); 471 | } 472 | 473 | // Push a callback handler onto the arguments 474 | args.push(function(err) { 475 | if (err) { 476 | return callback(err); 477 | } else { 478 | return callback(null); 479 | } 480 | }); 481 | 482 | // Forward modified arguments to _conn.setClientInfo 483 | this._conn.setClientInfo.apply(this._conn, args); 484 | }; 485 | 486 | Connection.prototype.setHoldability = function(holdability, callback) { 487 | this._conn.setHoldability(holdability, function(err) { 488 | if (err) { 489 | return callback(err); 490 | } else { 491 | return callback(null); 492 | } 493 | }); 494 | }; 495 | 496 | Connection.prototype.setNetworkTimeout = function(executor, ms, callback) { 497 | return callback(new Error('NOT IMPLEMENTED')); 498 | }; 499 | 500 | Connection.prototype.setReadOnly = function(readonly, callback) { 501 | this._conn.setReadOnly(readonly, function(err) { 502 | if (err) { 503 | return callback(err); 504 | } else { 505 | return callback(null); 506 | } 507 | }); 508 | }; 509 | 510 | Connection.prototype.setSavepoint = function(name, callback) { 511 | // Get arguments as an array 512 | var args = Array.prototype.slice.call(arguments); 513 | 514 | // Pull the callback off the end of the arguments 515 | callback = args.pop(); 516 | 517 | // Check arguments for validity, and return error if invalid 518 | if (! (_.isUndefined(args[0]) || _.isString(args[0]))) { 519 | return callback(new Error("INVALID ARGUMENTS")); 520 | } 521 | 522 | // Push a callback handler onto the arguments 523 | args.push(function(err, savepoint) { 524 | if (err) { 525 | return callback(err); 526 | } else { 527 | return callback(null, savepoint); 528 | } 529 | }); 530 | 531 | // Forward modified arguments to _conn.setSavepoint 532 | this._conn.setSavepoint.apply(this._conn, args); 533 | }; 534 | 535 | Connection.prototype.setSchema = function(schema, callback) { 536 | this._conn.setSchema(schema, function(err) { 537 | if (err) { 538 | return callback(err); 539 | } else { 540 | return callback(null); 541 | } 542 | }); 543 | }; 544 | 545 | Connection.prototype.setTransactionIsolation = function(txniso, callback) { 546 | this._conn.setTransactionIsolation(txniso, function(err) { 547 | if (err) { 548 | return callback(err); 549 | } else { 550 | return callback(null); 551 | } 552 | }); 553 | }; 554 | 555 | Connection.prototype.setTypeMap = function(map, callback) { 556 | return callback(new Error('NOT IMPLEMENTED')); 557 | }; 558 | 559 | module.exports = Connection; 560 | -------------------------------------------------------------------------------- /lib/drivermanager.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require('lodash'); 4 | var jinst = require("./jinst.js"); 5 | var java = jinst.getInstance(); 6 | 7 | var DM = 'java.sql.DriverManager'; 8 | 9 | module.exports = { 10 | getConnection: function(url, propsoruser, password, callback) { 11 | // Get arguments as an array 12 | var args = Array.prototype.slice.call(arguments); 13 | 14 | // Pull the callback off the end of the arguments 15 | callback = args.pop(); 16 | 17 | // Check arguments for validity, and return error if invalid 18 | var validArgs = args[0] && ( 19 | // args[1] (propsoruser) and args[2] (password) can both be falsey 20 | ! (args[1] || args[2]) || 21 | 22 | // args[1] (propsoruser) and args[2] (password) can both be strings 23 | (_.isString(args[1]) && _.isString(args[2])) || 24 | 25 | // args[1] (propsoruser) can be an object if args[2] (password) is falsey 26 | (_.isObject(args[1]) && ! args[2]) 27 | ); 28 | 29 | if(! validArgs) { 30 | return callback(new Error("INVALID ARGUMENTS")); 31 | } 32 | 33 | // Push a callback handler onto the arguments 34 | args.push(function(err, conn) { 35 | if (err) { 36 | return callback(err); 37 | } else { 38 | return callback(null, conn); 39 | } 40 | }); 41 | 42 | // Add DM and 'getConnection' string onto beginning of args 43 | // (unshift in reverse order of desired order) 44 | args.unshift('getConnection'); 45 | args.unshift(DM); 46 | 47 | // Forward modified arguments to java.callStaticMethod 48 | java.callStaticMethod.apply(java, args); 49 | }, 50 | getConnectionSync: function(url, propsoruser, password) { 51 | // Get arguments as an array 52 | var args = Array.prototype.slice.call(arguments); 53 | 54 | // Check arguments for validity, and return error if invalid 55 | var validArgs = args[0] && ( 56 | // args[1] (propsoruser) and args[2] (password) can both be falsey 57 | ! (args[1] || args[2]) || 58 | 59 | // args[1] (propsoruser) and args[2] (password) can both be strings 60 | (_.isString(args[1]) && _.isString(args[2])) || 61 | 62 | // args[1] (propsoruser) can be an object if args[2] (password) is falsey 63 | (_.isObject(args[1]) && ! args[2]) 64 | ); 65 | 66 | if(! validArgs) { 67 | return new Error("INVALID ARGUMENTS"); 68 | } 69 | 70 | // Add DM and 'getConnection' string onto beginning of args 71 | // (unshift in reverse order of desired order) 72 | args.unshift('getConnection'); 73 | args.unshift(DM); 74 | 75 | // Forward modified arguments to java.callStaticMethod 76 | return java.callStaticMethodSync.apply(java, args); 77 | }, 78 | getLoginTimeout: function(callback) { 79 | java.callStaticMethod(DM, 'getLoginTimeout', function(err, seconds) { 80 | if (err) { 81 | return callback(err); 82 | } else { 83 | return callback(null, seconds); 84 | } 85 | }); 86 | }, 87 | registerDriver: function(driver, callback) { 88 | java.callStaticMethod(DM, 'registerDriver', driver, function(err) { 89 | if (err) { 90 | return callback(err); 91 | } else { 92 | return callback(null); 93 | } 94 | }); 95 | }, 96 | setLoginTimeout: function(seconds, callback) { 97 | java.callStaticMethod(DM, 'setLoginTimeout', seconds, function(err) { 98 | if (err) { 99 | return callback(err); 100 | } else { 101 | return callback(null, true); 102 | } 103 | }); 104 | }, 105 | }; 106 | -------------------------------------------------------------------------------- /lib/jdbc.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var Pool = require("./pool"); 4 | 5 | function JDBC(config) { 6 | Pool.call(this, config); 7 | } 8 | 9 | JDBC.prototype = Object.create(Pool.prototype); 10 | JDBC.prototype.constructor = JDBC; 11 | 12 | module.exports = JDBC; 13 | -------------------------------------------------------------------------------- /lib/jinst.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var EventEmitter = require('events').EventEmitter; 4 | var util = require('util'); 5 | var java = require('java'); 6 | var winston = require('winston'); 7 | 8 | function isJvmCreated() { 9 | return typeof java.onJvmCreated !== 'function'; 10 | } 11 | 12 | var jinst = module.exports = { 13 | isJvmCreated: function() { 14 | return isJvmCreated(); 15 | }, 16 | addOption: function(option) { 17 | if (!isJvmCreated() && option) { 18 | java.options.push(option); 19 | } else if (isJvmCreated()) { 20 | winston.error("You've tried to add an option to an already running JVM!"); 21 | winston.error("This isn't currently supported. Please add all option entries before calling any java methods"); 22 | winston.error("You can test for a running JVM with the isJvmCreated funtion."); 23 | } 24 | }, 25 | setupClasspath: function(dependencyArr) { 26 | if (!isJvmCreated() && dependencyArr) { 27 | java.classpath.push.apply(java.classpath, dependencyArr); 28 | } else if (isJvmCreated()) { 29 | winston.error("You've tried to add an entry to the classpath of an already running JVM!"); 30 | winston.error("This isn't currently supported. Please add all classpath entries before calling any java methods"); 31 | winston.error("You can test for a running JVM with the isJvmCreated funtion."); 32 | } 33 | }, 34 | getInstance: function() { 35 | return java; 36 | }, 37 | events: new EventEmitter(), 38 | }; 39 | -------------------------------------------------------------------------------- /lib/pool.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require('lodash'); 4 | var asyncjs = require('async'); 5 | var uuid = require('uuid'); 6 | var jinst = require("./jinst"); 7 | var dm = require('./drivermanager'); 8 | var Connection = require('./connection'); 9 | var winston = require('winston'); 10 | 11 | var java = jinst.getInstance(); 12 | 13 | if (!jinst.isJvmCreated()) { 14 | jinst.addOption("-Xrs"); 15 | } 16 | 17 | var keepalive = function(conn, query) { 18 | var self = this; 19 | conn.createStatement(function(err, statement) { 20 | if (err) return winston.error(err); 21 | statement.execute(query, function(err, result) { 22 | if (err) return winston.error(err); 23 | winston.silly("%s - Keep-Alive", new Date().toUTCString()); 24 | }); 25 | }); 26 | }; 27 | 28 | var addConnection = function(url, props, ka, maxIdle, callback) { 29 | dm.getConnection(url, props, function(err, conn) { 30 | if (err) { 31 | return callback(err); 32 | } else { 33 | var connobj = { 34 | uuid: uuid.v4(), 35 | conn: new Connection(conn), 36 | keepalive: ka.enabled ? setInterval(keepalive, ka.interval, conn, ka.query) : false 37 | }; 38 | 39 | if (maxIdle) { 40 | connobj.lastIdle = new Date().getTime(); 41 | } 42 | 43 | return callback(null, connobj); 44 | } 45 | }); 46 | }; 47 | 48 | var addConnectionSync = function(url, props, ka, maxIdle) { 49 | var conn = dm.getConnectionSync(url, props); 50 | var connobj = { 51 | uuid: uuid.v4(), 52 | conn: new Connection(conn), 53 | keepalive: ka.enabled ? setInterval(keepalive, ka.interval, conn, ka.query) : false 54 | }; 55 | 56 | if (maxIdle) { 57 | connobj.lastIdle = new Date().getTime(); 58 | } 59 | 60 | return connobj; 61 | }; 62 | 63 | function Pool(config) { 64 | this._url = config.url; 65 | this._props = (function (config) { 66 | var Properties = java.import('java.util.Properties'); 67 | var properties = new Properties(); 68 | 69 | for(var name in config.properties) { 70 | properties.putSync(name, config.properties[name]); 71 | } 72 | 73 | // NOTE: https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#getProperty(java.lang.String) 74 | // if property does not exist it returns 'null' in the new java version, so we can use _.isNil to support 75 | // older versions as well 76 | 77 | if (config.user && _.isNil(properties.getPropertySync('user'))) { 78 | properties.putSync('user', config.user); 79 | } 80 | 81 | if (config.password && _.isNil(properties.getPropertySync('password'))) { 82 | properties.putSync('password', config.password); 83 | } 84 | 85 | return properties; 86 | })(config); 87 | this._drivername = config.drivername ? config.drivername : ''; 88 | this._minpoolsize = config.minpoolsize ? config.minpoolsize : 1; 89 | this._maxpoolsize = config.maxpoolsize ? config.maxpoolsize : 1; 90 | this._keepalive = config.keepalive ? config.keepalive : { 91 | interval: 60000, 92 | query: 'select 1', 93 | enabled: false 94 | }; 95 | this._maxidle = (!this._keepalive.enabled && config.maxidle) || null; 96 | this._logging = config.logging ? config.logging : { 97 | level: 'error' 98 | }; 99 | this._pool = []; 100 | this._reserved = []; 101 | } 102 | 103 | var connStatus = function(acc, pool) { 104 | _.reduce(pool, function(conns, connobj) { 105 | var conn = connobj.conn; 106 | var closed = conn.isClosedSync(); 107 | var readonly = conn.isReadOnlySync(); 108 | var valid = conn.isValidSync(1000); 109 | conns.push({ 110 | uuid: connobj.uuid, 111 | closed: closed, 112 | readonly: readonly, 113 | valid: valid 114 | }); 115 | return conns; 116 | }, acc); 117 | return acc; 118 | }; 119 | 120 | Pool.prototype.status = function(callback) { 121 | var self = this; 122 | var status = {}; 123 | status.available = self._pool.length; 124 | status.reserved = self._reserved.length; 125 | status.pool = connStatus([], self._pool); 126 | status.rpool = connStatus([], self._reserved); 127 | callback(null, status); 128 | }; 129 | 130 | Pool.prototype._addConnectionsOnInitialize = function(callback){ 131 | var self = this; 132 | asyncjs.times(self._minpoolsize, function(n, next){ 133 | addConnection(self._url, self._props, self._keepalive, self._maxidle, function(err, conn) { 134 | next(err, conn); 135 | }); 136 | }, function(err, conns) { 137 | if (err) { 138 | return callback(err); 139 | } else { 140 | _.each(conns, function(conn) { 141 | self._pool.push(conn); 142 | }); 143 | return callback(null); 144 | } 145 | }); 146 | }; 147 | 148 | Pool.prototype.initialize = function(callback) { 149 | var self = this; 150 | 151 | winston.level = this._logging.level; 152 | 153 | // If a drivername is supplied, initialize the via the old method, 154 | // Class.forName() 155 | if (this._drivername) { 156 | java.newInstance(this._drivername, function(err, driver) { 157 | if (err) { 158 | return callback(err); 159 | } else { 160 | dm.registerDriver(driver, function(err) { 161 | if (err) { 162 | return callback(err); 163 | } 164 | self._addConnectionsOnInitialize(callback); 165 | }); 166 | } 167 | }); 168 | } 169 | else { 170 | self._addConnectionsOnInitialize(callback); 171 | } 172 | 173 | jinst.events.emit('initialized'); 174 | }; 175 | 176 | Pool.prototype.reserve = function(callback) { 177 | var self = this; 178 | var conn = null; 179 | self._closeIdleConnections(); 180 | 181 | if (self._pool.length > 0 ) { 182 | conn = self._pool.shift(); 183 | 184 | if (conn.lastIdle) { 185 | conn.lastIdle = new Date().getTime(); 186 | } 187 | 188 | self._reserved.unshift(conn); 189 | } else if (self._reserved.length < self._maxpoolsize) { 190 | try { 191 | conn = addConnectionSync(self._url, self._props, self._keepalive, self._maxidle); 192 | self._reserved.unshift(conn); 193 | } catch (err) { 194 | winston.error(err); 195 | conn = null; 196 | return callback(err); 197 | } 198 | } 199 | 200 | if (conn === null) { 201 | callback(new Error("No more pool connections available")); 202 | } else { 203 | callback(null, conn); 204 | } 205 | }; 206 | 207 | Pool.prototype._closeIdleConnections = function() { 208 | if (! this._maxidle) { 209 | return; 210 | } 211 | 212 | var self = this; 213 | 214 | closeIdleConnectionsInArray(self._pool, this._maxidle); 215 | closeIdleConnectionsInArray(self._reserved, this._maxidle); 216 | }; 217 | 218 | function closeIdleConnectionsInArray(array, maxIdle) { 219 | var time = new Date().getTime(); 220 | var maxLastIdle = time - maxIdle; 221 | 222 | for (var i = array.length - 1; i >=0; i--) { 223 | var conn = array[i]; 224 | if (typeof conn === 'object' && conn.conn !== null) { 225 | if (conn.lastIdle < maxLastIdle) { 226 | conn.conn.close(function(err) { }); 227 | array.splice(i, 1); 228 | } 229 | } 230 | } 231 | } 232 | 233 | Pool.prototype.release = function(conn, callback) { 234 | var self = this; 235 | if (typeof conn === 'object') { 236 | var uuid = conn.uuid; 237 | self._reserved = _.reject(self._reserved, function(conn) { 238 | return conn.uuid === uuid; 239 | }); 240 | 241 | if (conn.lastIdle) { 242 | conn.lastIdle = new Date().getTime(); 243 | } 244 | 245 | self._pool.unshift(conn); 246 | return callback(null); 247 | } else { 248 | return callback(new Error("INVALID CONNECTION")); 249 | } 250 | }; 251 | 252 | Pool.prototype.purge = function(callback) { 253 | var self = this; 254 | var conns = self._pool.concat(self._reserved); 255 | 256 | asyncjs.each(conns, 257 | function(conn, done) { 258 | if (typeof conn === 'object' && conn.conn !== null) { 259 | conn.conn.close(function(err) { 260 | //we don't want to prevent other connections from being closed 261 | done(); 262 | }); 263 | } else { 264 | done(); 265 | } 266 | }, 267 | function() { 268 | self._pool = []; 269 | self._reserved = []; 270 | 271 | callback(); 272 | } 273 | ); 274 | }; 275 | 276 | module.exports = Pool; 277 | -------------------------------------------------------------------------------- /lib/preparedstatement.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var ResultSet = require('./resultset'); 4 | var ResultSetMetaData = require('./resultsetmetadata'); 5 | var Statement = require('./statement'); 6 | var winston = require('winston'); 7 | 8 | function PreparedStatement(ps) { 9 | Statement.call(this, ps); 10 | this._ps = ps; 11 | } 12 | 13 | PreparedStatement.prototype = Object.create(Statement.prototype); 14 | PreparedStatement.prototype.constructor = PreparedStatement; 15 | 16 | PreparedStatement.prototype.addBatch = function(callback) { 17 | this._ps.addBatch(function(err) { 18 | if (err) return callback(err); 19 | callback(null); 20 | }); 21 | }; 22 | 23 | PreparedStatement.prototype.clearParameters = function(callback) { 24 | this._ps.clearParameters(function(err) { 25 | if (err) return callback(err); 26 | callback(null); 27 | }); 28 | }; 29 | 30 | PreparedStatement.prototype.execute = function(callback) { 31 | this._ps.execute(function(err, result) { 32 | if (err) { winston.error(err); return callback(err); } 33 | callback(null, result); 34 | }); 35 | }; 36 | 37 | PreparedStatement.prototype.executeBatch = function(callback) { 38 | this._ps.executeBatch(function(err, result) { 39 | if (err) { winston.error(err); return callback(err); } 40 | callback(null, result); 41 | }); 42 | }; 43 | 44 | PreparedStatement.prototype.executeQuery = function(callback) { 45 | this._ps.executeQuery(function(err, resultset) { 46 | if (err) { winston.error(err); return callback(err); } 47 | callback(null, new ResultSet(resultset)); 48 | }); 49 | }; 50 | 51 | PreparedStatement.prototype.executeUpdate = function(callback) { 52 | this._ps.executeUpdate(function(err, result) { 53 | if (err) { winston.error(err); return callback(err); } 54 | callback(null, result); 55 | }); 56 | }; 57 | 58 | PreparedStatement.prototype.getMetaData = function(callback) { 59 | this._ps.getMetaData(function(err, result) { 60 | if (err) return callback(err); 61 | callback(null, new ResultSetMetaData(result)); 62 | }); 63 | }; 64 | 65 | PreparedStatement.prototype.getParameterMetaData = function(callback) { 66 | callback(new Error("NOT IMPLEMENTED")); 67 | // this._ps.getParameterMetaData(function(err, result) { 68 | // if (err) callback(err); 69 | // callback(null, result); 70 | // }); 71 | }; 72 | 73 | PreparedStatement.prototype.setArray = function(index, val, callback) { 74 | callback(new Error("NOT IMPLEMENTED")); 75 | }; 76 | 77 | PreparedStatement.prototype.setAsciiStream = function(index, val, length, callback) { 78 | // length is optional, or can be int or long. 79 | callback(new Error("NOT IMPLEMENTED")); 80 | }; 81 | 82 | // val must be a java.math.BigDecimal 83 | PreparedStatement.prototype.setBigDecimal = function(index, val, callback) { 84 | this._ps.setBigDecimal(index, val, function(err) { 85 | if (err) return callback(err); 86 | callback(null); 87 | }); 88 | }; 89 | 90 | PreparedStatement.prototype.setBinaryStream = function(index, val, length, callback) { 91 | // length is optional, or can be int or long. 92 | callback(new Error("NOT IMPLEMENTED")); 93 | }; 94 | 95 | PreparedStatement.prototype.setBlob = function(index, val, length, callback) { 96 | // length is optional. Must be java.lang.Long if supplied, only valid with 97 | // InputStream. 98 | // val can be java.sql.Blob or java.io.InputStream 99 | callback(new Error("NOT IMPLEMENTED")); 100 | }; 101 | 102 | PreparedStatement.prototype.setBoolean = function(index, val, callback) { 103 | this._ps.setBoolean(index, val, function(err) { 104 | if (err) return callback(err); 105 | callback(null); 106 | }); 107 | }; 108 | 109 | PreparedStatement.prototype.setByte = function(index, val, callback) { 110 | this._ps.setByte(index, val, function(err) { 111 | if (err) return callback(err); 112 | callback(null); 113 | }); 114 | }; 115 | 116 | PreparedStatement.prototype.setBytes = function(index, val, callback) { 117 | this._ps.setBytes(index, val, function(err) { 118 | if (err) return callback(err); 119 | callback(null); 120 | }); 121 | }; 122 | 123 | PreparedStatement.prototype.setCharacterStream = function(index, val, length, callback) { 124 | // length is optional, or can be int or long. 125 | // val must be a java.io.Reader 126 | callback(new Error("NOT IMPLEMENTED")); 127 | }; 128 | 129 | PreparedStatement.prototype.setClob = function(index, val, length, callback) { 130 | // length is optional, must be a long, only valid with a java.io.Reader. 131 | // val can be a java.io.Reader or a java.sql.Clob 132 | callback(new Error("NOT IMPLEMENTED")); 133 | }; 134 | 135 | PreparedStatement.prototype.setDate = function(index, val, calendar, callback) { 136 | if (calendar === null) { 137 | this._ps.setDate(index, val, function(err) { 138 | if (err) return callback(err); 139 | callback(null); 140 | }); 141 | } else { 142 | this._ps.setDate(index, val, calendar, function(err) { 143 | if (err) return callback(err); 144 | callback(null); 145 | }); 146 | } 147 | }; 148 | 149 | PreparedStatement.prototype.setDouble = function(index, val, callback) { 150 | this._ps.setDouble(index, val, function(err) { 151 | if (err) return callback(err); 152 | callback(null); 153 | }); 154 | }; 155 | 156 | PreparedStatement.prototype.setFloat = function(index, val, callback) { 157 | this._ps.setFloat(index, val, function(err) { 158 | if (err) return callback(err); 159 | callback(null); 160 | }); 161 | }; 162 | 163 | PreparedStatement.prototype.setInt = function(index, val, callback) { 164 | this._ps.setInt(index, val, function(err) { 165 | if (err) return callback(err); 166 | callback(null); 167 | }); 168 | }; 169 | 170 | PreparedStatement.prototype.setLong = function(index, val, callback) { 171 | this._ps.setLong(index, val, function(err) { 172 | if (err) return callback(err); 173 | callback(null); 174 | }); 175 | }; 176 | 177 | PreparedStatement.prototype.setString = function(index, val, callback) { 178 | this._ps.setString(index, val, function(err) { 179 | if (err) return callback(err); 180 | callback(null); 181 | }); 182 | }; 183 | 184 | PreparedStatement.prototype.setTime = function(index, val, calendar, callback) { 185 | if (calendar === null) { 186 | this._ps.setTime(index, val, function(err) { 187 | if (err) return callback(err); 188 | callback(null); 189 | }); 190 | } else { 191 | this._ps.setTime(index, val, calendar, function(err) { 192 | if (err) return callback(err); 193 | callback(null); 194 | }); 195 | } 196 | }; 197 | 198 | PreparedStatement.prototype.setTimestamp = function(index, val, calendar, callback) { 199 | if (calendar === null) { 200 | this._ps.setTimestamp(index, val, function(err) { 201 | if (err) return callback(err); 202 | callback(null); 203 | }); 204 | } else { 205 | this._ps.setTimestamp(index, val, calendar, function(err) { 206 | if (err) return callback(err); 207 | callback(null); 208 | }); 209 | } 210 | }; 211 | 212 | module.exports = PreparedStatement; 213 | -------------------------------------------------------------------------------- /lib/resultset.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require('lodash'); 4 | var jinst = require('./jinst'); 5 | var ResultSetMetaData = require('./resultsetmetadata'); 6 | var java = jinst.getInstance(); 7 | var winston = require('winston'); 8 | 9 | if (!jinst.isJvmCreated()) { 10 | jinst.addOption("-Xrs"); 11 | } 12 | 13 | function ResultSet(rs) { 14 | this._rs = rs; 15 | this._holdability = (function () { 16 | var h = []; 17 | 18 | h[java.getStaticFieldValue('java.sql.ResultSet', 'CLOSE_CURSORS_AT_COMMIT')] = 'CLOSE_CURSORS_AT_COMMIT'; 19 | h[java.getStaticFieldValue('java.sql.ResultSet', 'HOLD_CURSORS_OVER_COMMIT')] = 'HOLD_CURSORS_OVER_COMMIT'; 20 | 21 | return h; 22 | })(); 23 | this._types = (function () { 24 | var typeNames = []; 25 | 26 | typeNames[java.getStaticFieldValue("java.sql.Types", "BIT")] = "Boolean"; 27 | typeNames[java.getStaticFieldValue("java.sql.Types", "TINYINT")] = "Short"; 28 | typeNames[java.getStaticFieldValue("java.sql.Types", "SMALLINT")] = "Short"; 29 | typeNames[java.getStaticFieldValue("java.sql.Types", "INTEGER")] = "Int"; 30 | typeNames[java.getStaticFieldValue("java.sql.Types", "BIGINT")] = "String"; 31 | typeNames[java.getStaticFieldValue("java.sql.Types", "FLOAT")] = "Float"; 32 | typeNames[java.getStaticFieldValue("java.sql.Types", "REAL")] = "Float"; 33 | typeNames[java.getStaticFieldValue("java.sql.Types", "DOUBLE")] = "Double"; 34 | typeNames[java.getStaticFieldValue("java.sql.Types", "NUMERIC")] = "BigDecimal"; 35 | typeNames[java.getStaticFieldValue("java.sql.Types", "DECIMAL")] = "BigDecimal"; 36 | typeNames[java.getStaticFieldValue("java.sql.Types", "CHAR")] = "String"; 37 | typeNames[java.getStaticFieldValue("java.sql.Types", "VARCHAR")] = "String"; 38 | typeNames[java.getStaticFieldValue("java.sql.Types", "LONGVARCHAR")] = "String"; 39 | typeNames[java.getStaticFieldValue("java.sql.Types", "DATE")] = "Date"; 40 | typeNames[java.getStaticFieldValue("java.sql.Types", "TIME")] = "Time"; 41 | typeNames[java.getStaticFieldValue("java.sql.Types", "TIMESTAMP")] = "Timestamp"; 42 | typeNames[java.getStaticFieldValue("java.sql.Types", "BOOLEAN")] = "Boolean"; 43 | typeNames[java.getStaticFieldValue("java.sql.Types", "NCHAR")] = "String"; 44 | typeNames[java.getStaticFieldValue("java.sql.Types", "NVARCHAR")] = "String"; 45 | typeNames[java.getStaticFieldValue("java.sql.Types", "LONGNVARCHAR")] = "String"; 46 | typeNames[java.getStaticFieldValue("java.sql.Types", "BINARY")] = "Bytes"; 47 | typeNames[java.getStaticFieldValue("java.sql.Types", "VARBINARY")] = "Bytes"; 48 | typeNames[java.getStaticFieldValue("java.sql.Types", "LONGVARBINARY")] = "Bytes"; 49 | typeNames[java.getStaticFieldValue("java.sql.Types", "BLOB")] = "Bytes"; 50 | 51 | return typeNames; 52 | })(); 53 | } 54 | 55 | ResultSet.prototype.toObjArray = function (callback) { 56 | this.toObject(function (err, result) { 57 | if (err) return callback(err); 58 | callback(null, result.rows); 59 | }); 60 | }; 61 | 62 | ResultSet.prototype.toObject = function (callback) { 63 | this.toObjectIter(function (err, rs) { 64 | if (err) return callback(err); 65 | 66 | var rowIter = rs.rows; 67 | var rows = []; 68 | var row = rowIter.next(); 69 | 70 | while (!row.done) { 71 | rows.push(row.value); 72 | row = rowIter.next(); 73 | } 74 | 75 | rs.rows = rows; 76 | return callback(null, rs); 77 | }); 78 | }; 79 | 80 | ResultSet.prototype.toObjectIter = function (callback) { 81 | var self = this; 82 | 83 | self.getMetaData(function (err, rsmd) { 84 | if (err) { 85 | return callback(err); 86 | } else { 87 | var colsmetadata = []; 88 | 89 | rsmd.getColumnCount(function (err, colcount) { 90 | 91 | if (err) 92 | return callback(err); 93 | 94 | // Get some column metadata. 95 | _.each(_.range(1, colcount + 1), function (i) { 96 | colsmetadata.push({ 97 | label: rsmd._rsmd.getColumnLabelSync(i), 98 | type: rsmd._rsmd.getColumnTypeSync(i) 99 | }); 100 | }); 101 | 102 | callback(null, { 103 | labels: _.map(colsmetadata, 'label'), 104 | types: _.map(colsmetadata, 'type'), 105 | rows: { 106 | next: function () { 107 | var nextRow; 108 | try { 109 | nextRow = self._rs.nextSync(); // this row can lead to Java RuntimeException - sould be cathced. 110 | } 111 | catch (error) { 112 | callback(error); 113 | } 114 | if (!nextRow) { 115 | return { 116 | done: true 117 | }; 118 | } 119 | 120 | var result = {}; 121 | 122 | // loop through each column 123 | _.each(_.range(1, colcount + 1), function (i) { 124 | var cmd = colsmetadata[i - 1]; 125 | var type = self._types[cmd.type] || 'String'; 126 | if (type === 'BigDecimal') type = 'Double'; 127 | var getter = 'get' + type + 'Sync'; 128 | 129 | if (type === 'Date' || type === 'Time' || type === 'Timestamp') { 130 | var dateVal = self._rs[getter](cmd.label); 131 | result[cmd.label] = dateVal ? dateVal.toString() : null; 132 | } else { 133 | // If the column is an integer and is null, set result to null and continue 134 | if (type === 'Int' && _.isNull(self._rs.getObjectSync(cmd.label))) { 135 | result[cmd.label] = null; 136 | return; 137 | } 138 | 139 | result[cmd.label] = self._rs[getter](cmd.label); 140 | } 141 | }); 142 | 143 | return { 144 | value: result, 145 | done: false 146 | }; 147 | } 148 | } 149 | }); 150 | }); 151 | } 152 | }); 153 | }; 154 | 155 | ResultSet.prototype.close = function (callback) { 156 | this._rs.close(function (err) { 157 | if (err) { 158 | return callback(err); 159 | } else { 160 | return callback(null); 161 | } 162 | }); 163 | }; 164 | 165 | ResultSet.prototype.getMetaData = function (callback) { 166 | this._rs.getMetaData(function (err, rsmd) { 167 | if (err) { 168 | return callback(err); 169 | } else { 170 | return callback(null, new ResultSetMetaData(rsmd)); 171 | } 172 | }); 173 | }; 174 | 175 | module.exports = ResultSet; 176 | -------------------------------------------------------------------------------- /lib/resultsetmetadata.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | 4 | function ResultSetMetaData(rsmd) { 5 | this._rsmd = rsmd; 6 | } 7 | 8 | ResultSetMetaData.prototype.getColumnCount = function (callback) { 9 | this._rsmd.getColumnCount(function (err, count) { 10 | try { 11 | if (err) { 12 | return callback(err); 13 | } else { 14 | return callback(null, count); 15 | } 16 | } catch (err) { 17 | return callback(err); 18 | } 19 | }); 20 | }; 21 | 22 | ResultSetMetaData.prototype.getColumnName = function (column, callback) { 23 | this._rsmd.getColumnName(column, function (err, name) { 24 | try { 25 | if (err) { 26 | return callback(err); 27 | } else { 28 | return callback(null, name); 29 | } 30 | } catch (err) { 31 | return callback(err); 32 | } 33 | }); 34 | }; 35 | 36 | module.exports = ResultSetMetaData; -------------------------------------------------------------------------------- /lib/sqlwarning.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | function SQLWarning(sqlwarning) { 4 | this._sqlwarning = sqlwarning; 5 | } 6 | 7 | module.exports = SQLWarning; 8 | -------------------------------------------------------------------------------- /lib/statement.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true */ 2 | "use strict"; 3 | var _ = require('lodash'); 4 | var ResultSet = require('./resultset'); 5 | var jinst = require('./jinst'); 6 | var java = jinst.getInstance(); 7 | 8 | function Statement(s) { 9 | this._s = s; 10 | } 11 | 12 | Statement.prototype.addBatch = function(sql, callback) { 13 | return callback(new Error("NOT IMPLEMENTED")); 14 | } 15 | 16 | Statement.prototype.cancel = function(callback) { 17 | this._s.cancel(function(err) { 18 | if (err) { 19 | return callback(err); 20 | } else { 21 | return callback(null); 22 | } 23 | }); 24 | } 25 | 26 | Statement.prototype.clearBatch = function(callback) { 27 | this._s.clearBatch(function(err) { 28 | if (err) { 29 | return callback(err); 30 | } else { 31 | return callback(null); 32 | } 33 | }); 34 | } 35 | 36 | Statement.prototype.close = function(callback) { 37 | this._s.close(function(err) { 38 | if (err) { 39 | return callback(err); 40 | } else { 41 | return callback(null); 42 | } 43 | }); 44 | }; 45 | 46 | Statement.prototype.executeUpdate = function(sql, arg1, callback) { 47 | // Get arguments as an array 48 | var args = Array.prototype.slice.call(arguments); 49 | 50 | // Pull the callback off the end of the arguments 51 | callback = args.pop(); 52 | 53 | // Check arguments for validity, and return error if invalid 54 | if(! (_.isString(args[0]) && _.isUndefined(args[1]))) { 55 | return callback(new Error('INVALID ARGUMENTS')); 56 | } 57 | 58 | // Push a callback handler onto the arguments 59 | args.push(function(err, count) { 60 | if (err) { 61 | return callback(err); 62 | } 63 | return callback(null, count); 64 | }); 65 | 66 | // Forward modified arguments to _s.executeUpdate 67 | this._s.executeUpdate.apply(this._s, args); 68 | }; 69 | 70 | Statement.prototype.executeQuery = function(sql, callback) { 71 | if (typeof sql === 'string') { 72 | this._s.executeQuery(sql, function(err, resultset) { 73 | if (err) { 74 | return callback(err); 75 | } else { 76 | return callback(null, new ResultSet(resultset)); 77 | } 78 | }); 79 | } else { 80 | return callback(new Error('INVALID ARGUMENTS')); 81 | } 82 | }; 83 | 84 | Statement.prototype.execute = function(sql, callback) { 85 | var s = this._s; 86 | if (typeof sql === 'string') { 87 | s.execute(sql, function(err, isResultSet) { 88 | if (err) { 89 | return callback(err); 90 | } 91 | if (isResultSet) { 92 | s.getResultSet(function(err, resultset) { 93 | if (err) { 94 | return callback(err); 95 | } 96 | return callback(null, new ResultSet(resultset)); 97 | }); 98 | } else { 99 | s.getUpdateCount(function(err, count) { 100 | if (err) { 101 | return callback(err); 102 | } 103 | return callback(null, count); 104 | }); 105 | } 106 | }); 107 | } else { 108 | return callback(new Error('INVALID ARGUMENTS')); 109 | } 110 | }; 111 | 112 | Statement.prototype.getFetchSize = function(callback) { 113 | this._s.getFetchSize(function(err, fetchSize) { 114 | if (err) { 115 | return callback(err); 116 | } else { 117 | return callback(null, fetchSize); 118 | } 119 | }); 120 | }; 121 | 122 | Statement.prototype.setFetchSize = function(rows, callback) { 123 | this._s.setFetchSize(rows, function(err) { 124 | if (err) { 125 | return callback(err); 126 | } else { 127 | return callback(null); 128 | } 129 | }); 130 | }; 131 | 132 | Statement.prototype.getMaxRows = function(callback) { 133 | this._s.getMaxRows(function(err, max) { 134 | if (err) { 135 | return callback(err); 136 | } else { 137 | return callback(null, max); 138 | } 139 | }); 140 | }; 141 | 142 | Statement.prototype.setMaxRows = function(max, callback) { 143 | this._s.setMaxRows(max, function(err) { 144 | if (err) { 145 | return callback(err); 146 | } else { 147 | return callback(null); 148 | } 149 | }); 150 | }; 151 | 152 | Statement.prototype.getQueryTimeout = function(callback) { 153 | this._s.getQueryTimeout(function(err, queryTimeout) { 154 | if (err) { 155 | return callback(err); 156 | } else { 157 | return callback(null, queryTimeout); 158 | } 159 | }); 160 | }; 161 | 162 | Statement.prototype.setQueryTimeout = function(seconds, callback) { 163 | this._s.setQueryTimeout(seconds, function(err) { 164 | if (err) { 165 | return callback(err); 166 | } else { 167 | return callback(null); 168 | } 169 | }); 170 | }; 171 | 172 | Statement.prototype.getGeneratedKeys = function(callback) { 173 | this._s.getGeneratedKeys(function(err, resultset) { 174 | if(err) { 175 | return callback(err); 176 | } 177 | return callback(null, new ResultSet(resultset)); 178 | }); 179 | }; 180 | 181 | jinst.events.once('initialized', function onInitialized() { 182 | // The constant indicating that the current ResultSet object should be closed 183 | // when calling getMoreResults. 184 | Statement.CLOSE_CURRENT_RESULT = java.getStaticFieldValue('java.sql.Statement', 'CLOSE_CURRENT_RESULT'); 185 | 186 | // The constant indicating that the current ResultSet object should not be 187 | // closed when calling getMoreResults. 188 | Statement.KEEP_CURRENT_RESULT = java.getStaticFieldValue('java.sql.Statement', 'KEEP_CURRENT_RESULT'); 189 | 190 | // The constant indicating that all ResultSet objects that have previously been 191 | // kept open should be closed when calling getMoreResults. 192 | Statement.CLOSE_ALL_RESULTS = java.getStaticFieldValue('java.sql.Statement', 'CLOSE_ALL_RESULTS'); 193 | 194 | // The constant indicating that a batch statement executed successfully but that 195 | // no count of the number of rows it affected is available. 196 | Statement.SUCCESS_NO_INFO = java.getStaticFieldValue('java.sql.Statement', 'SUCCESS_NO_INFO'); 197 | 198 | // The constant indicating that an error occured while executing a batch 199 | // statement. 200 | Statement.EXECUTE_FAILED = java.getStaticFieldValue('java.sql.Statement', 'EXECUTE_FAILED'); 201 | 202 | // The constant indicating that generated keys should be made available for 203 | // retrieval. 204 | Statement.RETURN_GENERATED_KEYS = java.getStaticFieldValue('java.sql.Statement', 'RETURN_GENERATED_KEYS'); 205 | 206 | // The constant indicating that generated keys should not be made available for 207 | // retrieval. 208 | Statement.NO_GENERATED_KEYS = java.getStaticFieldValue('java.sql.Statement', 'NO_GENERATED_KEYS'); 209 | }); 210 | 211 | module.exports = Statement; 212 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jdbc", 3 | "version": "0.7.7", 4 | "description": "Node Module JDBC wrapper", 5 | "main": "index.js", 6 | "dependencies": { 7 | "async": "3.2.4", 8 | "java": "^0.15.0", 9 | "lodash": "4.17.21", 10 | "uuid": "9.0.0", 11 | "winston": "3.8.2" 12 | }, 13 | "devDependencies": { 14 | "jshint": "2.13.6", 15 | "lolex": "^6.0.0", 16 | "nodeunit": "~0.11.3", 17 | "q": "^1.5.1" 18 | }, 19 | "scripts": { 20 | "pretest": "bash bin/startdbs", 21 | "test": "nodeunit test", 22 | "posttest": "bash bin/stopdbs", 23 | "lint": "jshint lib/**.js test/**.js" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/CraZySacX/node-jdbc.git" 28 | }, 29 | "directories": { 30 | "doc": ".", 31 | "lib": "lib" 32 | }, 33 | "keywords": [ 34 | "node", 35 | "jdbc", 36 | "wrapper" 37 | ], 38 | "engines": { 39 | "node": ">=0.10" 40 | }, 41 | "author": "Jason Ozias ", 42 | "license": "MIT", 43 | "readmeFilename": "README.md" 44 | } 45 | -------------------------------------------------------------------------------- /test/sqltool.rc: -------------------------------------------------------------------------------- 1 | urlid xdb 2 | url jdbc:hsqldb:hsql://localhost/xdb;shutdown=true 3 | username SA 4 | password 5 | -------------------------------------------------------------------------------- /test/test-connection.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var dm = require('../lib/drivermanager'); 4 | var Connection = require('../lib/connection'); 5 | var ResultSet = require('../lib/resultset'); 6 | var java = jinst.getInstance(); 7 | 8 | if (!jinst.isJvmCreated()) { 9 | jinst.addOption("-Xrs"); 10 | jinst.setupClasspath(['./drivers/hsqldb.jar', 11 | './drivers/derby.jar', 12 | './drivers/derbyclient.jar', 13 | './drivers/derbytools.jar']); 14 | } 15 | 16 | var config = { 17 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 18 | user : 'SA', 19 | password: '' 20 | }; 21 | 22 | var testconn = null; 23 | 24 | module.exports = { 25 | setUp: function(callback) { 26 | if (testconn === null) { 27 | dm.getConnection(config.url, config.user, config.password, function(err, conn) { 28 | if (err) { 29 | console.log(err); 30 | } else { 31 | testconn = new Connection(conn); 32 | callback(); 33 | } 34 | }); 35 | } else { 36 | callback(); 37 | } 38 | }, 39 | testabort: function(test) { 40 | testconn.abort(null, function(err) { 41 | test.expect(2); 42 | test.ok(err); 43 | test.equal("NOT IMPLEMENTED", err.message); 44 | test.done(); 45 | }); 46 | }, 47 | testclearwarnings: function(test) { 48 | testconn.clearWarnings(function(err) { 49 | test.expect(1); 50 | test.equal(null, err); 51 | test.done(); 52 | }); 53 | }, 54 | testclose: function(test) { 55 | testconn.close(function(err) { 56 | test.expect(1); 57 | test.equal(null, err); 58 | testconn = null; 59 | test.done(); 60 | }); 61 | }, 62 | testcloseclosed: function(test) { 63 | testconn._conn = null; 64 | testconn.close(function(err) { 65 | test.expect(1); 66 | test.equal(null, err); 67 | testconn = null; 68 | test.done(); 69 | }); 70 | }, 71 | testcommit: function(test) { 72 | testconn.commit(function(err) { 73 | test.expect(1); 74 | test.equal(null, err); 75 | test.done(); 76 | }); 77 | }, 78 | testcreatearrayof: function(test) { 79 | testconn.createArrayOf(null, null, function(err) { 80 | test.expect(2); 81 | test.ok(err); 82 | test.equal("NOT IMPLEMENTED", err.message); 83 | test.done(); 84 | }); 85 | }, 86 | testcreateblob: function(test) { 87 | testconn.createBlob(function(err) { 88 | test.expect(2); 89 | test.ok(err); 90 | test.equal("NOT IMPLEMENTED", err.message); 91 | test.done(); 92 | }); 93 | }, 94 | testcreateclob: function(test) { 95 | testconn.createClob(function(err) { 96 | test.expect(2); 97 | test.ok(err); 98 | test.equal("NOT IMPLEMENTED", err.message); 99 | test.done(); 100 | }); 101 | }, 102 | testcreatenclob: function(test) { 103 | testconn.createNClob(function(err) { 104 | test.expect(2); 105 | test.ok(err); 106 | test.equal("NOT IMPLEMENTED", err.message); 107 | test.done(); 108 | }); 109 | }, 110 | testcreatesqlxml: function(test) { 111 | testconn.createSQLXML(function(err) { 112 | test.expect(2); 113 | test.ok(err); 114 | test.equal("NOT IMPLEMENTED", err.message); 115 | test.done(); 116 | }); 117 | }, 118 | testcreatestatment: function(test) { 119 | testconn.createStatement(function(err, statement) { 120 | test.expect(2); 121 | test.equal(null, err); 122 | test.ok(statement); 123 | test.done(); 124 | }); 125 | }, 126 | testcreatestatement1: function(test) { 127 | testconn.createStatement(0, 0, function(err, statement) { 128 | test.expect(2); 129 | test.equal(null, err); 130 | test.ok(statement); 131 | test.done(); 132 | }); 133 | }, 134 | testcreatestatement2: function(test) { 135 | testconn.createStatement(0, 0, 0, function(err, statement) { 136 | test.expect(2); 137 | test.equal(null, err); 138 | test.ok(statement); 139 | test.done(); 140 | }); 141 | }, 142 | testcreatestruct: function(test) { 143 | testconn.createStruct(null, null, function(err) { 144 | test.expect(2); 145 | test.ok(err); 146 | test.equal("NOT IMPLEMENTED", err.message); 147 | test.done(); 148 | }); 149 | }, 150 | testgetautocommit: function(test) { 151 | testconn.getAutoCommit(function(err, result) { 152 | test.expect(2); 153 | test.equal(null, err); 154 | test.equal(true, result); 155 | test.done(); 156 | }); 157 | }, 158 | testgetcatalog: function(test) { 159 | testconn.getCatalog(function(err, catalog) { 160 | test.expect(2); 161 | test.equal(null, err); 162 | test.ok(catalog); 163 | test.done(); 164 | }); 165 | }, 166 | testgetclientinfo: function(test) { 167 | testconn.getClientInfo(function(err, props) { 168 | test.expect(2); 169 | test.equal(null, err); 170 | test.equal(null, props); 171 | test.done(); 172 | }); 173 | }, 174 | testgetholdability: function(test) { 175 | testconn.getHoldability(function(err, holdability) { 176 | test.expect(2); 177 | test.equal(null, err); 178 | test.equal(null, holdability); 179 | test.done(); 180 | }); 181 | }, 182 | testgetmetadata: function(test) { 183 | testconn.getMetaData(function(err, metadata) { 184 | test.expect(2); 185 | test.equal(null, err); 186 | test.ok(metadata); 187 | test.done(); 188 | }); 189 | }, 190 | testgetnetworktimeout: function(test) { 191 | testconn.getNetworkTimeout(function(err, ms) { 192 | test.expect(2); 193 | test.equal(null, err); 194 | test.equal(0, ms); 195 | test.done(); 196 | }); 197 | }, 198 | testgetschema: function(test) { 199 | testconn.getSchema(function(err, schema) { 200 | test.expect(2); 201 | test.equal(null, err); 202 | test.ok(schema); 203 | test.done(); 204 | }); 205 | }, 206 | testgettransactionisolation: function(test) { 207 | testconn.getTransactionIsolation(function(err, txniso) { 208 | test.expect(3); 209 | test.equal(null, err); 210 | test.ok(txniso); 211 | test.equal(txniso, "TRANSACTION_READ_COMMITTED"); 212 | test.done(); 213 | }); 214 | }, 215 | testgettypemap: function(test) { 216 | testconn.getTypeMap(function(err, map) { 217 | test.expect(2); 218 | test.equal(null, err); 219 | test.ok(map); 220 | test.done(); 221 | }); 222 | }, 223 | testgetwarnings: function(test) { 224 | testconn.getWarnings(function(err, sqlwarning) { 225 | test.expect(2); 226 | test.equal(null, err); 227 | test.ok(sqlwarning); 228 | test.done(); 229 | }); 230 | }, 231 | testisclosed: function(test) { 232 | testconn.isClosed(function(err, closed) { 233 | test.expect(2); 234 | test.equal(null, err); 235 | test.equal(false, closed); 236 | test.done(); 237 | }); 238 | }, 239 | testisreadonly: function(test) { 240 | testconn.isReadOnly(function(err, readonly) { 241 | test.expect(2); 242 | test.equal(null, err); 243 | test.equal(false, readonly); 244 | test.done(); 245 | }); 246 | }, 247 | testisvalid: function(test) { 248 | testconn.isValid(0, function(err, valid) { 249 | test.expect(2); 250 | test.equal(null, err); 251 | test.ok(valid); 252 | test.done(); 253 | }); 254 | }, 255 | testnativesql: function(test) { 256 | testconn.nativeSQL(null, function(err) { 257 | test.expect(2); 258 | test.ok(err); 259 | test.equal("NOT IMPLEMENTED", err.message); 260 | test.done(); 261 | }); 262 | }, 263 | testpreparecallsql: function(test) { 264 | testconn.prepareCall("{ call database() }", function(err, callablestatement) { 265 | test.expect(2); 266 | test.equal(null, err); 267 | test.ok(callablestatement); 268 | test.done(); 269 | }); 270 | }, 271 | testpreparestatement: function(test) { 272 | testconn.prepareCall("SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS;", function(err, preparedstatement) { 273 | test.expect(2); 274 | if (err) { 275 | console.log(err); 276 | } 277 | test.equal(null, err); 278 | test.ok(preparedstatement); 279 | test.done(); 280 | }); 281 | }, 282 | testreleasesavepoint: function(test) { 283 | testconn.setAutoCommit(false, function(err){ 284 | if (err) { 285 | console.log(err); 286 | } else { 287 | testconn.setSavepoint(function(err, savepoint) { 288 | if (err) { 289 | console.log(err); 290 | } else { 291 | testconn.releaseSavepoint(savepoint, function(err) { 292 | test.expect(1); 293 | test.equal(null, err); 294 | test.done(); 295 | }); 296 | } 297 | }); 298 | } 299 | }); 300 | }, 301 | testrollback: function(test) { 302 | testconn.setAutoCommit(false, function(err){ 303 | if (err) { 304 | console.log(err); 305 | } else { 306 | testconn.rollback(function(err) { 307 | test.expect(1); 308 | test.equal(null, err); 309 | test.done(); 310 | }); 311 | } 312 | }); 313 | }, 314 | testrollbacksavepoint: function(test) { 315 | testconn.setAutoCommit(false, function(err){ 316 | if (err) { 317 | console.log(err); 318 | } else { 319 | testconn.setSavepoint(function(err, savepoint) { 320 | if (err) { 321 | console.log(err); 322 | } else { 323 | testconn.rollback(savepoint, function(err) { 324 | test.expect(1); 325 | test.equal(null, err); 326 | test.done(); 327 | }); 328 | } 329 | }); 330 | } 331 | }); 332 | }, 333 | testsetcatalog: function(test) { 334 | testconn.setCatalog('PUBLIC', function(err){ 335 | test.expect(1); 336 | if (err) { console.log(err); } 337 | test.equal(null, err); 338 | test.done(); 339 | }); 340 | }, 341 | testsetclientinfo: function(test) { 342 | // Note that HSQLDB doesn't support this feature so it errors. 343 | testconn.setClientInfo(null, 'TEST', 'ME', function(err){ 344 | test.expect(1); 345 | test.ok(err); 346 | test.done(); 347 | }); 348 | }, 349 | testsetholdability: function(test) { 350 | var hold = (new ResultSet(null))._holdability.indexOf('HOLD_CURSORS_OVER_COMMIT'); 351 | testconn.setHoldability(hold, function(err){ 352 | test.expect(1); 353 | if (err) { console.log(err); } 354 | test.equal(null, err); 355 | test.done(); 356 | }); 357 | }, 358 | testsetnetworktimeout: function(test) { 359 | testconn.setNetworkTimeout(null, null, function(err) { 360 | test.expect(2); 361 | test.ok(err); 362 | test.equal("NOT IMPLEMENTED", err.message); 363 | test.done(); 364 | }); 365 | }, 366 | testsetreadonly: function(test) { 367 | testconn.setReadOnly(true, function(err) { 368 | test.expect(1); 369 | test.equal(null, err); 370 | test.done(); 371 | }); 372 | }, 373 | testsetsavepoint: function(test) { 374 | testconn.setAutoCommit(false, function(err){ 375 | if (err) { 376 | console.log(err); 377 | } else { 378 | testconn.setSavepoint(function(err, savepoint) { 379 | test.expect(2); 380 | test.equal(null, err); 381 | test.ok(savepoint); 382 | test.done(); 383 | }); 384 | } 385 | }); 386 | }, 387 | testsetsavepointname: function(test) { 388 | testconn.setAutoCommit(false, function(err){ 389 | if (err) { 390 | console.log(err); 391 | } else { 392 | testconn.setSavepoint("SAVEPOINT", function(err, savepoint) { 393 | test.expect(2); 394 | test.equal(null, err); 395 | test.ok(savepoint); 396 | test.done(); 397 | }); 398 | } 399 | }); 400 | }, 401 | testsetschema: function(test) { 402 | testconn.setSchema('PUBLIC', function(err) { 403 | test.expect(1); 404 | test.equal(null, err); 405 | test.done(); 406 | }); 407 | }, 408 | testsettransactionisolation: function(test) { 409 | var txniso = testconn._txniso.indexOf('TRANSACTION_SERIALIZABLE'); 410 | testconn.setTransactionIsolation(txniso, function(err) { 411 | test.expect(1); 412 | test.equal(null, err); 413 | test.done(); 414 | }); 415 | }, 416 | testsettypemap: function(test) { 417 | testconn.setTypeMap(null, function(err) { 418 | test.expect(2); 419 | test.ok(err); 420 | test.equal("NOT IMPLEMENTED", err.message); 421 | test.done(); 422 | }); 423 | }, 424 | }; 425 | -------------------------------------------------------------------------------- /test/test-derby.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var derby = new JDBC({ 14 | url: 'jdbc:derby://localhost:1527/testdb;create=true' 15 | }); 16 | 17 | var testconn = null; 18 | var testDate = Date.now(); 19 | 20 | module.exports = { 21 | setUp: function(callback) { 22 | if (testconn === null && derby._pool.length > 0) { 23 | derby.reserve(function(err, conn) { 24 | testconn = conn; 25 | callback(); 26 | }); 27 | } else { 28 | callback(); 29 | } 30 | }, 31 | tearDown: function(callback) { 32 | if (testconn) { 33 | derby.release(testconn, function(err) { 34 | callback(); 35 | }); 36 | } else { 37 | callback(); 38 | } 39 | }, 40 | testinitialize: function(test) { 41 | derby.initialize(function(err) { 42 | test.expect(1); 43 | test.equal(err, null); 44 | test.done(); 45 | }); 46 | }, 47 | testcreatetable: function(test) { 48 | testconn.conn.createStatement(function(err, statement) { 49 | if (err) { 50 | console.log(err); 51 | } else { 52 | var create = "CREATE TABLE blah "; 53 | create += "(id int, bi bigint, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP, dollars NUMERIC(5,2))"; 54 | statement.executeUpdate(create, function(err, result) { 55 | test.expect(1); 56 | test.equal(null, err); 57 | test.done(); 58 | }); 59 | } 60 | }); 61 | }, 62 | testinsert: function(test) { 63 | testconn.conn.createStatement(function(err, statement) { 64 | if (err) { 65 | console.log(err); 66 | } else { 67 | var insert = "INSERT INTO blah VALUES "; 68 | insert += "(1, 9223372036854775807, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, 12.01)"; 69 | statement.executeUpdate(insert, function(err, result) { 70 | test.expect(2); 71 | test.equal(null, err); 72 | test.ok(result && result == 1); 73 | test.done(); 74 | }); 75 | } 76 | }); 77 | }, 78 | testupdate: function(test) { 79 | testconn.conn.createStatement(function(err, statement) { 80 | if (err) { 81 | console.log(err); 82 | } else { 83 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason'", function(err, result) { 84 | test.expect(2); 85 | test.equal(null, err); 86 | test.ok(result && result == 1); 87 | test.done(); 88 | }); 89 | } 90 | }); 91 | }, 92 | testselect: function(test) { 93 | testconn.conn.createStatement(function(err, statement) { 94 | if (err) { 95 | console.log(err); 96 | } else { 97 | statement.executeQuery("SELECT * FROM blah", function(err, resultset) { 98 | test.expect(9); 99 | test.equal(null, err); 100 | test.ok(resultset); 101 | resultset.toObjArray(function(err, results) { 102 | test.equal(results.length, 1); 103 | test.equal(results[0].BI, '9223372036854775807'); 104 | test.equal(results[0].NAME, 'Jason'); 105 | test.ok(results[0].DATE); 106 | test.ok(results[0].TIME); 107 | test.ok(results[0].TIMESTAMP); 108 | test.equal(results[0].DOLLARS, 12.01) 109 | test.done(); 110 | }); 111 | }); 112 | } 113 | }); 114 | }, 115 | testpreparedselectsetint: function(test) { 116 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id=?",function(err, statement) { 117 | if (err) { 118 | console.log(err); 119 | } else { 120 | statement.setInt(1, 2, function(err) { 121 | if (err) { 122 | console.log(err); 123 | } 124 | else { 125 | statement.executeQuery(function(err, resultset) { 126 | test.expect(3); 127 | test.equal(null, err); 128 | test.ok(resultset); 129 | resultset.toObjArray(function(err, results) { 130 | test.equal(results.length, 1); 131 | test.done(); 132 | }); 133 | }); 134 | } 135 | }); 136 | } 137 | }); 138 | }, 139 | testpreparedselectsetstring: function(test) { 140 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE name=?",function(err, statement) { 141 | if (err) { 142 | console.log(err); 143 | } else { 144 | statement.setString(1,'Jason', function(err) { 145 | if (err) { 146 | console.log(err); 147 | } 148 | else { 149 | statement.executeQuery(function(err, resultset) { 150 | test.expect(3); 151 | test.equal(null, err); 152 | test.ok(resultset); 153 | resultset.toObjArray(function(err, results) { 154 | test.equal(results.length, 1); 155 | test.done(); 156 | }); 157 | }); 158 | } 159 | }); 160 | } 161 | }); 162 | }, 163 | testpreparedinsertsetdate: function(test) { 164 | var myjava = jinst.getInstance(); 165 | testconn.conn.prepareStatement("INSERT INTO blah (id,name,date) VALUES (3,'Test',?)",function(err, statement) { 166 | if (err) { 167 | console.log(err); 168 | } else { 169 | var sqlDate = myjava.newInstanceSync("java.sql.Date", myjava.newLong(testDate)); 170 | statement.setDate(1, sqlDate, null, function(err) { 171 | if (err) { 172 | console.log(err); 173 | } else { 174 | statement.executeUpdate(function(err, numrows) { 175 | if (err) { 176 | console.log(err); 177 | } else { 178 | test.expect(2); 179 | test.equal(null, err); 180 | test.equal(1, numrows); 181 | test.done(); 182 | } 183 | }); 184 | } 185 | }); 186 | } 187 | }); 188 | }, 189 | testpreparedselectsetdate: function(test) { 190 | var myjava = jinst.getInstance(); 191 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id = 3 AND date = ?",function(err, statement) { 192 | if (err) { 193 | console.log(err); 194 | } else { 195 | var sqlDate = myjava.newInstanceSync("java.sql.Date", myjava.newLong(testDate)); 196 | statement.setDate(1, sqlDate, null, function(err) { 197 | if (err) { 198 | console.log(err); 199 | } 200 | else { 201 | statement.executeQuery(function(err, resultset) { 202 | if (err) { 203 | console.log(err); 204 | } else { 205 | test.expect(3); 206 | test.equal(null, err); 207 | test.ok(resultset); 208 | resultset.toObjArray(function(err, results) { 209 | if (err) { 210 | console.log(err); 211 | } else { 212 | test.equal(results.length, 1); 213 | test.done(); 214 | } 215 | }); 216 | } 217 | }); 218 | } 219 | }); 220 | } 221 | }); 222 | }, 223 | testpreparedinsertsettimestamp: function(test) { 224 | var myjava = jinst.getInstance(); 225 | testconn.conn.prepareStatement("INSERT INTO blah (id,name,timestamp) VALUES (4,'Test',?)",function(err, statement) { 226 | if (err) { 227 | console.log(err); 228 | } else { 229 | var sqlTimestamp = myjava.newInstanceSync("java.sql.Timestamp", myjava.newLong(testDate)); 230 | statement.setTimestamp(1, sqlTimestamp, null, function(err) { 231 | if (err) { 232 | console.log(err); 233 | } 234 | else { 235 | statement.executeUpdate(function(err, numrows) { 236 | if (err) { 237 | console.log(err); 238 | } else { 239 | test.expect(2); 240 | test.equal(null, err); 241 | test.equal(1,numrows); 242 | test.done(); 243 | } 244 | }); 245 | } 246 | }); 247 | } 248 | }); 249 | }, 250 | testpreparedselectsettimestamp: function(test) { 251 | var myjava = jinst.getInstance(); 252 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id = 4 AND timestamp = ?",function(err, statement) { 253 | if (err) { 254 | console.log(err); 255 | } else { 256 | var sqlTimestamp = myjava.newInstanceSync("java.sql.Timestamp", myjava.newLong(testDate)); 257 | statement.setTimestamp(1, sqlTimestamp, null, function(err) { 258 | if (err) { 259 | console.log(err); 260 | } 261 | else { 262 | statement.executeQuery(function(err, resultset) { 263 | if (err) { 264 | console.log(err); 265 | } else { 266 | test.expect(3); 267 | test.equal(null, err); 268 | test.ok(resultset); 269 | resultset.toObjArray(function(err, results) { 270 | if (err) { 271 | console.log(err); 272 | } else { 273 | test.equal(results.length, 1); 274 | test.done(); 275 | } 276 | }); 277 | } 278 | }); 279 | } 280 | }); 281 | } 282 | }); 283 | }, 284 | testdelete: function(test) { 285 | testconn.conn.createStatement(function(err, statement) { 286 | if (err) { 287 | console.log(err); 288 | } else { 289 | statement.executeUpdate("DELETE FROM blah WHERE id = 2", function(err, result) { 290 | test.expect(2); 291 | test.equal(null, err); 292 | test.ok(result && result == 1); 293 | test.done(); 294 | }); 295 | } 296 | }); 297 | }, 298 | testdroptable: function(test) { 299 | testconn.conn.createStatement(function(err, statement) { 300 | if (err) { 301 | console.log(err); 302 | } else { 303 | statement.executeUpdate("DROP TABLE blah", function(err, result) { 304 | test.expect(1); 305 | test.equal(null, err); 306 | test.done(); 307 | }); 308 | } 309 | }); 310 | } 311 | }; 312 | -------------------------------------------------------------------------------- /test/test-drivermanager.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var dm = require('../lib/drivermanager.js'); 4 | var java = jinst.getInstance(); 5 | 6 | if (!jinst.isJvmCreated()) { 7 | jinst.addOption("-Xrs"); 8 | jinst.setupClasspath(['./drivers/hsqldb.jar', 9 | './drivers/derby.jar', 10 | './drivers/derbyclient.jar', 11 | './drivers/derbytools.jar']); 12 | } 13 | 14 | var config = { 15 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 16 | user : 'SA', 17 | password: '' 18 | }; 19 | 20 | module.exports = { 21 | testgetconnection: function(test) { 22 | dm.getConnection(config.url + ';user=' + config.user + ';password=' + config.password, function(err, conn) { 23 | test.expect(2); 24 | test.equal(null, err); 25 | test.ok(conn); 26 | test.done(); 27 | }); 28 | }, 29 | testgetconnectionwithprops: function(test) { 30 | var Properties = java.import('java.util.Properties'); 31 | var props = new Properties(); 32 | 33 | props.putSync('user', config.user); 34 | props.putSync('password', config.password); 35 | 36 | dm.getConnection(config.url, props, function(err, conn) { 37 | test.expect(2); 38 | test.equal(null, err); 39 | test.ok(conn); 40 | test.done(); 41 | }); 42 | }, 43 | testgetconnectionwithuserpass: function(test) { 44 | dm.getConnection(config.url, config.user, config.password, function(err, conn) { 45 | test.expect(2); 46 | test.equal(null, err); 47 | test.ok(conn); 48 | test.done(); 49 | }); 50 | }, 51 | testsetlogintimeout: function(test) { 52 | dm.setLoginTimeout(60, function(err) { 53 | test.expect(1); 54 | test.equals(null, err); 55 | test.done(); 56 | }); 57 | }, 58 | testgetlogintimeout: function(test) { 59 | dm.getLoginTimeout(function(err, seconds) { 60 | test.expect(2); 61 | test.ok(seconds); 62 | test.equal(60, seconds); 63 | test.done(); 64 | }); 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /test/test-hsqldb.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var config = { 14 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 15 | drivername: 'org.hsqldb.jdbc.JDBCDriver', 16 | user: 'SA', 17 | password: '', 18 | minpoolsize: 10 19 | }; 20 | 21 | var hsqldb = new JDBC(config); 22 | var testconn = null; 23 | var testDate = Date.now(); 24 | 25 | module.exports = { 26 | setUp: function(callback) { 27 | if (testconn === null && hsqldb._pool.length > 0) { 28 | hsqldb.reserve(function(err, conn) { 29 | testconn = conn; 30 | callback(); 31 | }); 32 | } else { 33 | callback(); 34 | } 35 | }, 36 | tearDown: function(callback) { 37 | if (testconn) { 38 | hsqldb.release(testconn, function(err) { 39 | callback(); 40 | }); 41 | } else { 42 | callback(); 43 | } 44 | }, 45 | testinitialize: function(test) { 46 | hsqldb.initialize(function(err) { 47 | test.expect(1); 48 | test.equal(null, err); 49 | test.done(); 50 | }); 51 | }, 52 | testcreatetable: function(test) { 53 | testconn.conn.createStatement(function(err, statement) { 54 | if (err) { 55 | console.log(err); 56 | } else { 57 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP);", function(err, result) { 58 | test.expect(2); 59 | test.equal(null, err); 60 | test.equal(0, result); 61 | statement.close(function(err) { 62 | if (err) { 63 | console.log(err); 64 | } else { 65 | test.done(); 66 | } 67 | }); 68 | }); 69 | } 70 | }); 71 | }, 72 | testinsert: function(test) { 73 | testconn.conn.createStatement(function(err, statement) { 74 | if (err) { 75 | console.log(err); 76 | } else { 77 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP);", function(err, result) { 78 | test.expect(2); 79 | test.equal(null, err); 80 | test.ok(result && result == 1); 81 | test.done(); 82 | }); 83 | } 84 | }); 85 | }, 86 | testupdate: function(test) { 87 | testconn.conn.createStatement(function(err, statement) { 88 | if (err) { 89 | console.log(err); 90 | } else { 91 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason';", function(err, result) { 92 | test.expect(2); 93 | test.equal(null, err); 94 | test.ok(result && result == 1); 95 | test.done(); 96 | }); 97 | } 98 | }); 99 | }, 100 | testselect: function(test) { 101 | testconn.conn.createStatement(function(err, statement) { 102 | if (err) { 103 | console.log(err); 104 | } else { 105 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 106 | test.expect(7); 107 | test.equal(null, err); 108 | test.ok(resultset); 109 | resultset.toObjArray(function(err, results) { 110 | test.equal(results.length, 1); 111 | test.equal(results[0].NAME, 'Jason'); 112 | test.ok(results[0].DATE); 113 | test.ok(results[0].TIME); 114 | test.ok(results[0].TIMESTAMP); 115 | test.done(); 116 | }); 117 | }); 118 | } 119 | }); 120 | }, 121 | testpreparedselectsetint: function(test) { 122 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id=?",function(err, statement) { 123 | if (err) { 124 | console.log(err); 125 | } else { 126 | statement.setInt(1,2, function(err) { 127 | if (err) { 128 | console.log(err); 129 | } 130 | else { 131 | statement.executeQuery(function(err, resultset) { 132 | test.expect(3); 133 | test.equal(null, err); 134 | test.ok(resultset); 135 | resultset.toObjArray(function(err, results) { 136 | test.equal(results.length, 1); 137 | test.done(); 138 | }); 139 | }); 140 | } 141 | }); 142 | } 143 | }); 144 | }, 145 | testpreparedselectsetstring: function(test) { 146 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE name=?",function(err, statement) { 147 | if (err) { 148 | console.log(err); 149 | } else { 150 | statement.setString(1,'Jason', function(err) { 151 | if (err) { 152 | console.log(err); 153 | } 154 | else { 155 | statement.executeQuery(function(err, resultset) { 156 | test.expect(3); 157 | test.equal(null, err); 158 | test.ok(resultset); 159 | resultset.toObjArray(function(err, results) { 160 | test.equal(results.length, 1); 161 | test.done(); 162 | }); 163 | }); 164 | } 165 | }); 166 | } 167 | }); 168 | }, 169 | testpreparedinsertsetdate: function(test) { 170 | var myjava = jinst.getInstance(); 171 | testconn.conn.prepareStatement("INSERT INTO blah (id,name,date) VALUES (3,'Test',?)",function(err, statement) { 172 | if (err) { 173 | console.log(err); 174 | } else { 175 | var sqlDate = myjava.newInstanceSync("java.sql.Date", myjava.newLong(testDate)); 176 | statement.setDate(1, sqlDate, null, function(err) { 177 | if (err) { 178 | console.log(err); 179 | } 180 | else { 181 | statement.executeUpdate(function(err, numrows) { 182 | if (err) { 183 | console.log(err); 184 | } else { 185 | test.expect(2); 186 | test.equal(null, err); 187 | test.equal(1,numrows); 188 | test.done(); 189 | } 190 | }); 191 | } 192 | }); 193 | } 194 | }); 195 | }, 196 | testpreparedselectsetdate: function(test) { 197 | var myjava = jinst.getInstance(); 198 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id = 3 AND date = ?",function(err, statement) { 199 | if (err) { 200 | console.log(err); 201 | } else { 202 | var sqlDate = myjava.newInstanceSync("java.sql.Date", myjava.newLong(testDate)); 203 | statement.setDate(1, sqlDate, null, function(err) { 204 | if (err) { 205 | console.log(err); 206 | } 207 | else { 208 | statement.executeQuery(function(err, resultset) { 209 | if (err) { 210 | console.log(err); 211 | } else { 212 | test.expect(3); 213 | test.equal(null, err); 214 | test.ok(resultset); 215 | resultset.toObjArray(function(err, results) { 216 | if (err) { 217 | console.log(err); 218 | } else { 219 | test.equal(results.length, 1); 220 | test.done(); 221 | } 222 | }); 223 | } 224 | }); 225 | } 226 | }); 227 | } 228 | }); 229 | }, 230 | testpreparedinsertsettimestamp: function(test) { 231 | var myjava = jinst.getInstance(); 232 | testconn.conn.prepareStatement("INSERT INTO blah (id,name,timestamp) VALUES (4,'Test',?)",function(err, statement) { 233 | if (err) { 234 | console.log(err); 235 | } else { 236 | var sqlTimestamp = myjava.newInstanceSync("java.sql.Timestamp", myjava.newLong(testDate)); 237 | statement.setTimestamp(1, sqlTimestamp, null, function(err) { 238 | if (err) { 239 | console.log(err); 240 | } 241 | else { 242 | statement.executeUpdate(function(err, numrows) { 243 | if (err) { 244 | console.log(err); 245 | } else { 246 | test.expect(2); 247 | test.equal(null, err); 248 | test.equal(1,numrows); 249 | test.done(); 250 | } 251 | }); 252 | } 253 | }); 254 | } 255 | }); 256 | }, 257 | testpreparedselectsettimestamp: function(test) { 258 | var myjava = jinst.getInstance(); 259 | testconn.conn.prepareStatement("SELECT * FROM blah WHERE id = 4 AND timestamp = ?",function(err, statement) { 260 | if (err) { 261 | console.log(err); 262 | } else { 263 | var sqlTimestamp = myjava.newInstanceSync("java.sql.Timestamp", myjava.newLong(testDate)); 264 | statement.setTimestamp(1, sqlTimestamp, null, function(err) { 265 | if (err) { 266 | console.log(err); 267 | } 268 | else { 269 | statement.executeQuery(function(err, resultset) { 270 | if (err) { 271 | console.log(err); 272 | } else { 273 | test.expect(3); 274 | test.equal(null, err); 275 | test.ok(resultset); 276 | resultset.toObjArray(function(err, results) { 277 | if (err) { 278 | console.log(err); 279 | } else { 280 | test.equal(results.length, 1); 281 | test.done(); 282 | } 283 | }); 284 | } 285 | }); 286 | } 287 | }); 288 | } 289 | }); 290 | }, 291 | testdelete: function(test) { 292 | testconn.conn.createStatement(function(err, statement) { 293 | if (err) { 294 | console.log(err); 295 | } else { 296 | statement.executeUpdate("DELETE FROM blah WHERE id = 2;", function(err, result) { 297 | test.expect(2); 298 | test.equal(null, err); 299 | test.ok(result && result == 1); 300 | test.done(); 301 | }); 302 | } 303 | }); 304 | }, 305 | testcancel: function (test) { 306 | testconn.conn.createStatement(function (err, statement) { 307 | if (err) { 308 | console.log(err); 309 | } else { 310 | statement.cancel(function(err) { 311 | test.expect(1); 312 | test.equal(null, err); 313 | test.done(); 314 | }); 315 | } 316 | }); 317 | }, 318 | testdroptable: function(test) { 319 | testconn.conn.createStatement(function(err, statement) { 320 | if (err) { 321 | console.log(err); 322 | } else { 323 | statement.executeUpdate("DROP TABLE blah;", function(err, result) { 324 | test.expect(2); 325 | test.equal(null, err); 326 | test.equal(0, result); 327 | test.done(); 328 | }); 329 | } 330 | }); 331 | } 332 | }; 333 | -------------------------------------------------------------------------------- /test/test-multi.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var configWithUserInUrl = { 14 | url: 'jdbc:hsqldb:hsql://localhost/xdb;user=SA;password=' 15 | }; 16 | 17 | var configderby = { 18 | url: 'jdbc:derby://localhost:1527/testdb' 19 | }; 20 | 21 | var hsqldb = new JDBC(configWithUserInUrl); 22 | var derby = new JDBC(configderby); 23 | var hsqldbconn = null; 24 | var derbyconn = null; 25 | 26 | exports.hsqldb = { 27 | setUp: function(callback) { 28 | if (hsqldbconn === null && hsqldb._pool.length > 0) { 29 | hsqldb.reserve(function(err, conn) { 30 | hsqldbconn = conn; 31 | callback(); 32 | }); 33 | } else { 34 | callback(); 35 | } 36 | }, 37 | tearDown: function(callback) { 38 | if (hsqldbconn) { 39 | hsqldb.release(hsqldbconn, function(err) { 40 | callback(); 41 | }); 42 | } else { 43 | callback(); 44 | } 45 | }, 46 | testinitialize: function(test) { 47 | hsqldb.initialize(function(err) { 48 | test.expect(1); 49 | test.equal(null, err); 50 | test.done(); 51 | }); 52 | }, 53 | testcreatetable: function(test) { 54 | hsqldbconn.conn.createStatement(function(err, statement) { 55 | if (err) { 56 | console.log(err); 57 | } else { 58 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP);", function(err, result) { 59 | test.expect(2); 60 | test.equal(null, err); 61 | test.equal(0, result); 62 | test.done(); 63 | }); 64 | } 65 | }); 66 | }, 67 | testinsert: function(test) { 68 | hsqldbconn.conn.createStatement(function(err, statement) { 69 | if (err) { 70 | console.log(err); 71 | } else { 72 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP);", function(err, result) { 73 | test.expect(2); 74 | test.equal(null, err); 75 | test.equal(1, result); 76 | test.done(); 77 | }); 78 | } 79 | }); 80 | }, 81 | testupdate: function(test) { 82 | hsqldbconn.conn.createStatement(function(err, statement) { 83 | if (err) { 84 | console.log(err); 85 | } else { 86 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason';", function(err, result) { 87 | test.expect(2); 88 | test.equal(null, err); 89 | test.ok(1, result); 90 | test.done(); 91 | }); 92 | } 93 | }); 94 | }, 95 | testselect: function(test) { 96 | hsqldbconn.conn.createStatement(function(err, statement) { 97 | if (err) { 98 | console.log(err); 99 | } else { 100 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 101 | test.expect(7); 102 | test.equal(null, err); 103 | test.ok(resultset); 104 | resultset.toObjArray(function(err, results) { 105 | test.equal(results.length, 1); 106 | test.equal(results[0].NAME, 'Jason'); 107 | test.ok(results[0].DATE); 108 | test.ok(results[0].TIME); 109 | test.ok(results[0].TIMESTAMP); 110 | test.done(); 111 | }); 112 | }); 113 | } 114 | }); 115 | }, 116 | testselectbyexecute: function(test) { 117 | hsqldbconn.conn.createStatement(function(err, statement) { 118 | if (err) { 119 | console.log(err); 120 | } else { 121 | statement.execute("SELECT * FROM blah;", function(err, resultset) { 122 | test.expect(7); 123 | test.equal(null, err); 124 | test.ok(resultset); 125 | resultset.toObjArray(function(err, results) { 126 | test.equal(results.length, 1); 127 | test.equal(results[0].NAME, 'Jason'); 128 | test.ok(results[0].DATE); 129 | test.ok(results[0].TIME); 130 | test.ok(results[0].TIMESTAMP); 131 | test.done(); 132 | }); 133 | }); 134 | } 135 | }); 136 | }, 137 | testupdatebyexecute: function(test) { 138 | hsqldbconn.conn.createStatement(function(err, statement) { 139 | if (err) { 140 | console.log(err); 141 | } else { 142 | statement.execute("UPDATE blah SET id = 2 WHERE name = 'Jason';", function(err, result) { 143 | test.expect(2); 144 | test.equal(null, err); 145 | test.ok(1, result); 146 | test.done(); 147 | }); 148 | } 149 | }); 150 | }, 151 | testdelete: function(test) { 152 | hsqldbconn.conn.createStatement(function(err, statement) { 153 | if (err) { 154 | console.log(err); 155 | } else { 156 | statement.executeUpdate("DELETE FROM blah WHERE id = 2;", function(err, result) { 157 | test.expect(2); 158 | test.equal(null, err); 159 | test.equal(1, result); 160 | test.done(); 161 | }); 162 | } 163 | }); 164 | }, 165 | testdroptable: function(test) { 166 | hsqldbconn.conn.createStatement(function(err, statement) { 167 | if (err) { 168 | console.log(err); 169 | } else { 170 | statement.executeUpdate("DROP TABLE blah;", function(err, result) { 171 | test.expect(2); 172 | test.equal(null, err); 173 | test.equal(0, result); 174 | test.done(); 175 | }); 176 | } 177 | }); 178 | }, 179 | }; 180 | 181 | exports.derby = { 182 | setUp: function(callback) { 183 | if (derbyconn === null && derby._pool.length > 0) { 184 | derby.reserve(function(err, conn) { 185 | derbyconn = conn; 186 | callback(); 187 | }); 188 | } else { 189 | callback(); 190 | } 191 | }, 192 | tearDown: function(callback) { 193 | if (derbyconn) { 194 | derby.release(derbyconn, function(err) { 195 | callback(); 196 | }); 197 | } else { 198 | callback(); 199 | } 200 | }, 201 | testinitialize: function(test) { 202 | derby.initialize(function(err) { 203 | test.expect(1); 204 | test.equal(null, err); 205 | test.done(); 206 | }); 207 | }, 208 | testcreatetable: function(test) { 209 | derbyconn.conn.createStatement(function(err, statement) { 210 | if (err) { 211 | console.log(err); 212 | } else { 213 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP)", function(err, result) { 214 | test.expect(1); 215 | test.equal(null, err); 216 | test.done(); 217 | }); 218 | } 219 | }); 220 | }, 221 | testinsert: function(test) { 222 | derbyconn.conn.createStatement(function(err, statement) { 223 | if (err) { 224 | console.log(err); 225 | } else { 226 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP)", function(err, result) { 227 | test.expect(2); 228 | test.equal(null, err); 229 | test.ok(result && result == 1); 230 | test.done(); 231 | }); 232 | } 233 | }); 234 | }, 235 | testupdate: function(test) { 236 | derbyconn.conn.createStatement(function(err, statement) { 237 | if (err) { 238 | console.log(err); 239 | } else { 240 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason'", function(err, result) { 241 | test.expect(2); 242 | test.equal(null, err); 243 | test.ok(result && result == 1); 244 | test.done(); 245 | }); 246 | } 247 | }); 248 | }, 249 | testselect: function(test) { 250 | derbyconn.conn.createStatement(function(err, statement) { 251 | if (err) { 252 | console.log(err); 253 | } else { 254 | statement.executeQuery("SELECT * FROM blah", function(err, resultset) { 255 | test.expect(7); 256 | test.equal(null, err); 257 | test.ok(resultset); 258 | resultset.toObjArray(function(err, results) { 259 | test.equal(results.length, 1); 260 | test.equal(results[0].NAME, 'Jason'); 261 | test.ok(results[0].DATE); 262 | test.ok(results[0].TIME); 263 | test.ok(results[0].TIMESTAMP); 264 | test.done(); 265 | }); 266 | }); 267 | } 268 | }); 269 | }, 270 | testselectobject: function(test) { 271 | derbyconn.conn.createStatement(function(err, statement) { 272 | if (err) { 273 | console.log(err); 274 | } else { 275 | statement.executeQuery("SELECT * FROM blah", function(err, resultset) { 276 | test.expect(13); 277 | test.equal(null, err); 278 | test.ok(resultset); 279 | resultset.toObject(function(err, results) { 280 | test.equal(results.rows.length, 1); 281 | test.equal(results.rows[0].NAME, 'Jason'); 282 | test.ok(results.rows[0].DATE); 283 | test.ok(results.rows[0].TIME); 284 | test.ok(results.rows[0].TIMESTAMP); 285 | 286 | test.equal(results.labels.length, 5); 287 | test.equal(results.labels[0], 'ID'); 288 | test.equal(results.labels[1], 'NAME'); 289 | test.ok(results.labels[2], 'DATE'); 290 | test.ok(results.labels[3], 'TIME'); 291 | test.ok(results.labels[4], 'TIMESTAMP'); 292 | 293 | test.done(); 294 | }); 295 | }); 296 | } 297 | }); 298 | }, 299 | testselectzero: function(test) { 300 | derbyconn.conn.createStatement(function(err, statement) { 301 | if (err) { 302 | console.log(err); 303 | } else { 304 | statement.executeQuery("SELECT * FROM blah WHERE id = 1000", function(err, resultset) { 305 | test.expect(9); 306 | test.equal(null, err); 307 | test.ok(resultset); 308 | resultset.toObject(function(err, results) { 309 | test.equal(results.rows.length, 0); 310 | test.equal(results.labels.length, 5); 311 | test.equal(results.labels[0], 'ID'); 312 | test.equal(results.labels[1], 'NAME'); 313 | test.ok(results.labels[2], 'DATE'); 314 | test.ok(results.labels[3], 'TIME'); 315 | test.ok(results.labels[4], 'TIMESTAMP'); 316 | test.done(); 317 | }); 318 | }); 319 | } 320 | }); 321 | }, 322 | testdelete: function(test) { 323 | derbyconn.conn.createStatement(function(err, statement) { 324 | if (err) { 325 | console.log(err); 326 | } else { 327 | statement.executeUpdate("DELETE FROM blah WHERE id = 2", function(err, result) { 328 | test.expect(2); 329 | test.equal(null, err); 330 | test.ok(result && result == 1); 331 | test.done(); 332 | }); 333 | } 334 | }); 335 | }, 336 | testdroptable: function(test) { 337 | derbyconn.conn.createStatement(function(err, statement) { 338 | if (err) { 339 | console.log(err); 340 | } else { 341 | statement.executeUpdate("DROP TABLE blah", function(err, result) { 342 | test.expect(1); 343 | test.equal(null, err); 344 | test.done(); 345 | }); 346 | } 347 | }); 348 | } 349 | }; 350 | -------------------------------------------------------------------------------- /test/test-pool-maxidle.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var asyncjs = require('async'); 3 | var nodeunit = require('nodeunit'); 4 | var lolex = require("lolex"); 5 | var jinst = require('../lib/jinst'); 6 | var Pool = require('../lib/pool'); 7 | var java = jinst.getInstance(); 8 | var Q = require('q'); 9 | var lolex = require("lolex"); 10 | 11 | 12 | 13 | if (!jinst.isJvmCreated()) { 14 | jinst.addOption("-Xrs"); 15 | jinst.setupClasspath(['./drivers/hsqldb.jar', 16 | './drivers/derby.jar', 17 | './drivers/derbyclient.jar', 18 | './drivers/derbytools.jar']); 19 | } 20 | 21 | var config = { 22 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 23 | user : 'SA', 24 | password: '', 25 | minpoolsize: 1, 26 | maxpoolsize: 1 27 | }; 28 | 29 | var configWithMaxIdle = { 30 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 31 | user : 'SA', 32 | password: '', 33 | minpoolsize: 1, 34 | maxpoolsize: 1, 35 | maxidle: 20*60*1000 //20 minutes 36 | }; 37 | 38 | var configWithMaxIdleAndKeepAlive = { 39 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 40 | user : 'SA', 41 | password: '', 42 | minpoolsize: 1, 43 | maxpoolsize: 1, 44 | maxidle: 20*60*1000, 45 | keepalive: { 46 | interval: 45*60*1000, 47 | query: 'select 1', 48 | enabled: true 49 | } 50 | }; 51 | 52 | 53 | var testpool = null; 54 | var conn1Uuid = null; 55 | var clock = null; 56 | module.exports = { 57 | group1: { 58 | setUp: function(callback){ 59 | clock = lolex.install(); 60 | testpool = new Pool(config); 61 | 62 | return Q.ninvoke(testpool, 'reserve') 63 | .then(function (conn) { 64 | conn1Uuid = conn.uuid; 65 | return Q.ninvoke(testpool, 'release', conn); 66 | }) 67 | .then(callback); 68 | }, 69 | tearDown: function(callback) { 70 | clock.uninstall(); 71 | testpool = null; 72 | callback(); 73 | }, 74 | testreserve_normal: function(test) { 75 | clock.tick("20:00"); 76 | testpool.reserve(function(err, conn) { 77 | if (err) { 78 | console.log(err); 79 | } else { 80 | test.expect(4); 81 | //expect the same connection to be returned 82 | test.equal(conn1Uuid, conn.uuid); 83 | test.equal(null, err); 84 | test.equal(testpool._pool.length, 0); 85 | test.equal(testpool._reserved.length, 1); 86 | test.done(); 87 | } 88 | }); 89 | } 90 | }, 91 | group2: { 92 | setUp: function(callback) { 93 | clock = lolex.install(); 94 | testpool = new Pool(configWithMaxIdle); 95 | 96 | return Q.ninvoke(testpool, 'reserve') 97 | .then(function(conn) { 98 | conn1Uuid = conn.uuid; 99 | return Q.ninvoke(testpool, 'release', conn); 100 | }) 101 | .then(callback) 102 | .catch(function(e){ 103 | console.log(e); 104 | }); 105 | }, 106 | tearDown: function(callback) { 107 | clock.uninstall(); 108 | callback(); 109 | }, 110 | testreserve_after_max_idle_time: function(test) { 111 | clock.tick("40:00"); 112 | testpool.reserve(function(err, conn) { 113 | if (err) { 114 | console.log(err); 115 | } else { 116 | test.expect(4); 117 | //expect a new connection 118 | test.notEqual(conn1Uuid, conn.uuid); 119 | test.equal(null, err); 120 | test.equal(testpool._pool.length, 0); 121 | test.equal(testpool._reserved.length, 1); 122 | test.done(); 123 | } 124 | }); 125 | } 126 | }, 127 | group3: { 128 | setUp: function(callback) { 129 | clock = lolex.install(); 130 | 131 | testpool = new Pool(configWithMaxIdleAndKeepAlive); 132 | 133 | return Q.ninvoke(testpool, 'reserve') 134 | .then(function(conn) { 135 | conn1Uuid = conn.uuid; 136 | return Q.ninvoke(testpool, 'release', conn); 137 | }) 138 | .then(callback) 139 | .catch(callback); 140 | }, 141 | tearDown: function(callback) { 142 | clock.uninstall(); 143 | callback(); 144 | }, 145 | testreserve_after_max_idle_time_with_keepalive: function(test) { 146 | clock.tick("40:00"); 147 | testpool.reserve(function(err, conn) { 148 | if (err) { 149 | console.log(err); 150 | } else { 151 | test.expect(4); 152 | //we expect the same connection to be retrieved 153 | test.equals(conn1Uuid, conn.uuid); 154 | test.equal(null, err); 155 | test.equal(testpool._pool.length, 0); 156 | test.equal(testpool._reserved.length, 1); 157 | test.done(); 158 | } 159 | }); 160 | } 161 | } 162 | }; 163 | -------------------------------------------------------------------------------- /test/test-pool.js: -------------------------------------------------------------------------------- 1 | var _ = require('lodash'); 2 | var asyncjs = require('async'); 3 | var nodeunit = require('nodeunit'); 4 | var jinst = require('../lib/jinst'); 5 | var Pool = require('../lib/pool'); 6 | var java = jinst.getInstance(); 7 | 8 | if (!jinst.isJvmCreated()) { 9 | jinst.addOption("-Xrs"); 10 | jinst.setupClasspath(['./drivers/hsqldb.jar', 11 | './drivers/derby.jar', 12 | './drivers/derbyclient.jar', 13 | './drivers/derbytools.jar']); 14 | } 15 | 16 | var config = { 17 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 18 | user : 'SA', 19 | password: '', 20 | minpoolsize: 2, 21 | maxpoolsize: 3 22 | }; 23 | 24 | module.exports = { 25 | setUp: function(callback) { 26 | testpool = new Pool(config); 27 | testpool.initialize(function(err) { 28 | callback(); 29 | }); 30 | }, 31 | tearDown: function(callback) { 32 | testpool = null; 33 | callback(); 34 | }, 35 | teststatus: function(test) { 36 | testpool.reserve(function(err) { 37 | testpool.status(function(err, status) { 38 | test.expect(2); 39 | test.equal(status.available, 1); 40 | test.equal(status.reserved, 1); 41 | test.done(); 42 | }); 43 | }); 44 | }, 45 | testreserverelease: function(test) { 46 | testpool.reserve(function(err, conn) { 47 | testpool.release(conn, function(err, conn) { 48 | test.expect(3); 49 | test.equal(null, err); 50 | test.equal(testpool._pool.length, 2); 51 | test.equal(testpool._reserved.length, 0); 52 | test.done(); 53 | }); 54 | }); 55 | }, 56 | testreservepastmin: function(test) { 57 | asyncjs.times(3, function(n, next) { 58 | testpool.reserve(function(err, conn) { 59 | next(err, conn); 60 | }); 61 | }, function(err, results) { 62 | test.expect(2); 63 | test.equal(testpool._pool.length, 0); 64 | test.equal(testpool._reserved.length, 3); 65 | _.each(results, function(conn) { 66 | testpool.release(conn, function(err) {}); 67 | }); 68 | test.done(); 69 | }); 70 | }, 71 | testovermax: function(test) { 72 | asyncjs.times(4, function(n, next) { 73 | testpool.reserve(function(err, conn) { 74 | next(err, conn); 75 | }); 76 | }, function(err, results) { 77 | test.expect(3); 78 | test.ok(err); 79 | test.equal(testpool._reserved.length, 3); 80 | test.equal(testpool._pool.length, 0); 81 | _.each(results, function(conn) { 82 | testpool.release(conn, function(err) {}); 83 | }); 84 | test.done(); 85 | }); 86 | }, 87 | testpurge: function(test) { 88 | testpool.purge(function(err) { 89 | test.expect(3); 90 | test.equal(null, err); 91 | test.equal(testpool._pool.length, 0); 92 | test.equal(testpool._reserved.length, 0); 93 | test.done(); 94 | }); 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /test/test-properties-config.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var config = { 14 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 15 | properties: { 16 | user: 'SA', 17 | password: '' 18 | } 19 | }; 20 | 21 | var hsqldb = new JDBC(config); 22 | var testconn = null; 23 | 24 | module.exports = { 25 | setUp: function(callback) { 26 | if (testconn === null && hsqldb._pool.length > 0) { 27 | hsqldb.reserve(function(err, conn) { 28 | testconn = conn; 29 | callback(); 30 | }); 31 | } else { 32 | callback(); 33 | } 34 | }, 35 | tearDown: function(callback) { 36 | if (testconn) { 37 | hsqldb.release(testconn, function(err) { 38 | callback(); 39 | }); 40 | } else { 41 | callback(); 42 | } 43 | }, 44 | testinitialize: function(test) { 45 | hsqldb.initialize(function(err) { 46 | test.expect(1); 47 | test.equal(null, err); 48 | test.done(); 49 | }); 50 | }, 51 | testcreatetable: function(test) { 52 | testconn.conn.createStatement(function(err, statement) { 53 | if (err) { 54 | console.log(err); 55 | } else { 56 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP);", function(err, result) { 57 | test.expect(2); 58 | test.equal(null, err); 59 | test.equal(0, result); 60 | test.done(); 61 | }); 62 | } 63 | }); 64 | }, 65 | testinsert: function(test) { 66 | testconn.conn.createStatement(function(err, statement) { 67 | if (err) { 68 | console.log(err); 69 | } else { 70 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP);", function(err, result) { 71 | test.expect(2); 72 | test.equal(null, err); 73 | test.equal(1, result); 74 | test.done(); 75 | }); 76 | } 77 | }); 78 | }, 79 | testupdate: function(test) { 80 | testconn.conn.createStatement(function(err, statement) { 81 | if (err) { 82 | console.log(err); 83 | } else { 84 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason';", function(err, result) { 85 | test.expect(2); 86 | test.equal(null, err); 87 | test.ok(1, result); 88 | test.done(); 89 | }); 90 | } 91 | }); 92 | }, 93 | testselect: function(test) { 94 | testconn.conn.createStatement(function(err, statement) { 95 | if (err) { 96 | console.log(err); 97 | } else { 98 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 99 | test.expect(7); 100 | test.equal(null, err); 101 | test.ok(resultset); 102 | resultset.toObjArray(function(err, results) { 103 | test.equal(results.length, 1); 104 | test.equal(results[0].NAME, 'Jason'); 105 | test.ok(results[0].DATE); 106 | test.ok(results[0].TIME); 107 | test.ok(results[0].TIMESTAMP); 108 | test.done(); 109 | }); 110 | }); 111 | } 112 | }); 113 | }, 114 | testdelete: function(test) { 115 | testconn.conn.createStatement(function(err, statement) { 116 | if (err) { 117 | console.log(err); 118 | } else { 119 | statement.executeUpdate("DELETE FROM blah WHERE id = 2;", function(err, result) { 120 | test.expect(2); 121 | test.equal(null, err); 122 | test.equal(1, result); 123 | test.done(); 124 | }); 125 | } 126 | }); 127 | }, 128 | testdroptable: function(test) { 129 | testconn.conn.createStatement(function(err, statement) { 130 | if (err) { 131 | console.log(err); 132 | } else { 133 | statement.executeUpdate("DROP TABLE blah;", function(err, result) { 134 | test.expect(2); 135 | test.equal(null, err); 136 | test.equal(0, result); 137 | test.done(); 138 | }); 139 | } 140 | }); 141 | } 142 | }; 143 | -------------------------------------------------------------------------------- /test/test-statement-adjust.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | var asyncjs = require('async'); 5 | 6 | if (!jinst.isJvmCreated()) { 7 | jinst.addOption("-Xrs"); 8 | jinst.setupClasspath(['./drivers/hsqldb.jar', 9 | './drivers/derby.jar', 10 | './drivers/derbyclient.jar', 11 | './drivers/derbytools.jar']); 12 | } 13 | 14 | var derby = new JDBC({ 15 | url: 'jdbc:derby://localhost:1527/testdb;create=true' 16 | }); 17 | 18 | var testconn = null; 19 | 20 | module.exports = { 21 | setUp: function (callback) { 22 | if (testconn === null && derby._pool.length > 0) { 23 | derby.reserve(function (err, conn) { 24 | testconn = conn; 25 | callback(); 26 | }); 27 | } else { 28 | callback(); 29 | } 30 | }, 31 | tearDown: function (callback) { 32 | if (testconn) { 33 | derby.release(testconn, function () { 34 | callback(); 35 | }); 36 | } else { 37 | callback(); 38 | } 39 | }, 40 | testinitialize: function (test) { 41 | derby.initialize(function (err) { 42 | test.expect(1); 43 | test.equal(err, null); 44 | test.done(); 45 | }); 46 | }, 47 | testcreatetable: function (test) { 48 | testconn.conn.createStatement(function (err, statement) { 49 | if (err) { 50 | console.log(err); 51 | } else { 52 | var create = "CREATE TABLE blahMax "; 53 | create += "(id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP)"; 54 | statement.executeUpdate(create, function (err) { 55 | test.expect(1); 56 | test.equal(null, err); 57 | test.done(); 58 | }); 59 | } 60 | }); 61 | }, 62 | testMultipleInserts: function (test) { 63 | testconn.conn.createStatement(function (err, statement) { 64 | if (err) { 65 | console.log(err); 66 | } else { 67 | asyncjs.times(50, function (n, next) { 68 | var insert = "INSERT INTO blahMax VALUES " + 69 | "(" + n + ", 'Jason_" + n + "', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP)"; 70 | 71 | statement.executeUpdate(insert, function (err, result) { 72 | next(err, result); 73 | }); 74 | }, 75 | function (err, results) { 76 | if (err) 77 | console.log(err); 78 | else { 79 | test.expect(3); 80 | test.equal(null, err); 81 | test.equal(50, results.length); 82 | test.ok(results); 83 | test.done(); 84 | } 85 | }); 86 | } 87 | }); 88 | }, 89 | testselect: function (test) { 90 | testconn.conn.createStatement(function (err, statement) { 91 | if (err) { 92 | console.log(err); 93 | } else { 94 | statement.executeQuery("SELECT * FROM blahMax", function (err, resultset) { 95 | test.expect(7); 96 | test.equal(null, err); 97 | test.ok(resultset); 98 | resultset.toObjArray(function (err, results) { 99 | test.equal(results.length, 50); 100 | test.ok(results[0].NAME.startsWith('Jason')); 101 | test.ok(results[0].DATE); 102 | test.ok(results[0].TIME); 103 | test.ok(results[0].TIMESTAMP); 104 | test.done(); 105 | }); 106 | }); 107 | } 108 | }); 109 | }, 110 | testselectWithMax10Rows: function (test) { 111 | testconn.conn.createStatement(function (err, statement) { 112 | if (err) { 113 | console.log(err); 114 | } else { 115 | statement.setMaxRows(10, function (err) { 116 | if (err) { 117 | console.log(err); 118 | } else { 119 | statement.executeQuery("SELECT * FROM blahMax", function (err, resultset) { 120 | test.expect(4); 121 | test.equal(null, err); 122 | test.ok(resultset); 123 | resultset.toObjArray(function (err, results) { 124 | test.equal(results.length, 10); 125 | test.ok(results[0].NAME.startsWith('Jason')); 126 | test.done(); 127 | }); 128 | }); 129 | } 130 | }) 131 | } 132 | }); 133 | }, 134 | testselectWithMax70Rows: function (test) { 135 | testconn.conn.createStatement(function (err, statement) { 136 | if (err) { 137 | console.log(err); 138 | } else { 139 | statement.setMaxRows(70, function (err) { 140 | if (err) { 141 | console.log(err); 142 | } else { 143 | statement.executeQuery("SELECT * FROM blahMax", function (err, resultset) { 144 | test.expect(4); 145 | test.equal(null, err); 146 | test.ok(resultset); 147 | resultset.toObjArray(function (err, results) { 148 | test.equal(results.length, 50); 149 | test.ok(results[0].NAME.startsWith('Jason')); 150 | test.done(); 151 | }); 152 | }); 153 | } 154 | }) 155 | } 156 | }); 157 | }, 158 | testdroptable: function (test) { 159 | testconn.conn.createStatement(function (err, statement) { 160 | if (err) { 161 | console.log(err); 162 | } else { 163 | statement.executeUpdate("DROP TABLE blahMax", function (err) { 164 | test.expect(1); 165 | test.equal(null, err); 166 | test.done(); 167 | }); 168 | } 169 | }); 170 | } 171 | }; 172 | -------------------------------------------------------------------------------- /test/test-storedproc.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var config = { 14 | url: 'jdbc:hsqldb:hsql://localhost/xdb', 15 | user : 'SA', 16 | password: '' 17 | }; 18 | 19 | var hsqldb = new JDBC(config); 20 | var testconn = null; 21 | 22 | module.exports = { 23 | setUp: function(callback) { 24 | if (testconn === null && hsqldb._pool.length > 0) { 25 | hsqldb.reserve(function(err, conn) { 26 | testconn = conn; 27 | callback(); 28 | }); 29 | } else { 30 | callback(); 31 | } 32 | }, 33 | tearDown: function(callback) { 34 | if (testconn) { 35 | hsqldb.release(testconn, function(err) { 36 | callback(); 37 | }); 38 | } else { 39 | callback(); 40 | } 41 | }, 42 | testinit: function(test) { 43 | hsqldb.initialize(function(err) { 44 | test.expect(1); 45 | test.equal(null, err); 46 | test.done(); 47 | }); 48 | }, 49 | testcreatetable: function(test) { 50 | testconn.conn.createStatement(function(err, statement) { 51 | if (err) { 52 | console.log(err); 53 | } else { 54 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP);", function(err, result) { 55 | test.expect(2); 56 | test.equal(null, err); 57 | test.equal(0, result); 58 | test.done(); 59 | }); 60 | } 61 | }); 62 | }, 63 | testinsert: function(test) { 64 | testconn.conn.createStatement(function(err, statement) { 65 | if (err) { 66 | console.log(err); 67 | } else { 68 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP);", function(err, result) { 69 | test.expect(2); 70 | test.equal(null, err); 71 | test.equal(1, result); 72 | test.done(); 73 | }); 74 | } 75 | }); 76 | }, 77 | testcreateprocedure: function(test) { 78 | testconn.conn.createStatement(function(err, statement) { 79 | if (err) { 80 | console.log(err); 81 | } else { 82 | statement.executeUpdate("CREATE PROCEDURE new_blah(id int, name varchar(10)) " + 83 | "MODIFIES SQL DATA " + 84 | "BEGIN ATOMIC " + 85 | " INSERT INTO blah VALUES (id, name, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP); " + 86 | "END;", function(err, result) { 87 | test.expect(1); 88 | test.equal(null, err); 89 | test.done(); 90 | }); 91 | } 92 | }); 93 | }, 94 | testcallprocedure: function(test) { 95 | testconn.conn.prepareCall("{ call new_blah(2, 'Another')}", function(err, callablestatement) { 96 | if (err) { 97 | console.log(err); 98 | } else { 99 | callablestatement.execute(function(err, result) { 100 | test.expect(2); 101 | test.equal(null, err); 102 | test.equal(false, result); 103 | test.done(); 104 | }); 105 | } 106 | }); 107 | }, 108 | testselectaftercall: function(test) { 109 | testconn.conn.createStatement(function(err, statement) { 110 | if (err) { 111 | console.log(err); 112 | } else { 113 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 114 | test.expect(7); 115 | test.equal(null, err); 116 | test.ok(resultset); 117 | resultset.toObjArray(function(err, results) { 118 | test.equal(results.length, 2); 119 | test.equal(results[0].NAME, 'Jason'); 120 | test.ok(results[0].DATE); 121 | test.ok(results[0].TIME); 122 | test.ok(results[0].TIMESTAMP); 123 | test.done(); 124 | }); 125 | }); 126 | } 127 | }); 128 | }, 129 | testdropprocedure: function(test) { 130 | testconn.conn.createStatement(function(err, statement) { 131 | if (err) { 132 | console.log(err); 133 | } else { 134 | statement.executeUpdate("DROP PROCEDURE IF EXISTS new_blah;", function(err, result) { 135 | test.expect(1); 136 | test.equal(null, err); 137 | test.done(); 138 | }); 139 | } 140 | }); 141 | }, 142 | testdroptable: function(test) { 143 | testconn.conn.createStatement(function(err, statement) { 144 | if (err) { 145 | console.log(err); 146 | } else { 147 | statement.executeUpdate("DROP TABLE blah;", function(err, result) { 148 | test.expect(2); 149 | test.equal(null, err); 150 | test.equal(0, result); 151 | test.done(); 152 | }); 153 | } 154 | }); 155 | } 156 | }; 157 | -------------------------------------------------------------------------------- /test/test-txn.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var config = { 14 | url: 'jdbc:derby://localhost:1527/testdb;create=true', 15 | }; 16 | 17 | var derby = new JDBC(config); 18 | var testconn = null; 19 | 20 | module.exports = { 21 | setUp: function(callback) { 22 | if (testconn === null && derby._pool.length > 0) { 23 | derby.reserve(function(err, conn) { 24 | testconn = conn; 25 | testconn.conn.setAutoCommit(false, function(err) { 26 | callback(); 27 | }); 28 | }); 29 | } else { 30 | callback(); 31 | } 32 | }, 33 | tearDown: function(callback) { 34 | if (testconn) { 35 | derby.release(testconn, function(err) { 36 | callback(); 37 | }); 38 | } else { 39 | callback(); 40 | } 41 | }, 42 | testinitialize: function(test) { 43 | derby.initialize(function(err) { 44 | test.expect(1); 45 | test.equal(null, err); 46 | test.done(); 47 | }); 48 | }, 49 | testcreatetable: function(test) { 50 | testconn.conn.createStatement(function(err, statement) { 51 | if (err) { 52 | console.log(err); 53 | } else { 54 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP)", function(err, result) { 55 | test.expect(1); 56 | test.equal(null, err); 57 | test.done(); 58 | }); 59 | } 60 | }); 61 | }, 62 | testinsert: function(test) { 63 | testconn.conn.createStatement(function(err, statement) { 64 | if (err) { 65 | console.log(err); 66 | } else { 67 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP)", function(err, result) { 68 | test.expect(2); 69 | test.equal(null, err); 70 | test.ok(result && result == 1); 71 | testconn.conn.commit(function(err) { if (err) { console.log(err); }}); 72 | test.done(); 73 | }); 74 | } 75 | }); 76 | }, 77 | testupdate: function(test) { 78 | testconn.conn.createStatement(function(err, statement) { 79 | if (err) { 80 | console.log(err); 81 | } else { 82 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason'", function(err, result) { 83 | test.expect(2); 84 | test.equal(null, err); 85 | test.ok(result && result == 1); 86 | testconn.conn.commit(function(err) { if (err) { console.log(err); }}); 87 | test.done(); 88 | }); 89 | } 90 | }); 91 | }, 92 | testselect: function(test) { 93 | testconn.conn.createStatement(function(err, statement) { 94 | if (err) { 95 | console.log(err); 96 | } else { 97 | statement.executeQuery("SELECT * FROM blah", function(err, resultset) { 98 | test.expect(7); 99 | test.equal(null, err); 100 | test.ok(resultset); 101 | resultset.toObjArray(function(err, results) { 102 | test.equal(results.length, 1); 103 | test.equal(results[0].NAME, 'Jason'); 104 | test.ok(results[0].DATE); 105 | test.ok(results[0].TIME); 106 | test.ok(results[0].TIMESTAMP); 107 | test.done(); 108 | }); 109 | }); 110 | } 111 | }); 112 | }, 113 | testdeleterollback: function(test) { 114 | testconn.conn.createStatement(function(err, statement) { 115 | if (err) { 116 | console.log(err); 117 | } else { 118 | statement.executeUpdate("DELETE FROM blah WHERE id = 2", function(err, result) { 119 | test.expect(2); 120 | test.equal(null, err); 121 | test.ok(result && result == 1); 122 | testconn.conn.rollback(function(err) { if (err) { console.log(err); }}); 123 | test.done(); 124 | }); 125 | } 126 | }); 127 | }, 128 | testselectpostrollback: function(test) { 129 | testconn.conn.createStatement(function(err, statement) { 130 | if (err) { 131 | console.log(err); 132 | } else { 133 | statement.executeQuery("SELECT * FROM blah", function(err, resultset) { 134 | test.expect(7); 135 | test.equal(null, err); 136 | test.ok(resultset); 137 | resultset.toObjArray(function(err, results) { 138 | test.equal(results.length, 1); 139 | test.equal(results[0].NAME, 'Jason'); 140 | test.ok(results[0].DATE); 141 | test.ok(results[0].TIME); 142 | test.ok(results[0].TIMESTAMP); 143 | test.done(); 144 | }); 145 | }); 146 | } 147 | }); 148 | }, 149 | testdroptable: function(test) { 150 | testconn.conn.createStatement(function(err, statement) { 151 | if (err) { 152 | console.log(err); 153 | } else { 154 | statement.executeUpdate("DROP TABLE blah", function(err, result) { 155 | test.expect(1); 156 | test.equal(null, err); 157 | test.done(); 158 | }); 159 | } 160 | }); 161 | } 162 | }; 163 | -------------------------------------------------------------------------------- /test/test-user-password-url.js: -------------------------------------------------------------------------------- 1 | var nodeunit = require('nodeunit'); 2 | var jinst = require('../lib/jinst'); 3 | var JDBC = require('../lib/jdbc'); 4 | 5 | if (!jinst.isJvmCreated()) { 6 | jinst.addOption("-Xrs"); 7 | jinst.setupClasspath(['./drivers/hsqldb.jar', 8 | './drivers/derby.jar', 9 | './drivers/derbyclient.jar', 10 | './drivers/derbytools.jar']); 11 | } 12 | 13 | var config = { 14 | url: 'jdbc:hsqldb:hsql://localhost/xdb;user=SA;password=' 15 | }; 16 | 17 | var hsqldb = new JDBC(config); 18 | var testconn = null; 19 | 20 | module.exports = { 21 | setUp: function(callback) { 22 | if (testconn === null && hsqldb._pool.length > 0) { 23 | hsqldb.reserve(function(err, conn) { 24 | testconn = conn; 25 | callback(); 26 | }); 27 | } else { 28 | callback(); 29 | } 30 | }, 31 | tearDown: function(callback) { 32 | if (testconn) { 33 | hsqldb.release(testconn, function(err) { 34 | callback(); 35 | }); 36 | } else { 37 | callback(); 38 | } 39 | }, 40 | testinitialize: function(test) { 41 | hsqldb.initialize(function(err, drivername) { 42 | test.expect(1); 43 | test.equal(null, err); 44 | test.done(); 45 | }); 46 | }, 47 | testcreatetable: function(test) { 48 | testconn.conn.createStatement(function(err, statement) { 49 | if (err) { 50 | console.log(err); 51 | } else { 52 | statement.executeUpdate("CREATE TABLE blah (id int, name varchar(10), date DATE, time TIME, timestamp TIMESTAMP);", function(err, result) { 53 | test.expect(2); 54 | test.equal(null, err); 55 | test.equal(0, result); 56 | test.done(); 57 | }); 58 | } 59 | }); 60 | }, 61 | testinsert: function(test) { 62 | testconn.conn.createStatement(function(err, statement) { 63 | if (err) { 64 | console.log(err); 65 | } else { 66 | statement.executeUpdate("INSERT INTO blah VALUES (1, 'Jason', CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP);", function(err, result) { 67 | test.expect(2); 68 | test.equal(null, err); 69 | test.equal(1, result); 70 | test.done(); 71 | }); 72 | } 73 | }); 74 | }, 75 | testupdate: function(test) { 76 | testconn.conn.createStatement(function(err, statement) { 77 | if (err) { 78 | console.log(err); 79 | } else { 80 | statement.executeUpdate("UPDATE blah SET id = 2 WHERE name = 'Jason';", function(err, result) { 81 | test.expect(2); 82 | test.equal(null, err); 83 | test.ok(1, result); 84 | test.done(); 85 | }); 86 | } 87 | }); 88 | }, 89 | testselect: function(test) { 90 | testconn.conn.createStatement(function(err, statement) { 91 | if (err) { 92 | console.log(err); 93 | } else { 94 | statement.executeQuery("SELECT * FROM blah;", function(err, resultset) { 95 | test.expect(7); 96 | test.equal(null, err); 97 | test.ok(resultset); 98 | resultset.toObjArray(function(err, results) { 99 | test.equal(results.length, 1); 100 | test.equal(results[0].NAME, 'Jason'); 101 | test.ok(results[0].DATE); 102 | test.ok(results[0].TIME); 103 | test.ok(results[0].TIMESTAMP); 104 | test.done(); 105 | }); 106 | }); 107 | } 108 | }); 109 | }, 110 | testdelete: function(test) { 111 | testconn.conn.createStatement(function(err, statement) { 112 | if (err) { 113 | console.log(err); 114 | } else { 115 | statement.executeUpdate("DELETE FROM blah WHERE id = 2;", function(err, result) { 116 | test.expect(2); 117 | test.equal(null, err); 118 | test.equal(1, result); 119 | test.done(); 120 | }); 121 | } 122 | }); 123 | }, 124 | testdroptable: function(test) { 125 | testconn.conn.createStatement(function(err, statement) { 126 | if (err) { 127 | console.log(err); 128 | } else { 129 | statement.executeUpdate("DROP TABLE blah;", function(err, result) { 130 | test.expect(2); 131 | test.equal(null, err); 132 | test.equal(0, result); 133 | test.done(); 134 | }); 135 | } 136 | }); 137 | } 138 | }; 139 | --------------------------------------------------------------------------------