1 | url = require('url')
|
2 | anyDB = require('any-db')
|
3 | queries = require('./queries')
|
4 | dialects = require('./dialects')
|
5 |
|
6 | module.exports = -> Engine.create.apply Engine, arguments
|
7 |
|
8 | class Engine
|
9 | ###
|
10 | ``Engine`` is gesundheits interface to an actual database.
|
11 |
|
12 | Engines have all of the :ref:`query factory functions <query-factories>`
|
13 | attached to them as instance methods that automatically bind created queries
|
14 | to the engine. They also have these additionaly methods
|
15 | ###
|
16 |
|
17 | @create = (dbUrl, poolOptions) ->
|
18 | ###
|
19 | Create an :class:`engine::Engine` instance from an Any-DB_ connect string
|
20 | and extra connection pool options, this is exported by gesundheit as
|
21 | ``gesundheit.engine(...)``.
|
22 |
|
23 | :ref:`This example <engine-usage-example>` shows the most common way to set up
|
24 | a single default database engine for an application.
|
25 |
|
26 | .. _Any-DB: https://github.com/grncdr/node-any-db
|
27 | .. _Any-DB ConnectionPool: https://github.com/grncdr/node-any-db/blob/master/API.md#connectionpool
|
28 | ###
|
29 | parsed = url.parse(dbUrl)
|
30 | driverName = parsed.protocol.replace(':', '').split('+').shift()
|
31 |
|
32 | if driverName is 'fake'
|
33 | pool = fakePool()
|
34 | if parsed.protocol.match('pretty')
|
35 | dialectType = dialects.pretty
|
36 | else
|
37 | dialectType = dialects.base
|
38 | else
|
39 | pool = anyDB.createPool(dbUrl, poolOptions)
|
40 | dialectType = dialects[driverName]
|
41 |
|
42 | if not dialectType?
|
43 | throw new Error('no such dialect: ' + driverName)
|
44 | new Engine driverName, dbUrl, pool, new dialectType()
|
45 |
|
46 | constructor: (@driver, @url, @pool, @dialect) ->
|
47 | queries.mixinFactoryMethods @
|
48 |
|
49 | query: (statement, params, callback) ->
|
50 | ###
|
51 | Passes arguments directly to the query method of the underlying `Any-DB
|
52 | ConnectionPool`_
|
53 | ###
|
54 | @pool.query(arguments...)
|
55 |
|
56 | begin: (callback) ->
|
57 | ###
|
58 | Start a new transaction and return it.
|
59 |
|
60 | The returned object behaves exactly like a new engine, but has ``commit``
|
61 | and ``rollback`` methods instead of ``close``. (In fact it's an `Any-DB
|
62 | Transaction`_ that has had the query factory functions mixed in to it).
|
63 |
|
64 | .. _Any-DB Transaction: https://github.com/grncdr/node-any-db/blob/master/API.md#transaction
|
65 | ###
|
66 | tx = queries.mixinFactoryMethods(@pool.begin(callback))
|
67 | tx.engine = @
|
68 | tx.compile = @dialect.compile.bind(@dialect)
|
69 | tx
|
70 |
|
71 | compile: (root) ->
|
72 | ###
|
73 | Render an AST to a SQL string and collect parameters
|
74 | ###
|
75 | @dialect.compile(root)
|
76 |
|
77 | close: ->
|
78 | ###
|
79 | Closes the internal connection pool.
|
80 | ###
|
81 | @pool.close()
|
82 |
|
83 | fakePool = ->
|
84 | ###
|
85 | Create a fake database connection pool that throws errors if you try to
|
86 | execute a query.
|
87 | ###
|
88 | return {
|
89 | begin: (cb) ->
|
90 | if cb then process.nextTick(cb.bind(null, engine))
|
91 | engine
|
92 | query: (sql, params, cb) ->
|
93 | throw new Error("Cannot query with fakeEngine. Do `gesundheit.defaultEngine = gesundheit.engine(url)` before querying")
|
94 | close: ->
|
95 | }
|