Skip to content

Commit

Permalink
example: make the sqlite3 example use explicit "ref" types (rather th…
Browse files Browse the repository at this point in the history
…an "pointer")
  • Loading branch information
TooTallNate committed Sep 27, 2012
1 parent 025fdd2 commit c273289
Showing 1 changed file with 59 additions and 31 deletions.
90 changes: 59 additions & 31 deletions example/sqlite.js
@@ -1,62 +1,90 @@
var ffi = require('../')
, fs = require('fs')
, ref = require('ref')
, assert = require('assert')
, dbName = 'test.sqlite3'

/**
* Module dependencies.
*/

var fs = require('fs')
, ref = require('ref')
, ffi = require('../')

/**
* The filename of the sqlite3 database to use.
*/

var dbName = process.argv[2] || 'test.sqlite3'

/**
* "ref" types that the sqlite3 functions will use.
*/

var sqlite3 = 'void' // `sqlite3` is an "opaque" type, so we don't know its layout
, sqlite3Ptr = ref.refType(sqlite3)
, sqlite3PtrPtr = ref.refType(sqlite3Ptr)
, sqlite3_exec_callback = 'pointer' // TODO: use ffi.Callback when #76 is implemented
, stringPtr = ref.refType('string')

// create FFI'd versions of the libsqlite3 function we're interested in
var SQLite3 = ffi.Library('libsqlite3', {
'sqlite3_open': [ 'int32', [ 'string', 'pointer' ] ],
'sqlite3_close': [ 'int32', [ 'pointer' ] ],
'sqlite3_changes': [ 'int32', [ 'pointer' ]],
'sqlite3_exec': [ 'int32', [ 'pointer', 'string', 'pointer', 'pointer', 'pointer' ] ],
'sqlite3_libversion': [ 'string', [ ] ],
'sqlite3_open': [ 'int', [ 'string', sqlite3PtrPtr ] ],
'sqlite3_close': [ 'int', [ sqlite3Ptr ] ],
'sqlite3_changes': [ 'int', [ sqlite3Ptr ]],
'sqlite3_exec': [ 'int', [ sqlite3Ptr, 'string', sqlite3_exec_callback, 'void *', stringPtr ] ],
})

// print out the "libsqlite3" version number
console.log('Using libsqlite3 version %j...', SQLite3.sqlite3_libversion())

// create a storage area for the db pointer SQLite3 gives us
var db = new Buffer(ref.sizeof.pointer)
var db = ref.alloc(sqlite3PtrPtr)

console.log('Opening ' + dbName + '...')
// open the database object
console.log('Opening %j...', dbName)
SQLite3.sqlite3_open(dbName, db)
var dbh = db.readPointer() // we have to extract the pointer as it's an output param

console.log('Creating and/or clearing foo table...')
// we don't care about the `sqlite **`, but rather the `sqlite *` that it's
// pointing to, so we must deref()
db = db.deref()

SQLite3.sqlite3_exec(dbh, 'CREATE TABLE foo (bar VARCHAR);', null, null, null)
SQLite3.sqlite3_exec(dbh, 'DELETE FROM foo;', null, null, null)
// execute a couple SQL queries to create the table "foo" and ensure it's empty
console.log('Creating and/or clearing foo table...')
SQLite3.sqlite3_exec(db, 'CREATE TABLE foo (bar VARCHAR);', null, null, null)
SQLite3.sqlite3_exec(db, 'DELETE FROM foo;', null, null, null)

// execute a few INSERT queries into the "foo" table
console.log('Inserting bar 5 times...')

for (var i = 0; i < 5; i++) {
SQLite3.sqlite3_exec(dbh, 'INSERT INTO foo VALUES(\'baz' + i + '\');', null, null, null)
SQLite3.sqlite3_exec(db, 'INSERT INTO foo VALUES(\'baz' + i + '\');', null, null, null)
}

// we can also run queries asynchronously on the thread pool. this is good for
// when you expect a query to take a long time. when running SELECT queries, you
// pass a callback function that gets invoked for each record found. since we're
// running asynchronously, you pass a second callback function that will be
// invoked when the query has completed.
var rowCount = 0
var callback = ffi.Callback('int32', ['pointer', 'int32', 'pointer', 'pointer'], function(tmp, cols, argv, colv) {
var callback = ffi.Callback('int', ['void *', 'int', stringPtr, stringPtr], function (tmp, cols, argv, colv) {
var obj = {}

for (var i = 0; i < cols; i++) {
var colName = colv.readPointer().readCString()
var colData = argv.readPointer().readCString()
var colName = colv.deref()
var colData = argv.deref()
obj[colName] = colData
}

console.log('Row: ' + JSON.stringify(obj))
console.log('Row: %j', obj)
rowCount++

return 0
})

var fin = false

SQLite3.sqlite3_exec.async(dbh, 'SELECT * FROM foo;', callback, null, null, function(err, ret) {
var b = new Buffer('test')
SQLite3.sqlite3_exec.async(db, 'SELECT * FROM foo;', callback, b, null, function (err, ret) {
if (err) throw err
console.log('Total Rows: ' + rowCount)
console.log('Changes: ' + SQLite3.sqlite3_changes(dbh))
console.log('Total Rows: %j', rowCount)
console.log('Changes: %j', SQLite3.sqlite3_changes(db))
console.log('Closing...')
SQLite3.sqlite3_close(dbh)
SQLite3.sqlite3_close(db)
fs.unlinkSync(dbName)
fin = true
})

process.on('exit', function () {
assert(fin)
})

0 comments on commit c273289

Please sign in to comment.