Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
example: make the sqlite3 example use explicit "ref" types (rather th…
…an "pointer")
- Loading branch information
1 parent
025fdd2
commit c273289
Showing
1 changed file
with
59 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}) |