Add modules for sqlite and firebird
This commit is contained in:
parent
9c1d7e09b3
commit
fb6bf25062
10
node_modules/dblite/.npmignore
generated
vendored
Normal file
10
node_modules/dblite/.npmignore
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
src/*
|
||||
test/*
|
||||
benchmark/*
|
||||
template/*
|
||||
node_modules/*
|
||||
build/*.amd.js
|
||||
Makefile
|
||||
index.html
|
||||
.gitignore
|
||||
.travis.yml
|
19
node_modules/dblite/LICENSE.txt
generated
vendored
Normal file
19
node_modules/dblite/LICENSE.txt
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2013 by WebReflection
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
413
node_modules/dblite/README.md
generated
vendored
Normal file
413
node_modules/dblite/README.md
generated
vendored
Normal file
@ -0,0 +1,413 @@
|
||||
dblite
|
||||
======
|
||||
a zero hassle wrapper for sqlite
|
||||
```javascript
|
||||
var dblite = require('dblite'),
|
||||
db = dblite('file.name');
|
||||
|
||||
// Asynchronous, fast, and ...
|
||||
db.query('SELECT * FROM table', function(err, rows) {
|
||||
// ... that easy!
|
||||
});
|
||||
```
|
||||
More in [the related blogpost](http://webreflection.blogspot.com/2013/07/dblite-sqlite3-for-nodejs-made-easy.html) and here too :-)
|
||||
|
||||
[![build status](https://secure.travis-ci.org/WebReflection/dblite.png)](http://travis-ci.org/WebReflection/dblite)
|
||||
|
||||
[![NPM](https://nodei.co/npm/dblite.png?downloads=true)](https://nodei.co/npm/dblite/)
|
||||
|
||||
|
||||
### Important
|
||||
Starting from **sqlite3** version `3.8.6` you need a "_new line agnostic_" version of `dblite`, right now represented by the latest version `0.6.0`. This **will break** compatibility with older version of the database cli.
|
||||
|
||||
|
||||
### The What And The Why
|
||||
I've created `dblite` module because there's still not a simple and straight forward or standard way to have [sqlite](http://www.sqlite.org) in [node.js](http://nodejs.org) without requiring to re-compile, re-build, download sources a part or install dependencies instead of simply `apt-get install sqlite3` or `pacman -S sqlite3` in your \*nix system.
|
||||
|
||||
`dblite` has been created with portability, simplicity, and reasonable performance for **embedded Hardware** such [Raspberry Pi](http://www.raspberrypi.org) and [Cubieboard](http://cubieboard.org) in mind.
|
||||
|
||||
Generally speaking all linux based distributions like [Arch Linux](https://www.archlinux.org), where is not always that easy to `node-gyp` a module and add dependencies that work, can now use this battle tested wrap and perform basic to advanced sqlite operations.
|
||||
|
||||
|
||||
### Bootstrap
|
||||
To install dblite simply `npm install dblite` then in node:
|
||||
```javascript
|
||||
var dblite = require('dblite'),
|
||||
db = dblite('/folder/to/file.sqlite');
|
||||
|
||||
// ready to go, i.e.
|
||||
db.query('.databases');
|
||||
db.query(
|
||||
'SELECT * FROM users WHERE pass = ?',
|
||||
[pass],
|
||||
function (err, rows) {
|
||||
var user = rows.length && rows[0];
|
||||
}
|
||||
);
|
||||
```
|
||||
By default the `dblite` function uses **sqlite3 as executable**. If you need to change the path simply update `dblite.bin = "/usr/local/bin/sqlite3";` before invoking the function.
|
||||
|
||||
|
||||
### API
|
||||
Right now a created `EventEmitter` `db` instance has 3 extra methods: `.query()`, `.lastRowID()`, and `.close()`.
|
||||
|
||||
The `.lastRowID(table, callback(rowid))` helper simplifies a common operation with SQL tables after inserts, handful as shortcut for the following query:
|
||||
`SELECT ROWID FROM ``table`` ORDER BY ROWID DESC LIMIT 1`.
|
||||
|
||||
The method `.close()` does exactly what it suggests: it closes the database connection.
|
||||
Please note that it is **not possible to perform other operations once it has been closed**.
|
||||
|
||||
Being an `EventEmitter` instance, the database variable will be notified with the `close` listener, if any.
|
||||
|
||||
|
||||
### Understanding The .query() Method
|
||||
The main role in this module is played by the `db.query()` method, a method rich in overloads all with perfect and natural meaning.
|
||||
|
||||
The amount of parameters goes from one to four, left to right, where left is the input going through the right which is the eventual output.
|
||||
|
||||
All parameters are optionals except the SQL one.
|
||||
|
||||
### db.query() Possible Combinations
|
||||
```javascript
|
||||
db.query(SQL)
|
||||
db.query(SQL, callback:Function)
|
||||
db.query(SQL, params:Array|Object)
|
||||
db.query(SQL, fields:Array|Object)
|
||||
db.query(SQL, params:Array|Object, callback:Function)
|
||||
db.query(SQL, fields:Array|Object, callback:Function)
|
||||
db.query(SQL, params:Array|Object, fields:Array|Object)
|
||||
db.query(SQL, params:Array|Object, fields:Array|Object, callback:Function)
|
||||
```
|
||||
All above combinations are [tested properly in this file](test/dblite.js) together with many other tests able to make `dblite` robust enough and ready to be used.
|
||||
|
||||
Please note how `params` is always before `fields` and/or `callback` if `fields` is missing, just as reminder that order is left to right accordingly with what we are trying to do.
|
||||
|
||||
Following detailed explanation per each parameter.
|
||||
|
||||
#### The SQL:string
|
||||
This string [accepts any query understood by SQLite](http://www.sqlite.org/lang.html) plus it accepts all commands that regular SQLite shell would accept such `.databases`, `.tables`, `.show` and all others passing through the specified `info` listener, if any, using just the console as fallback otherwise.
|
||||
```javascript
|
||||
var dblite = require('dblite'),
|
||||
db = dblite('./db.sqlite');
|
||||
|
||||
// will call the implicit `info` console.log
|
||||
db.query('.show');
|
||||
/* will console.log something like:
|
||||
|
||||
echo: off
|
||||
explain: off
|
||||
headers: off
|
||||
mode: csv
|
||||
nullvalue: ""
|
||||
output: stdout
|
||||
separator: ","
|
||||
stats: off
|
||||
width:
|
||||
*/
|
||||
|
||||
// normal query
|
||||
db.query('CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, value TEXT)');
|
||||
db.query('INSERT INTO test VALUES(null, ?)', ['some text']);
|
||||
db.query('SELECT * FROM test');
|
||||
// will implicitly log the following
|
||||
// [ [ '1', 'some text' ] ]
|
||||
```
|
||||
|
||||
#### The params:Array|Object
|
||||
If the SQL string **contains special chars** such `?`, `:key`, `$key`, or `@key` properties, these will be replaced accordingly with the `params` `Array` or `Object` that, in this case, MUST be present.
|
||||
```javascript
|
||||
// params as Array
|
||||
db.query('SELECT * FROM test WHERE id = ?', [1]);
|
||||
|
||||
// params as Object
|
||||
db.query('SELECT * FROM test WHERE id = :id', {id:1});
|
||||
// same as
|
||||
db.query('SELECT * FROM test WHERE id = $id', {id:1});
|
||||
// same as
|
||||
db.query('SELECT * FROM test WHERE id = @id', {id:1});
|
||||
```
|
||||
|
||||
#### The fields:Array|Object
|
||||
By default, results are returned as an `Array` where all rows are the outer `Array` and each single row is another `Array`.
|
||||
```javascript
|
||||
db.query('SELECT * FROM test');
|
||||
// will log something like:
|
||||
[
|
||||
[ '1', 'some text' ], // row1
|
||||
[ '2', 'something else' ] // rowN
|
||||
]
|
||||
```
|
||||
If we specify a fields parameter we can have each row represented by an object, instead of an array.
|
||||
```javascript
|
||||
// same query using fields as Array
|
||||
db.query('SELECT * FROM test', ['key', 'value']);
|
||||
// will log something like:
|
||||
[
|
||||
{key: '1', value: 'some text'}, // row1
|
||||
{key: '2', value: 'something else'} // rowN
|
||||
]
|
||||
```
|
||||
|
||||
#### Parsing Through The fields:Object
|
||||
[SQLite Datatypes](http://www.sqlite.org/datatype3.html) are different from JavaScript plus SQLite works via affinity.
|
||||
This module also parses sqlite3 output which is **always a string** and as string every result will always be returned **unless** we specify `fields` parameter as object, suggesting validation per each field.
|
||||
```javascript
|
||||
// same query using fields as Object
|
||||
db.query('SELECT * FROM test', {
|
||||
key: Number,
|
||||
value: String
|
||||
});
|
||||
// note the key as integer!
|
||||
[
|
||||
{key: 1, value: 'some text'}, // row1
|
||||
{key: 2, value: 'something else'} // rowN
|
||||
]
|
||||
```
|
||||
More complex validators/transformers can be passed without problems:
|
||||
```javascript
|
||||
// same query using fields as Object
|
||||
db.query('SELECT * FROM `table.users`', {
|
||||
id: Number,
|
||||
name: String,
|
||||
adult: Boolean,
|
||||
skills: JSON.parse,
|
||||
birthday: Date,
|
||||
cube: function (fieldValue) {
|
||||
return fieldValue * 3;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### The params:Array|Object AND The fields:Array|Object
|
||||
Not a surprise we can combine both params, using the left to right order input to output so **params first**!
|
||||
```javascript
|
||||
// same query using params AND fields
|
||||
db.query('SELECT * FROM test WHERE id = :id', {
|
||||
id: 1
|
||||
},{
|
||||
key: Number,
|
||||
value: String
|
||||
});
|
||||
|
||||
// same as...
|
||||
db.query('SELECT * FROM test WHERE id = ?', [1], ['key', 'value']);
|
||||
// same as...
|
||||
db.query('SELECT * FROM test WHERE id = ?', [1], {
|
||||
key: Number,
|
||||
value: String
|
||||
});
|
||||
// same as...
|
||||
db.query('SELECT * FROM test WHERE id = :id', {
|
||||
id: 1
|
||||
}, [
|
||||
'key', 'value'
|
||||
]);
|
||||
```
|
||||
|
||||
#### The callback:Function
|
||||
When a `SELECT` or a `PRAGMA` `SQL` is executed the module puts itself in a *waiting for results* state.
|
||||
|
||||
**Update** - Starting from `0.4.0` the callback will be invoked with `err` and `data` if the callback length is greater than one. `function(err, data){}` VS `function(data){}`. However, latter mode will keep working in order to not break backward compatibility.
|
||||
**Update** - Starting from `0.3.3` every other `SQL` statement will invoke the callback after the operation has been completed.
|
||||
|
||||
As soon as results are fully pushed to the output the module parses this result, if any, and send it to the specified callback.
|
||||
|
||||
The callback is **always the last specified parameter**, if any, or the implicit equivalent of `console.log.bind(console)`.
|
||||
Latter case is simply helpful to operate directly via `node` **console** and see results without bothering writing a callback each `.query()` call.
|
||||
|
||||
#### Extra Bonus: JSON Serialization With fields:Array|Object
|
||||
If one field value is not scalar (boolean, number, string, null) `JSON.stringify` is performed in order to save data.
|
||||
This helps lazy developers that don't want to pre parse every field and let `dblite` do the magic.
|
||||
```javascript
|
||||
// test has two fields, id and value
|
||||
db.query('INSERT INTO test VALUES(?, ?)', [
|
||||
123,
|
||||
{name: 'dblite', rate: 'awesome'} // value serialized
|
||||
]);
|
||||
|
||||
// use the fields to parse back the object
|
||||
db.query('SELECT * FROM test WHERE id = ?', [123], {
|
||||
id: Number,
|
||||
value: JSON.parse // value unserialized
|
||||
}, function (err, rows) {
|
||||
var record = rows[0];
|
||||
console.log(record.id); // 123
|
||||
console.log(record.value.name); // "dblite"
|
||||
console.log(record.value.rate); // "awesome""
|
||||
});
|
||||
```
|
||||
|
||||
### Automatic Fields Through Headers
|
||||
Since version `0.3.0` it is possible to enable automatic fields parsing either through initialization (suggested) or at runtime.
|
||||
```javascript
|
||||
var dblite = require('dblite'),
|
||||
// passing extra argument at creation
|
||||
db = dblite('file.name', '-header');
|
||||
|
||||
db.query('SELECT * FROM table', function(err, rows) {
|
||||
rows[0]; // {header0: value0, headerN: valueN}
|
||||
});
|
||||
|
||||
// at runtime
|
||||
db
|
||||
.query('.headers ON')
|
||||
.query('SELECT * FROM table', function(err, rows) {
|
||||
rows[0]; // {header0: value0, headerN: valueN}
|
||||
})
|
||||
.query('.headers OFF')
|
||||
;
|
||||
```
|
||||
|
||||
In version `0.3.2` a smarter approach for combined _headers/fields_ is used where the right key order is granted by headers but it's possible to validate known fields too.
|
||||
|
||||
```javascript
|
||||
var db = require('dblite')('file.name', '-header');
|
||||
|
||||
db.query('SELECT 1 as one, 2 as two', {two:Number}, function(err, rows) {
|
||||
rows[0]; // {one: "1", two: 2} // note "1" as String
|
||||
});
|
||||
```
|
||||
In this way these two options can be supplementary when and if necessary.
|
||||
|
||||
|
||||
### Handling Infos And Errors - Listeners
|
||||
The `EventEmitter` will notify any listener attached to `info`, `error`, or `close` accordingly with the current status.
|
||||
```javascript
|
||||
db.on('info', function (data) {
|
||||
// show data returned by special syntax
|
||||
// such: .databases .tables .show and others
|
||||
console.log(data);
|
||||
// by default, it does the same
|
||||
});
|
||||
|
||||
db.on('error', function (err) {
|
||||
// same as `info` but for errors
|
||||
console.error(err.toString());
|
||||
// by default, it does the same
|
||||
});
|
||||
|
||||
db.on('close', function (code) {
|
||||
// by default, it logs "bye bye"
|
||||
// invoked once the database has been closed
|
||||
// and every statement in the queue executed
|
||||
// the code is the exit code returned via SQLite3
|
||||
// usually 0 if everything was OK
|
||||
console.log('safe to get out of here ^_^_');
|
||||
});
|
||||
```
|
||||
Please **note** that error is invoked only if the callback is not handling it already via double argument.
|
||||
|
||||
The `close` event ensures that all operations have been successfully performed and your app is ready to exit or move next.
|
||||
|
||||
Please note that after invoking `db.close()` any other query will be ignored and the instance will be put in a _waiting to complete_ state which will invoke the `close` listener once operations have been completed.
|
||||
|
||||
|
||||
### Raspberry Pi Performance
|
||||
This is the output generated after a `make test` call in this repo folder within Arch Linux for RPi.
|
||||
```
|
||||
npm test
|
||||
|
||||
> dblite@0.1.2 test /home/dblite
|
||||
> node test/.test.js
|
||||
|
||||
/home/dblite/dblite.test.sqlite
|
||||
------------------------------
|
||||
main
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
create table if not exists
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
100 sequential inserts
|
||||
100 records in 3.067 seconds
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
1 transaction with 100 inserts
|
||||
200 records in 0.178 seconds
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
auto escape
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
auto field
|
||||
fetched 201 rows as objects in 0.029 seconds
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
auto parsing field
|
||||
fetched 201 rows as normalized objects in 0.038 seconds
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
many selects at once
|
||||
different selects in 0.608 seconds
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
db.query() arguments
|
||||
[ [ '1' ] ]
|
||||
[ [ '2' ] ]
|
||||
[ { id: 1 } ]
|
||||
[ { id: 2 } ]
|
||||
passes: 5, fails: 0, errors: 0
|
||||
------------------------------
|
||||
utf-8
|
||||
¥ · £ · € · $ · ¢ · ₡ · ₢ · ₣ · ₤ · ₥ · ₦ · ₧ · ₨ · ₩ · ₪ · ₫ · ₭ · ₮ · ₯ · ₹
|
||||
passes: 1, fails: 0, errors: 0
|
||||
------------------------------
|
||||
erease file
|
||||
passes: 1, fails: 0, errors: 0
|
||||
|
||||
------------------------------
|
||||
15 Passes
|
||||
------------------------------
|
||||
```
|
||||
If an SD card can do this good, I guess any other environment should not have problems here ;-)
|
||||
|
||||
### F.A.Q.
|
||||
Here a list of probably common Q&A about this module. Please do not hesitate to ask me more, if necessary, thanks.
|
||||
|
||||
* **How Does It Work?** `dblite` uses a [spawned](http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) version of the `sqlite3` executable. It could theoretically work with any other SQL like database but it's tested with `sqlite3-shell` only
|
||||
* **Does It Spawn Per Each Query?** this is a quick one: **NO**! `dblite` spawns once per each database file where usually there is only one database file opened per time.
|
||||
* **How About Memory And Performance?** Accordingly with `node` manual:
|
||||
|
||||
> These child Nodes are still whole new instances of V8.
|
||||
> Assume at least 30ms startup and 10mb memory for each new Node.
|
||||
> That is, you cannot create many thousands of them.
|
||||
|
||||
Since `dblite` spawns only once, there is a little overhead during the database initialization but that's pretty much it, the amount of RAM increases with the amount of data we save or retrieve from the database. The above **Raspberry Pi Benchmark** should ensure that with most common operation, and using transactions where possible, latency and RAM aren't a real issue.
|
||||
* **Why Not The Native One?** I had some difficulty installing this [node-sqlite3 module](https://github.com/developmentseed/node-sqlite3#name) due `node-gyp` incompatibilities with some **ARM** based device in both *Debian* and *ArchLinux*. Since I really needed an sqlite manager for the next version of [polpetta](https://github.com/WebReflection/polpetta#က-polpetta) which aim is to have a complete, lightweight, and super fast web server in many embedded hardware such RPi, Cubieboard, and others, and since I needed something able to work with multiple core too, I've decided to try this road wrapping the native, easy to install and update, `sqlite3` shell client and do everything I need. So far, so good I would say ;-)
|
||||
* **Isn't `params` and `fields` an ambiguous choice?** At the very beginning I wasn't sure myself if that would have worked as API choice but later on I've changed my mind. First of all, it's very easy to spot special chars in the `SQL` statement. If present, params is mandatory and used, as easy as that. Secondly, if an object has functions as value, it's obviously a `fields` object, 'cause `params` cannot contains functions since these are not compatible with `JSON` serialization, neither meaningful for the database. The only case where `fields` might be confused with `params` is when no `params` has been specified, and `fields` is an `Array`. In this case I believe you are the same one that wrote the SQL too and know upfront if there are fields to retrieve from `params` or not so this is actually a *non real-world* problem and as soon as you try this API you'll realize it feels intuitive and right.
|
||||
* **Are Transactions Supported?** ... **YES**, transactions are supported simply performing multiple queries as you would do in *sqlite3* shell:
|
||||
```javascript
|
||||
db.query('BEGIN TRANSACTION');
|
||||
for(var i = 0; i < 100; i++) {
|
||||
db.query('INSERT INTO table VALUES(?, ?)', [null, Math.random()]);
|
||||
}
|
||||
db.query('COMMIT');
|
||||
```
|
||||
The test file has a transaction with 100 records in it, [have a look](test/dblite.js).
|
||||
* **Can I Connect To A `:memory:` Database?** well, you can do anything you would do with `sqlite3` shell so **YES**
|
||||
```javascript
|
||||
var db = dblite(':memory:'); // that's it!
|
||||
```
|
||||
|
||||
### License
|
||||
The usual Mit Style, thinking about the [WTFPL](http://en.wikipedia.org/wiki/WTFPL) though ... stay tuned for updates.
|
||||
|
||||
Copyright (C) 2013 by WebReflection
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
60
node_modules/dblite/package.json
generated
vendored
Normal file
60
node_modules/dblite/package.json
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"version": "0.6.1",
|
||||
"license": "MIT",
|
||||
"engine": "node >= 0.6.0",
|
||||
"name": "dblite",
|
||||
"description": "a zero hassle wrapper for sqlite - requires sqlite3 3.8.6 or greater",
|
||||
"homepage": "https://github.com/WebReflection/dblite",
|
||||
"keywords": [
|
||||
"sqlite",
|
||||
"sqlite3",
|
||||
"shell",
|
||||
"query",
|
||||
"embedded",
|
||||
"arch linux",
|
||||
"raspberry pi",
|
||||
"cubieboard",
|
||||
"cubieboard2",
|
||||
"simple",
|
||||
"no gyp",
|
||||
"no compile",
|
||||
"no hassle",
|
||||
"wrap",
|
||||
"spawn"
|
||||
],
|
||||
"author": {
|
||||
"name": "Andrea Giammarchi",
|
||||
"url": "http://webreflection.blogspot.com/"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/WebReflection/dblite.git"
|
||||
},
|
||||
"main": "./build/dblite.node.js",
|
||||
"scripts": {
|
||||
"test": "node test/.test.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/WebReflection/dblite/issues"
|
||||
},
|
||||
"_id": "dblite@0.6.1",
|
||||
"_shasum": "18e6d3811f4031ff0119e8a7b13ef1558215376a",
|
||||
"_from": "dblite@",
|
||||
"_npmVersion": "1.4.9",
|
||||
"_npmUser": {
|
||||
"name": "webreflection",
|
||||
"email": "andrea.giammarchi@gmail.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "webreflection",
|
||||
"email": "andrea.giammarchi@gmail.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "18e6d3811f4031ff0119e8a7b13ef1558215376a",
|
||||
"tarball": "http://registry.npmjs.org/dblite/-/dblite-0.6.1.tgz"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/dblite/-/dblite-0.6.1.tgz"
|
||||
}
|
2
node_modules/node-firebird/.npmignore
generated
vendored
Normal file
2
node_modules/node-firebird/.npmignore
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
*.fdb
|
373
node_modules/node-firebird/LICENSE
generated
vendored
Normal file
373
node_modules/node-firebird/LICENSE
generated
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
360
node_modules/node-firebird/README.md
generated
vendored
Normal file
360
node_modules/node-firebird/README.md
generated
vendored
Normal file
@ -0,0 +1,360 @@
|
||||
![Firebird Logo](https://www.totaljs.com/exports/firebird-logo.png)
|
||||
|
||||
[![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![Mozilla License][license-image]][license-url]
|
||||
# Pure JavaScript Firebird client for Node.js.
|
||||
|
||||
Pure JavaScript and Asynchronous Firebird client for Node.js. [Firebird forum](https://groups.google.com/forum/#!forum/node-firebird) on Google Groups. Please share and follow Firebird database, it's a very good open-source product.
|
||||
|
||||
__Firebird database on social networks__
|
||||
|
||||
- [Firebird on Google+](https://plus.google.com/111558763769231855886/posts)
|
||||
- [Firebird on Twitter](https://twitter.com/firebirdsql/)
|
||||
- [Firebird on Facebook](https://www.facebook.com/FirebirdSQL)
|
||||
|
||||
__New version v0.2.0 supports__
|
||||
|
||||
- added auto-reconnect
|
||||
- added [sequentially selects](https://github.com/hgourvest/node-firebird/wiki/What-is-sequentially-selects)
|
||||
- events for connection (attach, detach, row, result, transaction, commit, rollback, error, etc.)
|
||||
- performance improvements
|
||||
- supports inserting/updating buffers and streams
|
||||
- reading blobs (sequentially)
|
||||
- pooling
|
||||
- `database.detach()` waits for last command
|
||||
- better unit-test
|
||||
- best of use with [total.js - web application framework for node.js](http://www.totaljs.com)
|
||||
|
||||
---
|
||||
|
||||
- [Firebird documentation](http://www.firebirdsql.org/en/documentation/)
|
||||
- [Firebird limits and data types](http://www.firebirdsql.org/en/firebird-technical-specifications/)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install node-firebird
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var Firebird = require('node-firebird');
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
- `Firebird.escape(value) -> return {String}` - prevent for SQL Injections
|
||||
- `Firebird.attach(options, function(err, db))` attach a database
|
||||
- `Firebird.create(options, function(err, db))` create a database
|
||||
- `Firebird.attachOrCreate(options, function(err, db))` attach or create database
|
||||
- `Firebird.pool(maxSockets, options, function(err, db)) -> return {Object}` create a connection pooling
|
||||
|
||||
## Connection types
|
||||
|
||||
### Connection options
|
||||
|
||||
```js
|
||||
var options = {};
|
||||
|
||||
options.host = '127.0.0.1';
|
||||
// options.port = 3050;
|
||||
options.database = 'database.fdb';
|
||||
options.user = 'SYSDBA';
|
||||
options.password = 'masterkey';
|
||||
```
|
||||
|
||||
### Classic
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.query('SELECT * FROM TABLE', function(err, result) {
|
||||
// IMPORTANT: close the connection
|
||||
db.detach();
|
||||
});
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
### Pooling
|
||||
|
||||
```js
|
||||
// 5 = the number is count of opened sockets
|
||||
var pool = Firebird.pool(5, options);
|
||||
|
||||
// Get a free pool
|
||||
pool.get(function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.query('SELECT * FROM TABLE', function(err, result) {
|
||||
// IMPORTANT: release the pool connection
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
|
||||
// close all opened connections
|
||||
pool.detach();
|
||||
|
||||
// Destroy pool
|
||||
pool.destroy();
|
||||
```
|
||||
|
||||
## Database object (db)
|
||||
|
||||
### Methods
|
||||
|
||||
- `db.query(query, [params], function(err, result))` - classic query, returns Array of Object
|
||||
- `db.execute(query, [params], function(err, result))` - classic query, returns Array of Array
|
||||
- `db.sequentially(query, [params], function(row, index), function(err))` - sequentially query
|
||||
- `db.detach(function(err))` detach a database
|
||||
- `db.transaction(isolation, function(err, transaction))` create transaction
|
||||
|
||||
### Transaction methods
|
||||
|
||||
- `transaction.query(query, [params], function(err, result))` - classic query, returns Array of Object
|
||||
- `transaction.execute(query, [params], function(err, result))` - classic query, returns Array of Array
|
||||
- `transaction.commit(function(err))` commit current transaction
|
||||
- `transaction.rollback(function(err))` rollback current transaction
|
||||
|
||||
## Examples
|
||||
|
||||
### PARAMETRIZED QUERIES
|
||||
|
||||
### Parameters
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.query('INSERT INTO USERS (ID, ALIAS, CREATED) VALUES(?, ?, ?) RETURNING ID', [1, 'Pe\'ter', new Date()] function(err, result) {
|
||||
console.log(result[0].id);
|
||||
db.query('SELECT * FROM USERS WHERE Alias=?', ['Peter'], function(err, result) {
|
||||
console.log(result);
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### BLOB (stream)
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
// INSERT STREAM as BLOB
|
||||
db.query('INSERT INTO USERS (ID, ALIAS, FILE) VALUES(?, ?, ?)', [1, 'Peter', fs.createReadStream('/users/image.jpg')] function(err, result) {
|
||||
// IMPORTANT: close the connection
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### BLOB (buffer)
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
// INSERT BUFFER as BLOB
|
||||
db.query('INSERT INTO USERS (ID, ALIAS, FILE) VALUES(?, ?, ?)', [1, 'Peter', fs.readFileSync('/users/image.jpg')] function(err, result) {
|
||||
// IMPORTANT: close the connection
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### READING BLOBS (ASYNCHRONOUS)
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.query('SELECT ID, ALIAS, USERPICTURE FROM USER', function(err, rows) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// first row
|
||||
rows[0].userpicture(function(err, name, e) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// e === EventEmitter
|
||||
e.on('data', function(chunk) {
|
||||
// reading data
|
||||
});
|
||||
|
||||
e.on('end', function() {
|
||||
// end reading
|
||||
// IMPORTANT: close the connection
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### STREAMING A BIG DATA
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.sequentially('SELECT * FROM BIGTABLE', function(row, index) {
|
||||
|
||||
// EXAMPLE
|
||||
stream.write(JSON.stringify(row));
|
||||
|
||||
}, function(err) {
|
||||
// END
|
||||
// IMPORTANT: close the connection
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### TRANSACTIONS
|
||||
|
||||
__Transaction types:__
|
||||
|
||||
- `Firebird.ISOLATION_READ_UNCOMMITTED`
|
||||
- `Firebird.ISOLATION_READ_COMMITED`
|
||||
- `Firebird.ISOLATION_REPEATABLE_READ`
|
||||
- `Firebird.ISOLATION_SERIALIZABLE`
|
||||
- `Firebird.ISOLATION_READ_COMMITED_READ_ONLY`
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
// db = DATABASE
|
||||
db.transaction(Firebird.ISOLATION_READ_COMMITED, function(err, transaction) {
|
||||
transaction.query('INSERT INTO users VALUE(?,?)', [1, 'Janko'], function(err, result) {
|
||||
|
||||
if (err) {
|
||||
transaction.rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
transaction.commit(function(err) {
|
||||
if (err)
|
||||
transaction.rollback();
|
||||
else
|
||||
db.detach();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### EVENTS
|
||||
|
||||
```js
|
||||
Firebird.attach(options, function(err, db) {
|
||||
|
||||
if (err)
|
||||
throw err;
|
||||
|
||||
db.on('row', function(row, index, isObject) {
|
||||
// index === Number
|
||||
// isObject === is row object or array?
|
||||
});
|
||||
|
||||
db.on('result', function(result) {
|
||||
// result === Array
|
||||
});
|
||||
|
||||
db.on('attach', function() {
|
||||
|
||||
});
|
||||
|
||||
db.on('detach', function(isPoolConnection) {
|
||||
// isPoolConnection == Boolean
|
||||
});
|
||||
|
||||
db.on('reconnect', function() {
|
||||
|
||||
});
|
||||
|
||||
db.on('error', function(err) {
|
||||
|
||||
});
|
||||
|
||||
db.on('transaction', function(isolation) {
|
||||
// isolation === Number
|
||||
});
|
||||
|
||||
db.on('commit', function() {
|
||||
|
||||
});
|
||||
|
||||
db.on('rollback', function() {
|
||||
|
||||
});
|
||||
|
||||
db.detach();
|
||||
});
|
||||
```
|
||||
|
||||
### Escaping query values
|
||||
|
||||
```js
|
||||
var sql1 = 'SELECT * FROM TBL_USER WHERE ID>' + Firebird.escape(1);
|
||||
var sql2 = 'SELECT * FROM TBL_USER WHERE NAME=' + Firebird.escape('Pe\'er');
|
||||
var sql3 = 'SELECT * FROM TBL_USER WHERE CREATED<=' + Firebird.escape(new Date());
|
||||
var sql4 = 'SELECT * FROM TBL_USER WHERE NEWSLETTER=' + Firebird.escape(true);
|
||||
|
||||
// or db.escape()
|
||||
|
||||
console.log(sql1);
|
||||
console.log(sql2);
|
||||
console.log(sql3);
|
||||
console.log(sql4);
|
||||
```
|
||||
|
||||
### Charset for database connection is always UTF-8
|
||||
|
||||
node-firebird doesn't let you chose the charset connection, it will always use UTF8.
|
||||
Node is unicode, no matter if your database is using another charset to store string or blob, Firebird will transliterate automatically.
|
||||
|
||||
This is why you should use **Firebird 2.5** server at least.
|
||||
|
||||
## Contributors
|
||||
|
||||
- Henri Gourvest, <https://github.com/hgourvest>
|
||||
- Popa Marius Adrian, <https://github.com/mariuz>
|
||||
- Peter Širka, <https://github.com/petersirka>
|
||||
|
||||
[license-image]: http://img.shields.io/badge/license-MOZILLA-blue.svg?style=flat
|
||||
[license-url]: LICENSE
|
||||
|
||||
[npm-url]: https://npmjs.org/package/node-firebird
|
||||
[npm-version-image]: http://img.shields.io/npm/v/node-firebird.svg?style=flat
|
||||
[npm-downloads-image]: http://img.shields.io/npm/dm/node-firebird.svg?style=flat
|
BIN
node_modules/node-firebird/lib/firebird.msg
generated
vendored
Normal file
BIN
node_modules/node-firebird/lib/firebird.msg
generated
vendored
Normal file
Binary file not shown.
2716
node_modules/node-firebird/lib/index.js
generated
vendored
Normal file
2716
node_modules/node-firebird/lib/index.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
855
node_modules/node-firebird/lib/long.js
generated
vendored
Normal file
855
node_modules/node-firebird/lib/long.js
generated
vendored
Normal file
@ -0,0 +1,855 @@
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Copyright 2009 Google Inc. All Rights Reserved
|
||||
|
||||
/**
|
||||
* Defines a Long class for representing a 64-bit two's-complement
|
||||
* integer value, which faithfully simulates the behavior of a Java "Long". This
|
||||
* implementation is derived from LongLib in GWT.
|
||||
*
|
||||
* Constructs a 64-bit two's-complement integer, given its low and high 32-bit
|
||||
* values as *signed* integers. See the from* functions below for more
|
||||
* convenient ways of constructing Longs.
|
||||
*
|
||||
* The internal representation of a Long is the two given signed, 32-bit values.
|
||||
* We use 32-bit pieces because these are the size of integers on which
|
||||
* Javascript performs bit-operations. For operations like addition and
|
||||
* multiplication, we split each number into 16-bit pieces, which can easily be
|
||||
* multiplied within Javascript's floating-point representation without overflow
|
||||
* or change in sign.
|
||||
*
|
||||
* In the algorithms below, we frequently reduce the negative case to the
|
||||
* positive case by negating the input(s) and then post-processing the result.
|
||||
* Note that we must ALWAYS check specially whether those values are MIN_VALUE
|
||||
* (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
|
||||
* a positive number, it overflows back into a negative). Not handling this
|
||||
* case would often result in infinite recursion.
|
||||
*
|
||||
* @class Represents the BSON Long type.
|
||||
* @param {Number} low the low (signed) 32 bits of the Long.
|
||||
* @param {Number} high the high (signed) 32 bits of the Long.
|
||||
*/
|
||||
function Long(low, high) {
|
||||
|
||||
if (!(this instanceof Long))
|
||||
return new Long(low, high);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
this.low_ = low | 0; // force into 32 signed bits.
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
this.high_ = high | 0; // force into 32 signed bits.
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the int value.
|
||||
*
|
||||
* @return {Number} the value, assuming it is a 32-bit integer.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.toInt = function() {
|
||||
return this.low_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the Number value.
|
||||
*
|
||||
* @return {Number} the closest floating-point representation to this value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.toNumber = function() {
|
||||
return this.high_ * Long.TWO_PWR_32_DBL_ +
|
||||
this.getLowBitsUnsigned();
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the JSON value.
|
||||
*
|
||||
* @return {String} the JSON representation.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.toJSON = function() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the String value.
|
||||
*
|
||||
* @param {Number} [opt_radix] the radix in which the text should be written.
|
||||
* @return {String} the textual representation of this value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.toString = function(opt_radix) {
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix)
|
||||
throw Error('radix out of range: ' + radix);
|
||||
|
||||
if (this.isZero())
|
||||
return '0';
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (this.equals(Long.MIN_VALUE)) {
|
||||
// We need to change the Long value before it can be negated, so we remove
|
||||
// the bottom-most digit in this base and then recurse to do the rest.
|
||||
var radixLong = Long.fromNumber(radix);
|
||||
var div = this.div(radixLong);
|
||||
var rem = div.multiply(radixLong).subtract(this);
|
||||
return div.toString(radix) + rem.toInt().toString(radix);
|
||||
} else {
|
||||
return '-' + this.negate().toString(radix);
|
||||
}
|
||||
}
|
||||
|
||||
// Do several (6) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = Long.fromNumber(Math.pow(radix, 6));
|
||||
|
||||
var rem = this;
|
||||
var result = '';
|
||||
while (true) {
|
||||
var remDiv = rem.div(radixToPower);
|
||||
var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
|
||||
var digits = intval.toString(radix);
|
||||
|
||||
rem = remDiv;
|
||||
if (rem.isZero()) {
|
||||
return digits + result;
|
||||
} else {
|
||||
while (digits.length < 6) {
|
||||
digits = '0' + digits;
|
||||
}
|
||||
result = '' + digits + result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the high 32-bits value.
|
||||
*
|
||||
* @return {Number} the high 32-bits as a signed value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.getHighBits = function() {
|
||||
return this.high_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the low 32-bits value.
|
||||
*
|
||||
* @return {Number} the low 32-bits as a signed value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.getLowBits = function() {
|
||||
return this.low_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the low unsigned 32-bits value.
|
||||
*
|
||||
* @return {Number} the low 32-bits as an unsigned value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.getLowBitsUnsigned = function() {
|
||||
return (this.low_ >= 0) ?
|
||||
this.low_ : Long.TWO_PWR_32_DBL_ + this.low_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of bits needed to represent the absolute value of this Long.
|
||||
*
|
||||
* @return {Number} Returns the number of bits needed to represent the absolute value of this Long.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.getNumBitsAbs = function() {
|
||||
if (this.isNegative()) {
|
||||
if (this.equals(Long.MIN_VALUE)) {
|
||||
return 64;
|
||||
} else {
|
||||
return this.negate().getNumBitsAbs();
|
||||
}
|
||||
} else {
|
||||
var val = this.high_ != 0 ? this.high_ : this.low_;
|
||||
for (var bit = 31; bit > 0; bit--) {
|
||||
if ((val & (1 << bit)) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.high_ != 0 ? bit + 33 : bit + 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this value is zero.
|
||||
*
|
||||
* @return {Boolean} whether this value is zero.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.isZero = function() {
|
||||
return this.high_ == 0 && this.low_ == 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this value is negative.
|
||||
*
|
||||
* @return {Boolean} whether this value is negative.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.isNegative = function() {
|
||||
return this.high_ < 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this value is odd.
|
||||
*
|
||||
* @return {Boolean} whether this value is odd.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.isOdd = function() {
|
||||
return (this.low_ & 1) == 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long equals the other
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long equals the other
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.equals = function(other) {
|
||||
return (this.high_ == other.high_) && (this.low_ == other.low_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long does not equal the other.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long does not equal the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.notEquals = function(other) {
|
||||
return (this.high_ != other.high_) || (this.low_ != other.low_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long is less than the other.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long is less than the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.lessThan = function(other) {
|
||||
return this.compare(other) < 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long is less than or equal to the other.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long is less than or equal to the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.lessThanOrEqual = function(other) {
|
||||
return this.compare(other) <= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long is greater than the other.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long is greater than the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.greaterThan = function(other) {
|
||||
return this.compare(other) > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return whether this Long is greater than or equal to the other.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} whether this Long is greater than or equal to the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.greaterThanOrEqual = function(other) {
|
||||
return this.compare(other) >= 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares this Long with the given one.
|
||||
*
|
||||
* @param {Long} other Long to compare against.
|
||||
* @return {Boolean} 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.compare = function(other) {
|
||||
if (this.equals(other)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var thisNeg = this.isNegative();
|
||||
var otherNeg = other.isNegative();
|
||||
if (thisNeg && !otherNeg) {
|
||||
return -1;
|
||||
}
|
||||
if (!thisNeg && otherNeg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// at this point, the signs are the same, so subtraction will not overflow
|
||||
if (this.subtract(other).isNegative()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The negation of this value.
|
||||
*
|
||||
* @return {Long} the negation of this value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.negate = function() {
|
||||
if (this.equals(Long.MIN_VALUE)) {
|
||||
return Long.MIN_VALUE;
|
||||
} else {
|
||||
return this.not().add(Long.ONE);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the sum of this and the given Long.
|
||||
*
|
||||
* @param {Long} other Long to add to this one.
|
||||
* @return {Long} the sum of this and the given Long.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.add = function(other) {
|
||||
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
|
||||
|
||||
var a48 = this.high_ >>> 16;
|
||||
var a32 = this.high_ & 0xFFFF;
|
||||
var a16 = this.low_ >>> 16;
|
||||
var a00 = this.low_ & 0xFFFF;
|
||||
|
||||
var b48 = other.high_ >>> 16;
|
||||
var b32 = other.high_ & 0xFFFF;
|
||||
var b16 = other.low_ >>> 16;
|
||||
var b00 = other.low_ & 0xFFFF;
|
||||
|
||||
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
||||
c00 += a00 + b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 + b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 + b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 + b48;
|
||||
c48 &= 0xFFFF;
|
||||
return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the difference of this and the given Long.
|
||||
*
|
||||
* @param {Long} other Long to subtract from this.
|
||||
* @return {Long} the difference of this and the given Long.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.subtract = function(other) {
|
||||
return this.add(other.negate());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the product of this and the given Long.
|
||||
*
|
||||
* @param {Long} other Long to multiply with this.
|
||||
* @return {Long} the product of this and the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.multiply = function(other) {
|
||||
if (this.isZero()) {
|
||||
return Long.ZERO;
|
||||
} else if (other.isZero()) {
|
||||
return Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.equals(Long.MIN_VALUE)) {
|
||||
return other.isOdd() ? Long.MIN_VALUE : Long.ZERO;
|
||||
} else if (other.equals(Long.MIN_VALUE)) {
|
||||
return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().multiply(other.negate());
|
||||
} else {
|
||||
return this.negate().multiply(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.multiply(other.negate()).negate();
|
||||
}
|
||||
|
||||
// If both Longs are small, use float multiplication
|
||||
if (this.lessThan(Long.TWO_PWR_24_) &&
|
||||
other.lessThan(Long.TWO_PWR_24_)) {
|
||||
return Long.fromNumber(this.toNumber() * other.toNumber());
|
||||
}
|
||||
|
||||
// Divide each Long into 4 chunks of 16 bits, and then add up 4x4 products.
|
||||
// We can skip products that would overflow.
|
||||
|
||||
var a48 = this.high_ >>> 16;
|
||||
var a32 = this.high_ & 0xFFFF;
|
||||
var a16 = this.low_ >>> 16;
|
||||
var a00 = this.low_ & 0xFFFF;
|
||||
|
||||
var b48 = other.high_ >>> 16;
|
||||
var b32 = other.high_ & 0xFFFF;
|
||||
var b16 = other.low_ >>> 16;
|
||||
var b00 = other.low_ & 0xFFFF;
|
||||
|
||||
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
||||
c00 += a00 * b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 * b00;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c16 += a00 * b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 * b00;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a16 * b16;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a00 * b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
|
||||
c48 &= 0xFFFF;
|
||||
return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this Long divided by the given one.
|
||||
*
|
||||
* @param {Long} other Long by which to divide.
|
||||
* @return {Long} this Long divided by the given one.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.div = function(other) {
|
||||
if (other.isZero()) {
|
||||
throw Error('division by zero');
|
||||
} else if (this.isZero()) {
|
||||
return Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.equals(Long.MIN_VALUE)) {
|
||||
if (other.equals(Long.ONE) ||
|
||||
other.equals(Long.NEG_ONE)) {
|
||||
return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
|
||||
} else if (other.equals(Long.MIN_VALUE)) {
|
||||
return Long.ONE;
|
||||
} else {
|
||||
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
|
||||
var halfThis = this.shiftRight(1);
|
||||
var approx = halfThis.div(other).shiftLeft(1);
|
||||
if (approx.equals(Long.ZERO)) {
|
||||
return other.isNegative() ? Long.ONE : Long.NEG_ONE;
|
||||
} else {
|
||||
var rem = this.subtract(other.multiply(approx));
|
||||
var result = approx.add(rem.div(other));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (other.equals(Long.MIN_VALUE)) {
|
||||
return Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().div(other.negate());
|
||||
} else {
|
||||
return this.negate().div(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.div(other.negate()).negate();
|
||||
}
|
||||
|
||||
// Repeat the following until the remainder is less than other: find a
|
||||
// floating-point that approximates remainder / other *from below*, add this
|
||||
// into the result, and subtract it from the remainder. It is critical that
|
||||
// the approximate value is less than or equal to the real value so that the
|
||||
// remainder never becomes negative.
|
||||
var res = Long.ZERO;
|
||||
var rem = this;
|
||||
while (rem.greaterThanOrEqual(other)) {
|
||||
// Approximate the result of division. This may be a little greater or
|
||||
// smaller than the actual value.
|
||||
var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
|
||||
|
||||
// We will tweak the approximate result by changing it in the 48-th digit or
|
||||
// the smallest non-fractional digit, whichever is larger.
|
||||
var log2 = Math.ceil(Math.log(approx) / Math.LN2);
|
||||
var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
|
||||
|
||||
// Decrease the approximation until it is smaller than the remainder. Note
|
||||
// that if it is too large, the product overflows and is negative.
|
||||
var approxRes = Long.fromNumber(approx);
|
||||
var approxRem = approxRes.multiply(other);
|
||||
while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
|
||||
approx -= delta;
|
||||
approxRes = Long.fromNumber(approx);
|
||||
approxRem = approxRes.multiply(other);
|
||||
}
|
||||
|
||||
// We know the answer can't be zero... and actually, zero would cause
|
||||
// infinite recursion since we would make no progress.
|
||||
if (approxRes.isZero()) {
|
||||
approxRes = Long.ONE;
|
||||
}
|
||||
|
||||
res = res.add(approxRes);
|
||||
rem = rem.subtract(approxRem);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this Long modulo the given one.
|
||||
*
|
||||
* @param {Long} other Long by which to mod.
|
||||
* @return {Long} this Long modulo the given one.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.modulo = function(other) {
|
||||
return this.subtract(this.div(other).multiply(other));
|
||||
};
|
||||
|
||||
/**
|
||||
* The bitwise-NOT of this value.
|
||||
*
|
||||
* @return {Long} the bitwise-NOT of this value.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.not = function() {
|
||||
return Long.fromBits(~this.low_, ~this.high_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the bitwise-AND of this Long and the given one.
|
||||
*
|
||||
* @param {Long} other the Long with which to AND.
|
||||
* @return {Long} the bitwise-AND of this and the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.and = function(other) {
|
||||
return Long.fromBits(this.low_ & other.low_, this.high_ & other.high_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the bitwise-OR of this Long and the given one.
|
||||
*
|
||||
* @param {Long} other the Long with which to OR.
|
||||
* @return {Long} the bitwise-OR of this and the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.or = function(other) {
|
||||
return Long.fromBits(this.low_ | other.low_, this.high_ | other.high_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the bitwise-XOR of this Long and the given one.
|
||||
*
|
||||
* @param {Long} other the Long with which to XOR.
|
||||
* @return {Long} the bitwise-XOR of this and the other.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.xor = function(other) {
|
||||
return Long.fromBits(this.low_ ^ other.low_, this.high_ ^ other.high_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the left by the given amount.
|
||||
*
|
||||
* @param {Number} numBits the number of bits by which to shift.
|
||||
* @return {Long} this shifted to the left by the given amount.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.shiftLeft = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var low = this.low_;
|
||||
if (numBits < 32) {
|
||||
var high = this.high_;
|
||||
return Long.fromBits(
|
||||
low << numBits,
|
||||
(high << numBits) | (low >>> (32 - numBits)));
|
||||
} else {
|
||||
return Long.fromBits(0, low << (numBits - 32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the right by the given amount.
|
||||
*
|
||||
* @param {Number} numBits the number of bits by which to shift.
|
||||
* @return {Long} this shifted to the right by the given amount.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.shiftRight = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var high = this.high_;
|
||||
if (numBits < 32) {
|
||||
var low = this.low_;
|
||||
return Long.fromBits(
|
||||
(low >>> numBits) | (high << (32 - numBits)),
|
||||
high >> numBits);
|
||||
} else {
|
||||
return Long.fromBits(
|
||||
high >> (numBits - 32),
|
||||
high >= 0 ? 0 : -1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the right by the given amount, with the new top bits matching the current sign bit.
|
||||
*
|
||||
* @param {Number} numBits the number of bits by which to shift.
|
||||
* @return {Long} this shifted to the right by the given amount, with zeros placed into the new leading bits.
|
||||
* @api public
|
||||
*/
|
||||
Long.prototype.shiftRightUnsigned = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var high = this.high_;
|
||||
if (numBits < 32) {
|
||||
var low = this.low_;
|
||||
return Long.fromBits(
|
||||
(low >>> numBits) | (high << (32 - numBits)),
|
||||
high >>> numBits);
|
||||
} else if (numBits == 32) {
|
||||
return Long.fromBits(high, 0);
|
||||
} else {
|
||||
return Long.fromBits(high >>> (numBits - 32), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Long representing the given (32-bit) integer value.
|
||||
*
|
||||
* @param {Number} value the 32-bit integer in question.
|
||||
* @return {Long} the corresponding Long value.
|
||||
* @api public
|
||||
*/
|
||||
Long.fromInt = function(value) {
|
||||
if (-128 <= value && value < 128) {
|
||||
var cachedObj = Long.INT_CACHE_[value];
|
||||
if (cachedObj) {
|
||||
return cachedObj;
|
||||
}
|
||||
}
|
||||
|
||||
var obj = new Long(value | 0, value < 0 ? -1 : 0);
|
||||
if (-128 <= value && value < 128) {
|
||||
Long.INT_CACHE_[value] = obj;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
|
||||
*
|
||||
* @param {Number} value the number in question.
|
||||
* @return {Long} the corresponding Long value.
|
||||
* @api public
|
||||
*/
|
||||
Long.fromNumber = function(value) {
|
||||
if (isNaN(value) || !isFinite(value)) {
|
||||
return Long.ZERO;
|
||||
} else if (value <= -Long.TWO_PWR_63_DBL_) {
|
||||
return Long.MIN_VALUE;
|
||||
} else if (value + 1 >= Long.TWO_PWR_63_DBL_) {
|
||||
return Long.MAX_VALUE;
|
||||
} else if (value < 0) {
|
||||
return Long.fromNumber(-value).negate();
|
||||
} else {
|
||||
return new Long(
|
||||
(value % Long.TWO_PWR_32_DBL_) | 0,
|
||||
(value / Long.TWO_PWR_32_DBL_) | 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits.
|
||||
*
|
||||
* @param {Number} lowBits the low 32-bits.
|
||||
* @param {Number} highBits the high 32-bits.
|
||||
* @return {Long} the corresponding Long value.
|
||||
* @api public
|
||||
*/
|
||||
Long.fromBits = function(lowBits, highBits) {
|
||||
return new Long(lowBits, highBits);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a Long representation of the given string, written using the given radix.
|
||||
*
|
||||
* @param {String} str the textual representation of the Long.
|
||||
* @param {Number} opt_radix the radix in which the text is written.
|
||||
* @return {Long} the corresponding Long value.
|
||||
* @api public
|
||||
*/
|
||||
Long.fromString = function(str, opt_radix) {
|
||||
if (str.length == 0) {
|
||||
throw Error('number format error: empty string');
|
||||
}
|
||||
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix) {
|
||||
throw Error('radix out of range: ' + radix);
|
||||
}
|
||||
|
||||
if (str.charAt(0) == '-') {
|
||||
return Long.fromString(str.substring(1), radix).negate();
|
||||
} else if (str.indexOf('-') >= 0) {
|
||||
throw Error('number format error: interior "-" character: ' + str);
|
||||
}
|
||||
|
||||
// Do several (8) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = Long.fromNumber(Math.pow(radix, 8));
|
||||
|
||||
var result = Long.ZERO;
|
||||
for (var i = 0; i < str.length; i += 8) {
|
||||
var size = Math.min(8, str.length - i);
|
||||
var value = parseInt(str.substring(i, i + size), radix);
|
||||
if (size < 8) {
|
||||
var power = Long.fromNumber(Math.pow(radix, size));
|
||||
result = result.multiply(power).add(Long.fromNumber(value));
|
||||
} else {
|
||||
result = result.multiply(radixToPower);
|
||||
result = result.add(Long.fromNumber(value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
|
||||
// from* methods on which they depend.
|
||||
|
||||
|
||||
/**
|
||||
* A cache of the Long representations of small integer values.
|
||||
* @type {Object}
|
||||
* @api private
|
||||
*/
|
||||
Long.INT_CACHE_ = {};
|
||||
|
||||
// NOTE: the compiler should inline these constant values below and then remove
|
||||
// these variables, so there should be no runtime penalty for these.
|
||||
|
||||
/**
|
||||
* Number used repeated below in calculations. This must appear before the
|
||||
* first call to any from* function below.
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_16_DBL_ = 1 << 16;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_24_DBL_ = 1 << 24;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_32_DBL_ = Long.TWO_PWR_16_DBL_ * Long.TWO_PWR_16_DBL_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_31_DBL_ = Long.TWO_PWR_32_DBL_ / 2;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_48_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_16_DBL_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_64_DBL_ = Long.TWO_PWR_32_DBL_ * Long.TWO_PWR_32_DBL_;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_63_DBL_ = Long.TWO_PWR_64_DBL_ / 2;
|
||||
|
||||
/** @type {Long} */
|
||||
Long.ZERO = Long.fromInt(0);
|
||||
|
||||
/** @type {Long} */
|
||||
Long.ONE = Long.fromInt(1);
|
||||
|
||||
/** @type {Long} */
|
||||
Long.NEG_ONE = Long.fromInt(-1);
|
||||
|
||||
/** @type {Long} */
|
||||
Long.MAX_VALUE =
|
||||
Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
|
||||
|
||||
/** @type {Long} */
|
||||
Long.MIN_VALUE = Long.fromBits(0, 0x80000000 | 0);
|
||||
|
||||
/**
|
||||
* @type {Long}
|
||||
* @api private
|
||||
*/
|
||||
Long.TWO_PWR_24_ = Long.fromInt(1 << 24);
|
||||
|
||||
/**
|
||||
* Expose.
|
||||
*/
|
||||
if(typeof window === 'undefined') {
|
||||
exports.Long = Long;
|
||||
}
|
162
node_modules/node-firebird/lib/messages.js
generated
vendored
Normal file
162
node_modules/node-firebird/lib/messages.js
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
var fs = require('fs');
|
||||
|
||||
const
|
||||
//ISC_MASK = 0x14000000, // Defines the code as a valid ISC code
|
||||
FAC_MASK = 0x00FF0000, // Specifies the facility where the code is located
|
||||
CODE_MASK = 0x0000FFFF, // Specifies the code in the message file
|
||||
CLASS_MASK = 0xF0000000; // Defines the code as warning, error, info, or other
|
||||
|
||||
var msgNumber = exports.msgNumber = function(facility, code) {
|
||||
return (facility * 10000 + code);
|
||||
};
|
||||
|
||||
var getCode = exports.getCode = function(code) {
|
||||
return (code & CODE_MASK)
|
||||
};
|
||||
|
||||
var getFacility = exports.getFacility = function(code) {
|
||||
return (code & FAC_MASK) >> 16;
|
||||
};
|
||||
|
||||
exports.getClass = function(code) {
|
||||
return (code & CLASS_MASK) >> 30
|
||||
};
|
||||
|
||||
exports.lookupMessages = function(status, callback){
|
||||
|
||||
var handle;
|
||||
var bucket_size;
|
||||
var top_tree;
|
||||
var levels;
|
||||
var buffer;
|
||||
|
||||
function lookup(item, callback) {
|
||||
|
||||
var code = msgNumber(getFacility(item.gdscode), getCode(item.gdscode));
|
||||
|
||||
function readIndex(stackSize, position) {
|
||||
|
||||
function readNode(from) {
|
||||
var ret = {};
|
||||
ret.code = buffer.readUInt32LE(from);
|
||||
ret.seek = buffer.readUInt32LE(from + 4);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fs.read(handle, buffer, 0, bucket_size, position, function(err, bufferSize) {
|
||||
|
||||
if (bufferSize <= 0) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (stackSize === levels) {
|
||||
search();
|
||||
return;
|
||||
}
|
||||
|
||||
var from = 0;
|
||||
var node = readNode(from);
|
||||
|
||||
while (true) {
|
||||
|
||||
if (node.code >= code)
|
||||
{
|
||||
readIndex(stackSize + 1, node.seek);
|
||||
break;
|
||||
}
|
||||
|
||||
from += 8;
|
||||
if (from >= bufferSize)
|
||||
{
|
||||
callback();
|
||||
break;
|
||||
}
|
||||
|
||||
node = readNode(from);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function search() {
|
||||
|
||||
function readRec(from) {
|
||||
|
||||
function align(v) {
|
||||
return (v + 3) & ~3;
|
||||
}
|
||||
|
||||
var ret = {};
|
||||
ret.code = buffer.readUInt32LE(from);
|
||||
ret.length = buffer.readUInt16LE(from + 4);
|
||||
|
||||
if (ret.code == code){
|
||||
from += 8;
|
||||
ret.text = buffer.toString(null, from, from + ret.length);
|
||||
} else
|
||||
ret.seek = from + align(8 + ret.length, 4);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
var rec = readRec(0);
|
||||
|
||||
while (rec.seek) {
|
||||
if (rec.seek >= buffer.length)
|
||||
break;
|
||||
else
|
||||
rec = readRec(rec.seek);
|
||||
}
|
||||
|
||||
var str = rec.text;
|
||||
if (item.params) {
|
||||
for (var i = 0; i < item.params.length; i++)
|
||||
str = str.replace('@' + String(i+1), item.params[i]);
|
||||
}
|
||||
|
||||
callback(str);
|
||||
}
|
||||
|
||||
readIndex(1, top_tree);
|
||||
}
|
||||
|
||||
fs.open(__dirname + "/firebird.msg", 'r', function(err, h) {
|
||||
|
||||
if (!h) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = new Buffer(14);
|
||||
fs.read(h, buffer, 0, 14, 0, function(){
|
||||
|
||||
handle = h;
|
||||
bucket_size = buffer.readUInt16LE(2);
|
||||
top_tree = buffer.readUInt32LE(4);
|
||||
levels = buffer.readUInt16LE(12);
|
||||
buffer = new Buffer(bucket_size);
|
||||
|
||||
var i = 0;
|
||||
var text;
|
||||
|
||||
function loop() {
|
||||
lookup(status[i], function(line) {
|
||||
if (text)
|
||||
text = text + ', ' + line
|
||||
else
|
||||
text = line;
|
||||
|
||||
if (i === status.length - 1) {
|
||||
fs.close(handle);
|
||||
callback(text);
|
||||
} else {
|
||||
i++;
|
||||
loop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loop(0);
|
||||
});
|
||||
});
|
||||
};
|
361
node_modules/node-firebird/lib/serialize.js
generated
vendored
Normal file
361
node_modules/node-firebird/lib/serialize.js
generated
vendored
Normal file
@ -0,0 +1,361 @@
|
||||
|
||||
var Long = require('./long.js').Long;
|
||||
|
||||
function align(n) {
|
||||
return (n + 3) & ~3;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* BLR Writer
|
||||
*
|
||||
***************************************/
|
||||
|
||||
const
|
||||
MAX_STRING_SIZE = 255;
|
||||
|
||||
var BlrWriter = exports.BlrWriter = function(size){
|
||||
this.buffer = new Buffer(size || 32);
|
||||
this.pos = 0;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addByte = function (b) {
|
||||
this.ensure(1);
|
||||
this.buffer.writeUInt8(b, this.pos);
|
||||
this.pos++;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addShort = function (b) {
|
||||
this.ensure(1);
|
||||
this.buffer.writeInt8(b, this.pos);
|
||||
this.pos++;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addSmall = function (b) {
|
||||
this.ensure(2);
|
||||
this.buffer.writeInt16LE(b, this.pos);
|
||||
this.pos += 2;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addWord = function (b) {
|
||||
this.ensure(2);
|
||||
this.buffer.writeUInt16LE(b, this.pos);
|
||||
this.pos += 2;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addNumeric = function (c, v) {
|
||||
|
||||
if (v < 256){
|
||||
this.ensure(3);
|
||||
this.buffer.writeUInt8(c, this.pos);
|
||||
this.pos++;
|
||||
this.buffer.writeUInt8(1, this.pos);
|
||||
this.pos++;
|
||||
this.buffer.writeUInt8(v, this.pos);
|
||||
this.pos++;
|
||||
return;
|
||||
}
|
||||
|
||||
this.ensure(6);
|
||||
this.buffer.writeUInt8(c, this.pos);
|
||||
this.pos++;
|
||||
this.buffer.writeUInt8(4, this.pos);
|
||||
this.pos++;
|
||||
this.buffer.writeInt32BE(v, this.pos);
|
||||
this.pos += 4;
|
||||
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addBytes = function (b) {
|
||||
|
||||
this.ensure(b.length);
|
||||
for (var i = 0, length = b.length; i < length; i++) {
|
||||
this.buffer.writeUInt8(b[i], this.pos);
|
||||
this.pos++;
|
||||
}
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addString = function (c, s, encoding) {
|
||||
this.addByte(c);
|
||||
|
||||
var len = Buffer.byteLength(s, encoding);
|
||||
if (len > MAX_STRING_SIZE)
|
||||
throw new Error('blr string is too big');
|
||||
|
||||
this.ensure(len + 1);
|
||||
this.buffer.writeUInt8(len, this.pos);
|
||||
this.pos++;
|
||||
this.buffer.write(s, this.pos, s.length, encoding);
|
||||
this.pos += len;
|
||||
};
|
||||
|
||||
BlrWriter.prototype.addBuffer = function (b) {
|
||||
this.addSmall(b.length);
|
||||
this.ensure(b.length);
|
||||
b.copy(this.buffer, this.pos);
|
||||
this.pos += b.length;
|
||||
};
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* BLR Reader
|
||||
*
|
||||
***************************************/
|
||||
|
||||
var BlrReader = exports.BlrReader = function(buffer) {
|
||||
this.buffer = buffer;
|
||||
this.pos = 0;
|
||||
};
|
||||
|
||||
BlrReader.prototype.readByteCode = function(){
|
||||
return this.buffer.readUInt8(this.pos++);
|
||||
};
|
||||
|
||||
BlrReader.prototype.readInt = function(){
|
||||
var len = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
var value;
|
||||
switch (len) {
|
||||
case 1:
|
||||
value = this.buffer.readInt8(this.pos);
|
||||
break;
|
||||
case 2:
|
||||
value = this.buffer.readInt16LE(this.pos);
|
||||
break;
|
||||
case 4:
|
||||
value = this.buffer.readInt32LE(this.pos)
|
||||
}
|
||||
this.pos += len;
|
||||
return value;
|
||||
};
|
||||
|
||||
BlrReader.prototype.readString = function(encoding){
|
||||
|
||||
var len = this.buffer.readUInt16LE(this.pos);
|
||||
var str;
|
||||
|
||||
this.pos += 2;
|
||||
if (len <= 0)
|
||||
return '';
|
||||
|
||||
str = this.buffer.toString(encoding, this.pos, this.pos + len);
|
||||
this.pos += len;
|
||||
return str;
|
||||
};
|
||||
|
||||
BlrReader.prototype.readSegment = function() {
|
||||
|
||||
var ret, tmp;
|
||||
var len = this.buffer.readUInt16LE(this.pos);
|
||||
|
||||
this.pos += 2;
|
||||
|
||||
while (len > 0) {
|
||||
|
||||
if (ret) {
|
||||
tmp = ret;
|
||||
ret = new Buffer(tmp.length + len);
|
||||
tmp.copy(ret);
|
||||
this.buffer.copy(ret, tmp.length, this.pos, this.pos + len);
|
||||
} else {
|
||||
ret = new Buffer(len);
|
||||
this.buffer.copy(ret, 0, this.pos, this.pos + len);
|
||||
}
|
||||
|
||||
this.pos += len;
|
||||
|
||||
if (this.pos === this.buffer.length)
|
||||
break;
|
||||
|
||||
len = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* XDR Writer
|
||||
*
|
||||
***************************************/
|
||||
|
||||
var XdrWriter = exports.XdrWriter = function(size){
|
||||
this.buffer = new Buffer(size || 32);
|
||||
this.pos = 0;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.ensure = BlrWriter.prototype.ensure = function (len) {
|
||||
var newlen = this.buffer.length;
|
||||
|
||||
while (newlen < this.pos + len)
|
||||
newlen *= 2
|
||||
|
||||
if (this.buffer.length >= newlen)
|
||||
return;
|
||||
|
||||
var b = new Buffer(newlen);
|
||||
this.buffer.copy(b);
|
||||
delete(this.buffer);
|
||||
this.buffer = b;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addInt = function (value) {
|
||||
this.ensure(4);
|
||||
this.buffer.writeInt32BE(value, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addInt64 = function (value) {
|
||||
this.ensure(8);
|
||||
var l = new Long(value);
|
||||
this.buffer.writeInt32BE(l.high_, this.pos);
|
||||
this.pos += 4;
|
||||
this.buffer.writeInt32BE(l.low_, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addUInt = function (value) {
|
||||
this.ensure(4);
|
||||
this.buffer.writeUInt32BE(value, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addString = function(s, encoding) {
|
||||
var len = Buffer.byteLength(s, encoding);
|
||||
var alen = align(len);
|
||||
this.ensure(alen + 4);
|
||||
this.buffer.writeInt32BE(len, this.pos);
|
||||
this.pos += 4;
|
||||
this.buffer.write(s, this.pos, len, encoding);
|
||||
this.pos += alen;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addText = function(s, encoding) {
|
||||
var len = Buffer.byteLength(s, encoding);
|
||||
var alen = align(len);
|
||||
this.ensure(alen);
|
||||
this.buffer.write(s, this.pos, len, encoding);
|
||||
this.pos += alen;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addBlr = function(blr) {
|
||||
var alen = align(blr.pos);
|
||||
this.ensure(alen + 4);
|
||||
this.buffer.writeInt32BE(blr.pos, this.pos);
|
||||
this.pos += 4;
|
||||
blr.buffer.copy(this.buffer, this.pos);
|
||||
this.pos += alen;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.getData = function() {
|
||||
return this.buffer.slice(0, this.pos);
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addDouble = function(value) {
|
||||
this.ensure(8);
|
||||
this.buffer.writeDoubleBE(value, this.pos);
|
||||
this.pos += 8;
|
||||
};
|
||||
|
||||
XdrWriter.prototype.addQuad = function(quad) {
|
||||
this.ensure(8);
|
||||
var b = this.buffer;
|
||||
b.writeInt32BE(quad.high, this.pos);
|
||||
this.pos += 4;
|
||||
b.writeInt32BE(quad.low, this.pos);
|
||||
this.pos += 4;
|
||||
};
|
||||
|
||||
/***************************************
|
||||
*
|
||||
* XDR Reader
|
||||
*
|
||||
***************************************/
|
||||
|
||||
var XdrReader = exports.XdrReader = function(buffer){
|
||||
this.buffer = buffer;
|
||||
this.pos = 0;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readInt = function () {
|
||||
var r = this.buffer.readInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readUInt = function () {
|
||||
var r = this.buffer.readUInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readInt64 = function () {
|
||||
var high = this.buffer.readInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
var low = this.buffer.readInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
return new Long(low, high);
|
||||
};
|
||||
|
||||
XdrReader.prototype.readShort = function () {
|
||||
var r = this.buffer.readInt16BE(this.pos);
|
||||
this.pos += 2;
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readQuad = function () {
|
||||
var b = this.buffer;
|
||||
var high = b.readInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
var low = b.readInt32BE(this.pos);
|
||||
this.pos += 4;
|
||||
return {low: low, high: high}
|
||||
};
|
||||
|
||||
XdrReader.prototype.readFloat = function () {
|
||||
var r = this.buffer.readFloatBE(this.pos);
|
||||
this.pos += 4;
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readDouble = function () {
|
||||
var r = this.buffer.readDoubleBE(this.pos);
|
||||
this.pos += 8;
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readArray = function () {
|
||||
var len = this.readInt();
|
||||
if (!len)
|
||||
return;
|
||||
var r = this.buffer.slice(this.pos, this.pos + len);
|
||||
this.pos += align(len);
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readBuffer = function (len) {
|
||||
if (!arguments.length)
|
||||
len = this.readInt();
|
||||
|
||||
if (!len)
|
||||
return;
|
||||
|
||||
var r = this.buffer.slice(this.pos, this.pos + len);
|
||||
this.pos += align(len);
|
||||
return r;
|
||||
};
|
||||
|
||||
XdrReader.prototype.readString = function (encoding) {
|
||||
var len = this.readInt();
|
||||
return this.readText(len, encoding);
|
||||
};
|
||||
|
||||
XdrReader.prototype.readText = function (len, encoding) {
|
||||
if (len <= 0)
|
||||
return '';
|
||||
|
||||
var r = this.buffer.toString(encoding, this.pos, this.pos + len);
|
||||
this.pos += align(len);
|
||||
return r;
|
||||
};
|
70
node_modules/node-firebird/package.json
generated
vendored
Normal file
70
node_modules/node-firebird/package.json
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "node-firebird",
|
||||
"version": "0.2.3",
|
||||
"description": "Pure JavaScript and Asynchronous Firebird client for Node.js.",
|
||||
"keywords": [
|
||||
"firebird",
|
||||
"database",
|
||||
"rdbms",
|
||||
"sql"
|
||||
],
|
||||
"homepage": "https://github.com/hgourvest/node-firebird",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hgourvest/node-firebird"
|
||||
},
|
||||
"author": {
|
||||
"name": "Henri Gourvest",
|
||||
"email": "hgourvest@gmail.com"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Popa Marius Adrian",
|
||||
"email": "mapopa@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Peter Širka",
|
||||
"email": "petersirka@gmail.com"
|
||||
}
|
||||
],
|
||||
"main": "./lib",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MPL-2.0",
|
||||
"url": "https://raw.githubusercontent.com/hgourvest/node-firebird/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"gitHead": "39dadf20e203a8300eb766a24deecbfe3757954a",
|
||||
"bugs": {
|
||||
"url": "https://github.com/hgourvest/node-firebird/issues"
|
||||
},
|
||||
"_id": "node-firebird@0.2.3",
|
||||
"scripts": {},
|
||||
"_shasum": "5af05dc7575543188b5005a59bd3e10537cff160",
|
||||
"_from": "node-firebird@",
|
||||
"_npmVersion": "1.4.28",
|
||||
"_npmUser": {
|
||||
"name": "mariuz",
|
||||
"email": "mapopa@gmail.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "hgourvest",
|
||||
"email": "hgourvest@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "mariuz",
|
||||
"email": "mapopa@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "petersirka",
|
||||
"email": "petersirka@gmail.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "5af05dc7575543188b5005a59bd3e10537cff160",
|
||||
"tarball": "http://registry.npmjs.org/node-firebird/-/node-firebird-0.2.3.tgz"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/node-firebird/-/node-firebird-0.2.3.tgz"
|
||||
}
|
BIN
node_modules/node-firebird/test/image.png
generated
vendored
Normal file
BIN
node_modules/node-firebird/test/image.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
441
node_modules/node-firebird/test/run.js
generated
vendored
Normal file
441
node_modules/node-firebird/test/run.js
generated
vendored
Normal file
@ -0,0 +1,441 @@
|
||||
var fb = require('../lib');
|
||||
var fs = require('fs');
|
||||
var os = require('os');
|
||||
|
||||
var assert = require('assert');
|
||||
var Path = require('path');
|
||||
var now = new Date();
|
||||
|
||||
var config = {
|
||||
|
||||
// Problem with privileges in OSX
|
||||
// database: Path.join(os.tmpdir(), 'test-' + new Date().getTime() + '.fdb'),
|
||||
|
||||
database: Path.join(process.cwd(), 'test-' + new Date().getTime() + '.fdb'),
|
||||
host: '127.0.0.1', // default
|
||||
port: 3050, // default
|
||||
user: 'SYSDBA', // default
|
||||
password: 'masterkey', // default
|
||||
role: null, // default
|
||||
pageSize: 4096, // default when creating database
|
||||
timeout: 3000 // default query timeout
|
||||
}
|
||||
|
||||
Array.prototype.async = function(cb) {
|
||||
|
||||
var self = this;
|
||||
var item = self.shift();
|
||||
|
||||
if (item === undefined) {
|
||||
if (cb)
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
item(function() {
|
||||
setImmediate(function() {
|
||||
self.async(cb);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
fb.attachOrCreate(config, function (err, db) {
|
||||
|
||||
if (err)
|
||||
throw err.message;
|
||||
|
||||
database = db;
|
||||
|
||||
var task = [];
|
||||
|
||||
task.push(test_create);
|
||||
task.push(test_reconnect);
|
||||
task.push(test_insert);
|
||||
task.push(test_select_insert); // for inserted rows
|
||||
task.push(test_update);
|
||||
task.push(test_select_update); // for updated rows
|
||||
task.push(test_transaction);
|
||||
|
||||
task.push(function(next) {
|
||||
db.detach(next);
|
||||
});
|
||||
|
||||
task.push(test_pooling);
|
||||
task.async();
|
||||
});
|
||||
|
||||
function test_create(next) {
|
||||
|
||||
var name = 'TEST ---> test_create';
|
||||
console.time(name);
|
||||
|
||||
// Create table
|
||||
database.query('CREATE TABLE test (ID INT, NAME VARCHAR(50), FILE BLOB, CREATED TIMESTAMP)', function(err) {
|
||||
assert.ok(!err, name + ': create table ' + err);
|
||||
|
||||
// Check if table exists
|
||||
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
||||
assert.ok(!err, name + ': check existing of table ' + err);
|
||||
|
||||
assert.ok(r[0].count === 0, name + ': check rows in new table');
|
||||
console.timeEnd(name);
|
||||
|
||||
// Next test
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_reconnect(next) {
|
||||
|
||||
var name = 'TEST ---> test_reconnect';
|
||||
console.time(name);
|
||||
database.connection._socket.end();
|
||||
database.on('reconnect', function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function test_insert(next) {
|
||||
|
||||
var name = 'TEST ---> test_insert';
|
||||
var query = [];
|
||||
|
||||
console.time(name);
|
||||
|
||||
// Insert record with blob (STREAM)
|
||||
query.push(function(next) {
|
||||
database.query('INSERT INTO test (ID, NAME, FILE, CREATED) VALUES(?, ?, ?, ?) RETURNING ID', [1, 'Firebird 1', fs.createReadStream('image.png'), '14.12.2014 12:12:12'], function(err, r) {
|
||||
assert.ok(!err, name + ': insert blob (stream) ' + err);
|
||||
assert.ok(r['id'] === 1, name + ': blob (stream) returning value');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Insert record with blob (BUFFER)
|
||||
query.push(function(next) {
|
||||
database.query('INSERT INTO test (ID, NAME, FILE, CREATED) VALUES(?, ?, ?, ?) RETURNING ID', [2, 'Firebird 2', fs.readFileSync('image.png'), '14.12.2014T12:12:12'], function(err, r) {
|
||||
assert.ok(!err, name + ': insert blob (buffer) ' + err);
|
||||
assert.ok(r['id'] === 2, name + ': blob (buffer) returning value');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Insert record without blob
|
||||
query.push(function(next) {
|
||||
database.query('INSERT INTO test (ID, NAME, CREATED) VALUES(?, ?, ?) RETURNING ID', [3, 'Firebird 3', now], function(err, r) {
|
||||
assert.ok(!err, name + ': insert without blob (buffer) (1) ' + err);
|
||||
assert.ok(r['id'] === 3, name + ': without blob (buffer) returning value');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Insert record without blob (without returning value)
|
||||
query.push(function(next) {
|
||||
database.query('INSERT INTO test (ID, NAME, CREATED) VALUES(?, ?, ?)', [4, 'Firebird 4', '2014-12-12 13:59'], function(err, r) {
|
||||
assert.ok(!err, name + ': insert without blob (buffer) (2) ' + err);
|
||||
assert.ok(err === undefined, name + ': insert without blob + without returning value');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
query.async(function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function test_update(next) {
|
||||
|
||||
var name = 'TEST ---> test_update';
|
||||
console.time(name);
|
||||
|
||||
var query = [];
|
||||
|
||||
// Insert record with blob (STREAM)
|
||||
query.push(function(next) {
|
||||
database.query('UPDATE test SET NAME=?, FILE=? WHERE Id=1', ['Firebird 1 (UPD)', fs.createReadStream('image.png')], function(err, r) {
|
||||
assert.ok(!err, name + ': update blob (stream) ' + err);
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Insert record with blob (BUFFER)
|
||||
query.push(function(next) {
|
||||
database.query('UPDATE test SET NAME=?, FILE=? WHERE Id=2', ['Firebird 2 (UPD)', fs.readFileSync('image.png')], function(err, r) {
|
||||
assert.ok(!err, name + ': update blob (buffer) ' + err);
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
query.async(function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function test_select_insert(next) {
|
||||
|
||||
var name = 'TEST ---> test_select_insert';
|
||||
console.time(name);
|
||||
|
||||
var query = [];
|
||||
|
||||
// Classic select
|
||||
query.push(function(next) {
|
||||
database.query('SELECT * FROM test', function(err, r) {
|
||||
|
||||
var row = r[0];
|
||||
var row2 = r[2];
|
||||
var row4 = r[3];
|
||||
|
||||
assert.ok(!err, name + ': problem (1) ' + err);
|
||||
assert.ok(row !== undefined, name + ': problem (2)');
|
||||
assert.ok(row.id === 1 && row.name === 'Firebird 1', name + ': problem with deserializer');
|
||||
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
||||
assert.ok(row.created.getMonth() === 11 && row.created.getDate() === 14 && row.created.getFullYear() === 2014 && row.created.getHours() === 12 && row.created.getMinutes() === 12, name + ': date problem (1)');
|
||||
assert.ok(row2.created.getTime() === now.getTime(), name + ': date problem (2)');
|
||||
assert.ok(row4.created.getMonth() === 11 && row4.created.getDate() === 12 && row4.created.getFullYear() === 2014 && row4.created.getHours() === 13 && row4.created.getMinutes() === 59, name + ': date problem (3)');
|
||||
|
||||
row.file(function(err, name, e) {
|
||||
|
||||
assert.ok(!err, name + ': reading blob ' + err);
|
||||
|
||||
var count = 0;
|
||||
|
||||
e.on('data', function(buffer) {
|
||||
count += buffer.length;
|
||||
});
|
||||
|
||||
e.on('end', function() {
|
||||
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
// Select to array
|
||||
query.push(function(next) {
|
||||
// Deserialize to array
|
||||
database.execute('SELECT COUNT(*), SUM(Id) FROM test', function(err, r) {
|
||||
assert.ok(r[0][0] === 4 && r[0][1] === 10, name + ': array deserializer problem');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Sequentially select (object)
|
||||
query.push(function(next) {
|
||||
var counter = 0;
|
||||
database.sequentially('SELECT Id FROM test', function(row, index) {
|
||||
counter += row.id;
|
||||
}, function() {
|
||||
assert.ok(counter === 10, name + ': sequentially (object)');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Sequentially select (array)
|
||||
query.push(function(next) {
|
||||
var counter = 0;
|
||||
database.sequentially('SELECT Id FROM test', function(row, index) {
|
||||
counter += row[0];
|
||||
}, function() {
|
||||
assert.ok(counter === 10, name + ': sequentially (array)');
|
||||
next();
|
||||
}, true);
|
||||
});
|
||||
|
||||
query.async(function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function test_select_update(next) {
|
||||
|
||||
var name = 'TEST ---> test_select_update';
|
||||
console.time(name);
|
||||
|
||||
var query = [];
|
||||
|
||||
// Classic select 1
|
||||
query.push(function(next) {
|
||||
database.query('SELECT * FROM test WHERE Id=1', function(err, r) {
|
||||
|
||||
var row = r[0];
|
||||
|
||||
assert.ok(!err, name + ': problem (1) ' + err);
|
||||
assert.ok(row !== undefined, name + ': problem (2)');
|
||||
assert.ok(row.id === 1 && row.name === 'Firebird 1 (UPD)', name + ': problem with deserializer');
|
||||
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
||||
|
||||
row.file(function(err, name, e) {
|
||||
|
||||
assert.ok(!err, name + ': reading blob');
|
||||
|
||||
var count = 0;
|
||||
|
||||
e.on('data', function(buffer) {
|
||||
count += buffer.length;
|
||||
});
|
||||
|
||||
e.on('end', function() {
|
||||
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Classic select 2
|
||||
query.push(function(next) {
|
||||
database.query('SELECT * FROM test WHERE Id=2', function(err, r) {
|
||||
|
||||
var row = r[0];
|
||||
|
||||
assert.ok(!err, name + ': problem (1) ' + err);
|
||||
assert.ok(row !== undefined, name + ': problem (2)');
|
||||
assert.ok(row.id === 2 && row.name === 'Firebird 2 (UPD)', name + ': problem with deserializer');
|
||||
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
||||
|
||||
row.file(function(err, name, e) {
|
||||
|
||||
assert.ok(!err, name + ': reading blob');
|
||||
|
||||
var count = 0;
|
||||
|
||||
e.on('data', function(buffer) {
|
||||
count += buffer.length;
|
||||
});
|
||||
|
||||
e.on('end', function() {
|
||||
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
query.async(function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function test_transaction(next) {
|
||||
|
||||
var name = 'TEST ---> test_transaction';
|
||||
console.time(name);
|
||||
|
||||
var query = [];
|
||||
|
||||
// Invalid transaction
|
||||
query.push(function(next) {
|
||||
database.transaction(function(err, transaction) {
|
||||
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [5, 'Transaction 1'], function(err) {
|
||||
assert.ok(!err, name + ': problem (1) ' + err);
|
||||
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [6, 'Transaction 2'], function(err) {
|
||||
assert.ok(!err, name + ': problem (2)');
|
||||
transaction.query('INSERT INTO testa (ID, NAME) VALUES(?, ?)', [7, 'Transaction 3'], function(err) {
|
||||
assert.ok(err, name + ': problem (3)');
|
||||
transaction.rollback(function(err) {
|
||||
assert.ok(!err, name + ': rollback problem');
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Select to array
|
||||
query.push(function(next) {
|
||||
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
||||
assert.ok(r[0].count === 4, name + ': transaction does not work (rollback)');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
// Valid transaction
|
||||
query.push(function(next) {
|
||||
database.transaction(function(err, transaction) {
|
||||
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [5, 'Transaction 1'], function(err) {
|
||||
assert.ok(!err, name + ': problem (4) ' + err);
|
||||
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [6, 'Transaction 2'], function(err) {
|
||||
assert.ok(!err, name + ': problem (5)');
|
||||
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [7, 'Transaction 3'], function(err) {
|
||||
assert.ok(!err, name + ': problem (6) ' + err);
|
||||
transaction.commit(function(err) {
|
||||
assert.ok(!err, name + ': commit problem ' + err);
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Select to array
|
||||
query.push(function(next) {
|
||||
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
||||
assert.ok(r[0].count === 7, name + ': transaction does not work (commit)');
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
query.async(function() {
|
||||
console.timeEnd(name);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function test_pooling(next) {
|
||||
|
||||
var name = 'TEST ---> test_pooling';
|
||||
console.time(name);
|
||||
|
||||
var query = [];
|
||||
var pool = fb.pool(2, config);
|
||||
|
||||
query.push(function(next) {
|
||||
pool.get(function(err, db) {
|
||||
setTimeout(function() {
|
||||
// detach a current connection (socket is opened)
|
||||
db.detach();
|
||||
}, 1000);
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
query.push(function(next) {
|
||||
pool.get(function(err, db) {
|
||||
setTimeout(function() {
|
||||
// detach a current connection (socket is still opened)
|
||||
db.detach();
|
||||
}, 1500);
|
||||
next();
|
||||
});
|
||||
});
|
||||
|
||||
query.push(function(next) {
|
||||
pool.get(function(err, db) {
|
||||
next();
|
||||
});
|
||||
assert.ok(pool.pending.length > 0, name + ': pool pending');
|
||||
});
|
||||
|
||||
query.push(function(next) {
|
||||
setTimeout(function() {
|
||||
pool.destroy();
|
||||
console.timeEnd(name);
|
||||
}, 500);
|
||||
next();
|
||||
});
|
||||
|
||||
query.async(next);
|
||||
}
|
Loading…
Reference in New Issue
Block a user