Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

any-db-adapter-spec

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

any-db-adapter-spec - npm Package Compare versions

Comparing version 0.0.1 to 2.0.2

tests/basic/interfaces.js

2

package.json
{
"name": "any-db-adapter-spec",
"version": "0.0.1",
"version": "2.0.2",
"description": "Specification and test suite for any-db adapters",

@@ -5,0 +5,0 @@ "main": "test-any-db-adapter.js",

@@ -12,32 +12,32 @@ # Any-DB API

## Objects
## Interfaces
- [Connection](#connection)
- [Query](#query)
- [Transaction][] (external link)
- [Queryable][] - a common interface implemented by connections, pools, and
transactions.
- [Connection][] - the "transport" responsible for getting SQL queries to a
database, and streaming results back through a `Query` instance.
- [Query][] - a [Readable][] stream that emits row objects.
## Connection
## Queryable
```ocaml
Connection := EventEmitter & {
adapter: String,
query: (text: String, params: Array?, Continuation<Results>?) => Query,
begin: (statement: String?, Continuation<Transaction>?) => Transaction,
end: (Continuation<void>?) => void
Queryable := EventEmitter & {
adapter: Adapter
query: (text: String, params: Array?, Continuation<Results>?) => Query
query: (Query) => Query
}
```
Connection objects are obtained using [createConnection][] from [Any-DB][] or
[ConnectionPool.acquire][], both of which delegate to the
[createConnection](#adaptercreateconnection) implementation of the specified
adapter.
Known implementations:
- [Connection][Connection]
- [ConnectionPool][ConnectionPool] (external)
- [Transaction][Transaction] (external).
`Connection` instances are guaranteed to have the methods and events listed
here, but drivers (and their adapters) may have additional methods or emit
additional events. If you need to access a feature of your database that is not
described here (such as Postgres' server-side prepared statements), consult the
documentation for the database driver.
### Queryable.adapter
### Connection.query
The [Adapter][] instance that will be used by this `Queryable` for creating
[Query][] instances and/or connections.
### Queryable.query
```ocaml

@@ -49,5 +49,6 @@ (text: String, params: Array?, Continuation<ResultSet>?) => Query

Execute a SQL statement using bound parameters (if they are provided) and
return a [Query](#query) object for the in-progress query. If a
`Continuation<Results>` is provided it will be passed a [ResultSet](#resultset)
object after the query has completed.
return a [Query][] object that is a [Readable][] stream of the resulting
rows. If a `Continuation<Results>` is provided the rows returned by the
database will be aggregated into a [ResultSet][] which will be passed to the
continuation after the query has completed.

@@ -60,3 +61,3 @@ The second form is not needed for normal use, but must be implemented by

```javascript
conn.query('SELECT * FROM my_table', function (err, res) {
queryable.query('SELECT * FROM my_table', function (err, res) {
if (err) return console.error(err)

@@ -68,59 +69,46 @@ res.rows.forEach(console.log)

*EventEmitter-style*
*Stream-style*
```javascript
conn.query('SELECT * FROM my_table')
queryable.query('SELECT * FROM my_table')
.on('error', console.error)
.on('row', console.log)
.on('data', console.log)
.on('end', function () { console.log('All done!') })
```
### Connection.begin
### Queryable events
- `'query', query` - Emitted immediately before a query is executed.
## Connection
```ocaml
(statement: String?, Continuation<Transaction>?) => Transaction
Connection := Queryable & {
end: (Continuation<void>?) => void
}
```
Start a new database transaction and return a [Transaction][] to manage it. If
`statement` is given it will be used in place of the default statement
(`BEGIN`). If a `Continuation` is given it will be called after the database
transaction has successfully started (or failed to do so).
Known implementations:
*Note for adapter authors*: This method is trivially implemented by delegating
to [Transaction.begin][] from [any-db-transaction][] .
- [any-db-mysql][] (external)
- [any-db-postgres][] (external)
- [any-db-sqlite3][] (external)
*Callback-style*
```javascript
conn.begin(function (err, transaction) {
if (err) return console.error(err)
// Do work using transaction
transaction.query(...)
transaction.commit()
})
```
Connection objects are obtained using [createConnection][] from [Any-DB][] or
[ConnectionPool.acquire][], both of which delegate to the
[createConnection](#adaptercreateconnection) implementation of the specified
adapter.
*Synchronous-style*
```javascript
var transaction = conn.begin()
transaction.on('error', console.error)
// Do work using transaction, queries are queued until transaction successfully
// starts.
transaction.query(...)
transaction.commit()
```
While all `Connection` objects implement the [Queryable][] interface, the
implementations in each adapter may add additional methods or emit additional
events. If you need to access a feature of your database that is not described
here (such as Postgres' server-side prepared statements), consult the
documentation for your adapter.
See also: the [Transaction][] API docs.
### Connection.end
`conn.end([callback])`
`(Continuation<void>) => void`
Close the database connection. If `callback` is given it will be called after
the connection has closed.
Close the database connection. If a continuation is provided it will be
called after the connection has closed.
### Connection.adapter
`conn.adapter`
Contains the adapter name used for this connection, e.g. `'sqlite3'`, etc.
### Connection Events

@@ -134,3 +122,3 @@

```ocaml
Query := EventEmitter & {
Query := Readable<Object> & {
text: String,

@@ -141,7 +129,14 @@ values: Array

Query objects are returned by the `query` methods of [connections][Connection.query],
[pools][ConnectionPool.query], and [transactions][Transaction.query]. Like
connections, query objects are created by an adapter and may have more methods
and events than are described here.
`Query` objects are returned by the [Queryable.query][Queryable.query] method,
available on [connections][Connection], [pools][ConnectionPool.query], and
[transactions][Transaction.query]. Queries are instances of [Readable][], and
as such can be [piped][Readable.pipe] through transforms and support backpressure
for more efficient memory-usage on very large results sets. (Note: at this time
the `sqlite3` driver does not support backpressure)
Internally, `Query` instances are
[created by a database Adapter][Adapter.createQuery] and may have more methods,
properties, and events than are described here. Consult the documentation for
your specific adapter to find out about any extensions.
### Query.text

@@ -158,6 +153,29 @@

* `'error', err` - Emitted if the query results in an error.
* `'row', row` - Emitted for each row in the queries result set.
* `'end', [res]` - Emitted when the query completes.
* `'error', error` - Emitted if the query results in an error.
* `'fields', fields` - An array of [Field][ResultSet] objects emitted before
any `'data'` events.
* `'data', row` - Emitted for each row in the query result set.
* `'end'` - Emitted when the query completes.
## ResultSet
```ocaml
ResultSet := {
fields: Array<Field>
rows: Array<Object<Any>>
rowCount: Integer
lastInsertId: Any?
}
Field := {
name: String
{* other properties are driver specific *}
}
```
`ResultSet` objects are just plain data that collect results of a query when a
continuation is provided to [Queryable.query][]. The `lastInsertId` is optional,
and currently supported by `sqlite3` and `mysql` but not `postgres`, because
it is not supported by Postgres itself.
## Adapter

@@ -167,4 +185,5 @@

Adapter: {
createConnection: (Object, Continuation<Connection>?) => Connection,
createQuery: (String, Array?, Continuation<Results>?) => Query,
name: String
createConnection: (Object, Continuation<Connection>?) => Connection,
createQuery: (String, Array?, Continuation<Results>?) => Query,
}

@@ -176,2 +195,6 @@ ```

### Adapter.name
The string name of the adapter, e.g. `'mysql'`, `'postgres'` or `'sqlite3'`.
### Adapter.createConnection

@@ -195,6 +218,6 @@

Create a [Query](#query) that may be executed later on by a [Connection][].
While this function is rarely needed by user code, it makes it possible for
[ConnectionPool.query][] and [Transaction.query][] to return a [Query][] object
synchronously in the same style as a [Connection.query][].
Create a [Query](#query) that *may* eventually be executed later on by a
[Connection][]. While this function is rarely needed by user code, it makes
it possible for [ConnectionPool.query][] and [Transaction.query][] to fulfill
the [Queryable.query][] contract by synchronously returning a [Query][] stream.

@@ -207,16 +230,25 @@ # License

[once]: http://npm.im/once
[test suite]: tests
[parse-db-url]: https://github.com/grncdr/parse-db-url#api
[any-db]: https://github.com/grncdr/node-any-db
[any-db-mysql]: https://github.com/grncdr/node-any-db-mysql
[any-db-postgres]: https://github.com/grncdr/node-any-db-postgres
[any-db-sqlite3]: https://github.com/grncdr/node-any-db-sqlite3
[createConnection]: https://github.com/grncdr/node-any-db#exportscreateconnection
[parse-db-url]: https://github.com/grncdr/parse-db-url#api
[Connection]: #connection
[Connection.query]: #connectionquery
[Query]: #query
[Readable]: http://nodejs.org/api/stream.html#stream_class_stream_readable
[Readable.pipe]: http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options
[ConnectionPool.query]: https://github.com/grncdr/node-any-db-pool#connectionpoolquery
[ConnectionPool.acquire]: https://github.com/grncdr/node-any-db-pool#connectionpoolacquire
[ConnectionPool]: https://github.com/grncdr/node-any-db-pool#api
[Transaction]: https://github.com/grncdr/node-any-db-transaction
[Transaction]: https://github.com/grncdr/node-any-db-transaction#api
[any-db-transaction]: https://github.com/grncdr/node-any-db-transaction
[Transaction.begin]: https://github.com/grncdr/node-any-db-transaction#transactionquery
[Transaction.query]: https://github.com/grncdr/node-any-db-transaction#transactionquery
[test suite]: tests
[Queryable]: #queryable
[Queryable.query]: #queryablequery
[Connection]: #connection
[Connection.query]: #connectionquery
[Query]: #query
[Adapter.createQuery]: #adaptercreatequery

@@ -1,3 +0,3 @@

require('../test').withConnection("Last insert id", function (conn, t) {
if (conn.adapter == 'postgres') {
require('../test')("Last insert id", function (conn, t) {
if (conn.adapter.name == 'postgres') {
t.skip("Last insert ID not supported by postgres")

@@ -8,20 +8,21 @@ return t.end()

debugger
conn.query("DROP TABLE last_insert_id_test", function (err) {})
if (conn.adapter == 'sqlite3')
if (conn.adapter.name == 'sqlite3')
conn.query("CREATE TABLE last_insert_id_test (id integer primary key autoincrement, a int)")
else if (conn.adapter == 'mysql')
conn.query("CREATE TABLE last_insert_id_test (id integer primary key auto_increment, a int)")
else if (conn.adapter.name == 'mysql')
{
conn.query("CREATE TABLE last_insert_id_test (id integer primary key auto_increment, a int)").on('end', function () { console.log('create complete') })
}
else throw new Error("Unknown adapter: " + conn.adapter.name)
conn.query('INSERT INTO last_insert_id_test (a) VALUES (123)', function (err, res) {
if (err) throw err
t.equal(res.lastInsertId, 1)
t.equal(res.lastInsertId, 1)
conn.query('INSERT INTO last_insert_id_test (a) VALUES (456)', function (err, res) {
if (err) throw err
t.equal(res.lastInsertId, 2)
t.equal(res.lastInsertId, 2)
})
})
}
)
})

@@ -1,11 +0,11 @@

require('../test').withTransaction("Streaming results", function (tx, test) {
require('../test')("Streaming results", function (conn, test) {
test.plan(11)
tx.query("DROP TABLE IF EXISTS streaming_test", function (err) { /* swallow errors */ })
tx.query("CREATE TABLE streaming_test (a int)")
conn.query("DROP TABLE IF EXISTS streaming_test", function (err) { /* swallow errors */ })
conn.query("CREATE TABLE streaming_test (a int)")
var placeHolder = tx.adapter == 'postgres' ? '($1)' : '(?)';
var placeHolder = conn.adapter.name == 'postgres' ? '($1)' : '(?)';
var vals = []
for (var i = 0; i < 10; i++) {
tx.query('INSERT INTO streaming_test (a) VALUES ' + placeHolder, [i])
conn.query('INSERT INTO streaming_test (a) VALUES ' + placeHolder, [i])
vals.push(i)

@@ -15,7 +15,9 @@ }

var i = 0;
tx.query('SELECT a FROM streaming_test')
.on('row', function (row) { test.equal(row.a, vals.shift()) })
.on('end', function (result) {
conn.query('SELECT a FROM streaming_test')
.on('data', function (row) {
test.equal(row.a, vals.shift())
})
.on('end', function () {
test.deepEqual(vals, [])
})
})
var tape = require('tape')
var test = module.exports = tape.bind(null)
test.withAdapter = function (description, callback) {
test(description, function (t) {
var config = require('../config')
callback(config, t)
})
}
test.withConnection = maybeOpts(function (description, opts, callback) {
module.exports = function test (description, opts, callback) {
if (!callback) {
callback = opts
opts = {}
}
tape(description, function (t) {

@@ -21,30 +16,2 @@ var config = require('../config')

})
})
test.withTransaction = maybeOpts(function (description, opts, callback) {
test(description, function (t) {
var config = require('../config')
config.adapter.createConnection(config.url, function (err, conn) {
if (err) throw err
var tx = conn.begin()
t.on('end', function () {
if (tx.state() != 'closed') {
tx.rollback(conn.end.bind(conn))
} else {
conn.end()
}
})
callback(tx, t)
})
})
})
function maybeOpts(f) {
return function (description, opts, callback) {
if (!callback) {
callback = opts
opts = {}
}
f(description, opts, callback)
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc