Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
node-sqlite3
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
俞永鹏
node-sqlite3
Commits
db72749d
Commit
db72749d
authored
Feb 14, 2011
by
Konstantin Käfer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
unify indentation and rework database opening, closing and garbage collection
parent
493050a9
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
360 additions
and
177 deletions
+360
-177
sqlite3.js
lib/sqlite3.js
+6
-1
database.cc
src/database.cc
+161
-111
database.h
src/database.h
+37
-27
macros.h
src/macros.h
+101
-25
sqlite3_bindings.cc
src/sqlite3_bindings.cc
+43
-0
statement.cc
src/statement.cc
+10
-10
blob.test.js
test/blob.test.js
+2
-3
No files found.
lib/sqlite3.js
View file @
db72749d
...
@@ -16,6 +16,9 @@
...
@@ -16,6 +16,9 @@
var
sqlite3
=
module
.
exports
=
exports
=
require
(
'./sqlite3_bindings'
);
var
sqlite3
=
module
.
exports
=
exports
=
require
(
'./sqlite3_bindings'
);
var
sys
=
require
(
"sys"
);
var
sys
=
require
(
"sys"
);
/*
sqlite3.Database.prototype.query = function(sql, bindings, rowCallback) {
sqlite3.Database.prototype.query = function(sql, bindings, rowCallback) {
var self = this;
var self = this;
...
@@ -68,7 +71,7 @@ function _doStep(db, statement, rowCallback) {
...
@@ -68,7 +71,7 @@ function _doStep(db, statement, rowCallback) {
// Execute a single SQL query with the given optional parameters. Calls
// Execute a single SQL query with the given optional parameters. Calls
// `callback` with all rows or an error on query completion.
// `callback` with all rows or an error on query completion.
sqlite3
.
Database
.
prototype
.
execute
=
function
(
sql
/* , bindings, callback
*/
)
{
sqlite3.Database.prototype.execute = function (sql /* , bindings, callback ) {
var self = this;
var self = this;
var bindings, callback;
var bindings, callback;
var n = arguments.length;
var n = arguments.length;
...
@@ -248,3 +251,4 @@ sqlite3.sanitizeError = function(err, data) {
...
@@ -248,3 +251,4 @@ sqlite3.sanitizeError = function(err, data) {
'" with values ' + JSON.stringify(data, false, 4);
'" with values ' + JSON.stringify(data, false, 4);
return err;
return err;
};
};
*/
\ No newline at end of file
src/database.cc
View file @
db72749d
...
@@ -38,17 +38,19 @@ void Database::Init(v8::Handle<Object> target) {
...
@@ -38,17 +38,19 @@ void Database::Init(v8::Handle<Object> target) {
constructor_template
->
SetClassName
(
String
::
NewSymbol
(
"Database"
));
constructor_template
->
SetClassName
(
String
::
NewSymbol
(
"Database"
));
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"open"
,
Open
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"open"
,
Open
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"openSync"
,
OpenSync
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"close"
,
Close
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"close"
,
Close
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"closeSync"
,
CloseSync
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"prepare"
,
Prepare
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"prepare"
,
Prepare
);
NODE_SET_PROTOTYPE_METHOD
(
constructor_template
,
"prepareAndStep"
,
PrepareAndStep
);
target
->
Set
(
v8
::
String
::
NewSymbol
(
"Database"
),
target
->
Set
(
v8
::
String
::
NewSymbol
(
"Database"
),
constructor_template
->
GetFunction
());
constructor_template
->
GetFunction
());
// insert/update execution result mask
// insert/update execution result mask
NODE_DEFINE_CONSTANT
(
target
,
EXEC_EMPTY
);
NODE_DEFINE_CONSTANT
(
target
,
EXEC_EMPTY
);
NODE_DEFINE_CONSTANT
(
target
,
EXEC_LAST_INSERT_ID
);
NODE_DEFINE_CONSTANT
(
target
,
EXEC_LAST_INSERT_ID
);
NODE_DEFINE_CONSTANT
(
target
,
EXEC_AFFECTED_ROWS
);
NODE_DEFINE_CONSTANT
(
target
,
EXEC_AFFECTED_ROWS
);
}
}
Handle
<
Value
>
Database
::
New
(
const
Arguments
&
args
)
{
Handle
<
Value
>
Database
::
New
(
const
Arguments
&
args
)
{
...
@@ -58,152 +60,170 @@ Handle<Value> Database::New(const Arguments& args) {
...
@@ -58,152 +60,170 @@ Handle<Value> Database::New(const Arguments& args) {
return
args
.
This
();
return
args
.
This
();
}
}
int
Database
::
EIO_AfterOpen
(
eio_req
*
req
)
{
ev_unref
(
EV_DEFAULT_UC
);
Handle
<
Value
>
Database
::
OpenSync
(
const
Arguments
&
args
)
{
HandleScope
scope
;
HandleScope
scope
;
struct
open_request
*
open_req
=
(
struct
open_request
*
)(
req
->
data
);
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
()
);
Local
<
Value
>
argv
[
1
];
if
(
db
->
readyState
==
CLOSED
)
{
bool
err
=
false
;
if
(
!
Open
(
db
))
{
if
(
req
->
result
)
{
EXCEPTION
(
db
->
error_message
.
c_str
(),
db
->
error_status
,
exception
);
err
=
true
;
return
ThrowException
(
exception
);
argv
[
0
]
=
Exception
::
Error
(
String
::
New
(
"Error opening database"
));
}
}
else
{
args
.
This
()
->
Set
(
String
::
NewSymbol
(
"opened"
),
True
(),
ReadOnly
);
db
->
Emit
(
String
::
NewSymbol
(
"opened"
),
0
,
NULL
);
TryCatch
try_catch
;
if
(
db
->
pending
==
0
)
{
db
->
Emit
(
String
::
NewSymbol
(
"idle"
),
0
,
NULL
);
}
}
}
open_req
->
db
->
Unref
();
return
args
.
This
();
open_req
->
cb
->
Call
(
Context
::
GetCurrent
()
->
Global
(),
err
?
1
:
0
,
argv
);
}
if
(
try_catch
.
HasCaught
()
)
{
Handle
<
Value
>
Database
::
Open
(
const
Arguments
&
args
)
{
FatalException
(
try_catch
)
;
HandleScope
scope
;
}
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
open_req
->
db
->
Emit
(
String
::
New
(
"ready"
),
0
,
NULL
);
if
(
db
->
readyState
==
CLOSED
)
{
open_req
->
cb
.
Dispose
();
db
->
readyState
=
OPENING
;
db
->
Ref
();
eio_custom
(
EIO_Open
,
EIO_PRI_DEFAULT
,
EIO_AfterOpen
,
db
);
ev_ref
(
EV_DEFAULT_UC
);
}
free
(
open_req
);
return
args
.
This
();
}
return
0
;
bool
Database
::
Open
(
Database
*
db
)
{
db
->
error_status
=
sqlite3_open_v2
(
db
->
filename
.
c_str
(),
&
db
->
handle
,
SQLITE_OPEN_FULLMUTEX
|
db
->
open_mode
,
NULL
);
if
(
db
->
error_status
!=
SQLITE_OK
)
{
db
->
error_message
=
std
::
string
(
sqlite3_errmsg
(
db
->
handle
));
db
->
readyState
=
CLOSED
;
return
false
;
}
else
{
db
->
readyState
=
OPEN
;
return
true
;
}
}
}
int
Database
::
EIO_Open
(
eio_req
*
req
)
{
int
Database
::
EIO_Open
(
eio_req
*
req
)
{
struct
open_request
*
open_req
=
(
struct
open_request
*
)(
req
->
data
);
Database
*
db
=
static_cast
<
Database
*>
(
req
->
data
);
Open
(
db
);
sqlite3
**
dbptr
=
open_req
->
db
->
GetDBPtr
();
return
0
;
int
rc
=
sqlite3_open_v2
(
open_req
->
filename
}
,
dbptr
,
SQLITE_OPEN_READWRITE
|
SQLITE_OPEN_CREATE
|
SQLITE_OPEN_FULLMUTEX
,
NULL
);
req
->
result
=
rc
;
int
Database
::
EIO_AfterOpen
(
eio_req
*
req
)
{
HandleScope
scope
;
Database
*
db
=
static_cast
<
Database
*>
(
req
->
data
);
ev_unref
(
EV_DEFAULT_UC
);
db
->
Unref
();
// Set the a 10s timeout valuei for retries on BUSY errors.
Local
<
Value
>
argv
[
1
];
sqlite3_busy_timeout
(
*
dbptr
,
10000
);
if
(
db
->
error_status
!=
SQLITE_OK
)
{
EXCEPTION
(
db
->
error_message
.
c_str
(),
db
->
error_status
,
exception
);
argv
[
0
]
=
exception
;
}
else
{
argv
[
0
]
=
Local
<
Value
>::
New
(
Null
());
db
->
handle_
->
Set
(
String
::
NewSymbol
(
"opened"
),
True
(),
ReadOnly
);
}
db
->
Emit
(
String
::
NewSymbol
(
"opened"
),
1
,
argv
);
// sqlite3 *db = *dbptr;
if
(
db
->
pending
==
0
)
{
// sqlite3_commit_hook(db, CommitHook, open_req->db);
db
->
Emit
(
String
::
NewSymbol
(
"idle"
),
0
,
NULL
);
// sqlite3_rollback_hook(db, RollbackHook, open_req->db);
}
// sqlite3_update_hook(db, UpdateHook, open_req->db);
return
0
;
return
0
;
}
}
Handle
<
Value
>
Database
::
Open
(
const
Arguments
&
args
)
{
HandleScope
scope
;
REQ_STR_ARG
(
0
,
filename
);
REQ_FUN_ARG
(
1
,
cb
);
Handle
<
Value
>
Database
::
CloseSync
(
const
Arguments
&
args
)
{
HandleScope
scope
;
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
struct
open_request
*
open_req
=
(
struct
open_request
*
)
if
(
db
->
readyState
==
OPEN
)
{
calloc
(
1
,
sizeof
(
struct
open_request
)
+
filename
.
length
());
if
(
!
Close
(
db
))
{
EXCEPTION
(
db
->
error_message
.
c_str
(),
db
->
error_status
,
exception
);
if
(
!
open_req
)
{
return
ThrowException
(
exception
);
V8
::
LowMemoryNotification
();
}
return
ThrowException
(
Exception
::
Error
(
else
{
String
::
New
(
"Could not allocate enough memory"
)));
args
.
This
()
->
Set
(
String
::
NewSymbol
(
"opened"
),
False
(),
ReadOnly
);
db
->
Emit
(
String
::
NewSymbol
(
"closed"
),
0
,
NULL
);
}
}
}
strcpy
(
open_req
->
filename
,
*
filename
);
return
True
();
open_req
->
cb
=
Persistent
<
Function
>::
New
(
cb
);
}
open_req
->
db
=
db
;
eio_custom
(
EIO_Open
,
EIO_PRI_DEFAULT
,
EIO_AfterOpen
,
open_req
);
Handle
<
Value
>
Database
::
Close
(
const
Arguments
&
args
)
{
HandleScope
scope
;
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
ev_ref
(
EV_DEFAULT_UC
);
if
(
db
->
readyState
==
OPEN
)
{
db
->
readyState
=
CLOSING
;
db
->
Ref
();
db
->
Ref
();
eio_custom
(
EIO_Close
,
EIO_PRI_DEFAULT
,
EIO_AfterClose
,
db
);
ev_ref
(
EV_DEFAULT_UC
);
}
return
Undefined
();
return
args
.
This
();
}
}
int
Database
::
EIO_AfterClose
(
eio_req
*
req
)
{
bool
Database
::
Close
(
Database
*
db
)
{
ev_unref
(
EV_DEFAULT_UC
);
assert
(
db
->
handle
);
HandleScope
scope
;
struct
close_request
*
close_req
=
(
struct
close_request
*
)(
req
->
data
);
db
->
error_status
=
sqlite3_close
(
db
->
handle
);
Local
<
Value
>
argv
[
1
];
if
(
db
->
error_status
!=
SQLITE_OK
)
{
bool
err
=
false
;
db
->
error_message
=
std
::
string
(
sqlite3_errmsg
(
db
->
handle
));
if
(
req
->
result
)
{
db
->
readyState
=
OPEN
;
err
=
true
;
return
false
;
argv
[
0
]
=
Exception
::
Error
(
String
::
New
(
"Error closing database"
));
}
}
else
{
TryCatch
try_catch
;
db
->
readyState
=
CLOSED
;
db
->
handle
=
NULL
;
close_req
->
db
->
Unref
();
return
true
;
close_req
->
cb
->
Call
(
Context
::
GetCurrent
()
->
Global
(),
err
?
1
:
0
,
argv
);
if
(
try_catch
.
HasCaught
())
{
FatalException
(
try_catch
);
}
}
close_req
->
cb
.
Dispose
();
free
(
close_req
);
return
0
;
}
}
int
Database
::
EIO_Close
(
eio_req
*
req
)
{
int
Database
::
EIO_Close
(
eio_req
*
req
)
{
struct
close_request
*
close_req
=
(
struct
close_request
*
)(
req
->
data
);
Database
*
db
=
static_cast
<
Database
*>
(
req
->
data
);
Database
*
db
=
close_req
->
db
;
Close
(
db
);
req
->
result
=
sqlite3_close
(
db
->
db_
);
db
->
db_
=
NULL
;
return
0
;
return
0
;
}
}
Handle
<
Value
>
Database
::
Close
(
const
Arguments
&
args
)
{
int
Database
::
EIO_AfterClose
(
eio_req
*
req
)
{
HandleScope
scope
;
HandleScope
scope
;
Database
*
db
=
static_cast
<
Database
*>
(
req
->
data
);
ev_unref
(
EV_DEFAULT_UC
);
db
->
Unref
();
REQ_FUN_ARG
(
0
,
cb
);
Local
<
Value
>
argv
[
1
];
if
(
db
->
error_status
!=
SQLITE_OK
)
{
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
EXCEPTION
(
db
->
error_message
.
c_str
(),
db
->
error_status
,
exception
);
argv
[
0
]
=
exception
;
struct
close_request
*
close_req
=
(
struct
close_request
*
)
}
calloc
(
1
,
sizeof
(
struct
close_request
));
else
{
argv
[
0
]
=
Local
<
Value
>::
New
(
Null
());
if
(
!
close_req
)
{
db
->
handle_
->
Set
(
String
::
NewSymbol
(
"opened"
),
False
(),
ReadOnly
);
V8
::
LowMemoryNotification
();
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Could not allocate enough memory"
)));
}
}
close_req
->
cb
=
Persistent
<
Function
>::
New
(
cb
);
db
->
Emit
(
String
::
NewSymbol
(
"closed"
),
1
,
argv
);
close_req
->
db
=
db
;
eio_custom
(
EIO_Close
,
EIO_PRI_DEFAULT
,
EIO_AfterClose
,
close_req
);
ev_ref
(
EV_DEFAULT_UC
);
db
->
Ref
();
return
Undefined
()
;
return
0
;
}
}
// // TODO: libeio'fy
// // TODO: libeio'fy
...
@@ -243,7 +263,7 @@ int Database::EIO_AfterPrepareAndStep(eio_req *req) {
...
@@ -243,7 +263,7 @@ int Database::EIO_AfterPrepareAndStep(eio_req *req) {
// if the prepare failed
// if the prepare failed
if
(
req
->
result
!=
SQLITE_OK
)
{
if
(
req
->
result
!=
SQLITE_OK
)
{
argv
[
0
]
=
Exception
::
Error
(
argv
[
0
]
=
Exception
::
Error
(
String
::
New
(
sqlite3_errmsg
(
prep_req
->
db
->
db_
)));
String
::
New
(
sqlite3_errmsg
(
prep_req
->
db
->
handle
)));
argc
=
1
;
argc
=
1
;
}
}
...
@@ -307,7 +327,7 @@ int Database::EIO_PrepareAndStep(eio_req *req) {
...
@@ -307,7 +327,7 @@ int Database::EIO_PrepareAndStep(eio_req *req) {
prep_req
->
stmt
=
NULL
;
prep_req
->
stmt
=
NULL
;
prep_req
->
tail
=
NULL
;
prep_req
->
tail
=
NULL
;
sqlite3
*
db
=
prep_req
->
db
->
db_
;
sqlite3
*
db
=
prep_req
->
db
->
handle
;
int
rc
=
sqlite3_prepare_v2
(
db
,
prep_req
->
sql
,
-
1
,
int
rc
=
sqlite3_prepare_v2
(
db
,
prep_req
->
sql
,
-
1
,
&
(
prep_req
->
stmt
),
&
(
prep_req
->
tail
));
&
(
prep_req
->
stmt
),
&
(
prep_req
->
tail
));
...
@@ -346,9 +366,9 @@ int Database::EIO_PrepareAndStep(eio_req *req) {
...
@@ -346,9 +366,9 @@ int Database::EIO_PrepareAndStep(eio_req *req) {
Handle
<
Value
>
Database
::
PrepareAndStep
(
const
Arguments
&
args
)
{
Handle
<
Value
>
Database
::
PrepareAndStep
(
const
Arguments
&
args
)
{
HandleScope
scope
;
HandleScope
scope
;
REQ_STR_AR
G
(
0
,
sql
);
REQUIRE_ARGUMENT_STRIN
G
(
0
,
sql
);
REQ_FUN_ARG
(
1
,
cb
);
REQUIRE_ARGUMENT_FUNCTION
(
1
,
cb
);
OPT_INT_ARG
(
2
,
mode
,
EXEC_EMPTY
);
OPTIONAL_ARGUMENT_INTEGER
(
2
,
mode
,
EXEC_EMPTY
);
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
Database
*
db
=
ObjectWrap
::
Unwrap
<
Database
>
(
args
.
This
());
...
@@ -385,7 +405,7 @@ int Database::EIO_AfterPrepare(eio_req *req) {
...
@@ -385,7 +405,7 @@ int Database::EIO_AfterPrepare(eio_req *req) {
// if the prepare failed
// if the prepare failed
if
(
req
->
result
!=
SQLITE_OK
)
{
if
(
req
->
result
!=
SQLITE_OK
)
{
argv
[
0
]
=
Exception
::
Error
(
argv
[
0
]
=
Exception
::
Error
(
String
::
New
(
sqlite3_errmsg
(
prep_req
->
db
->
db_
)));
String
::
New
(
sqlite3_errmsg
(
prep_req
->
db
->
handle
)));
argc
=
1
;
argc
=
1
;
}
}
else
{
else
{
...
@@ -423,7 +443,7 @@ int Database::EIO_Prepare(eio_req *req) {
...
@@ -423,7 +443,7 @@ int Database::EIO_Prepare(eio_req *req) {
prep_req
->
stmt
=
NULL
;
prep_req
->
stmt
=
NULL
;
prep_req
->
tail
=
NULL
;
prep_req
->
tail
=
NULL
;
sqlite3
*
db
=
prep_req
->
db
->
db_
;
sqlite3
*
db
=
prep_req
->
db
->
handle
;
int
rc
=
sqlite3_prepare_v2
(
db
,
prep_req
->
sql
,
-
1
,
int
rc
=
sqlite3_prepare_v2
(
db
,
prep_req
->
sql
,
-
1
,
&
(
prep_req
->
stmt
),
&
(
prep_req
->
tail
));
&
(
prep_req
->
stmt
),
&
(
prep_req
->
tail
));
...
@@ -449,7 +469,7 @@ Handle<Value> Database::Prepare(const Arguments& args) {
...
@@ -449,7 +469,7 @@ Handle<Value> Database::Prepare(const Arguments& args) {
Local
<
Function
>
cb
;
Local
<
Function
>
cb
;
int
mode
;
int
mode
;
REQ_STR_AR
G
(
0
,
sql
);
REQUIRE_ARGUMENT_STRIN
G
(
0
,
sql
);
// middle argument could be options or
// middle argument could be options or
switch
(
args
.
Length
())
{
switch
(
args
.
Length
())
{
...
@@ -509,3 +529,33 @@ Handle<Value> Database::Prepare(const Arguments& args) {
...
@@ -509,3 +529,33 @@ Handle<Value> Database::Prepare(const Arguments& args) {
return
Undefined
();
return
Undefined
();
}
}
/**
* Override this so that we can properly close the database when this object
* gets garbage collected.
*/
void
Database
::
Wrap
(
Handle
<
Object
>
handle
)
{
assert
(
handle_
.
IsEmpty
());
assert
(
handle
->
InternalFieldCount
()
>
0
);
handle_
=
Persistent
<
Object
>::
New
(
handle
);
handle_
->
SetPointerInInternalField
(
0
,
this
);
handle_
.
MakeWeak
(
this
,
Destruct
);
}
void
Database
::
Destruct
(
Persistent
<
Value
>
value
,
void
*
data
)
{
Database
*
db
=
static_cast
<
Database
*>
(
data
);
if
(
db
->
handle
)
{
eio_custom
(
EIO_Close
,
EIO_PRI_DEFAULT
,
EIO_AfterDestruct
,
db
);
ev_ref
(
EV_DEFAULT_UC
);
}
else
{
delete
db
;
}
}
int
Database
::
EIO_AfterDestruct
(
eio_req
*
req
)
{
Database
*
db
=
static_cast
<
Database
*>
(
req
->
data
);
ev_unref
(
EV_DEFAULT_UC
);
delete
db
;
return
0
;
}
src/database.h
View file @
db72749d
...
@@ -19,35 +19,51 @@
...
@@ -19,35 +19,51 @@
#include <node.h>
#include <node.h>
#include <node_events.h>
#include <node_events.h>
#include <string>
#include <sqlite3.h>
#include <sqlite3.h>
using
namespace
v8
;
using
namespace
v8
;
using
namespace
node
;
using
namespace
node
;
enum
ReadyState
{
CLOSED
,
OPENING
,
OPEN
,
CLOSING
};
class
Database
:
public
EventEmitter
{
class
Database
:
public
EventEmitter
{
public
:
public
:
static
Persistent
<
FunctionTemplate
>
constructor_template
;
static
Persistent
<
FunctionTemplate
>
constructor_template
;
static
void
Init
(
v8
::
Handle
<
Object
>
target
);
static
void
Init
(
v8
::
Handle
<
Object
>
target
);
protected
:
protected
:
Database
()
:
EventEmitter
(),
db_
(
NULL
)
{
}
Database
()
:
EventEmitter
(),
handle
(
NULL
),
pending
(
0
),
readyState
(
CLOSED
)
{
}
~
Database
()
{
~
Database
()
{
assert
(
db_
==
NULL
);
fprintf
(
stderr
,
"Calling destructor
\n
"
);
printf
(
"Destroying database
\n
"
);
}
}
static
Handle
<
Value
>
New
(
const
Arguments
&
args
);
static
Handle
<
Value
>
New
(
const
Arguments
&
args
);
static
int
EIO_AfterOpen
(
eio_req
*
req
);
static
Handle
<
Value
>
OpenSync
(
const
Arguments
&
args
);
static
int
EIO_Open
(
eio_req
*
req
);
static
Handle
<
Value
>
Open
(
const
Arguments
&
args
);
static
Handle
<
Value
>
Open
(
const
Arguments
&
args
);
static
bool
Open
(
Database
*
db
);
static
int
EIO_Open
(
eio_req
*
req
);
static
int
EIO_AfterOpen
(
eio_req
*
req
);
static
int
EIO_AfterClose
(
eio_req
*
req
);
static
Handle
<
Value
>
CloseSync
(
const
Arguments
&
args
);
static
int
EIO_Close
(
eio_req
*
req
);
static
Handle
<
Value
>
Close
(
const
Arguments
&
args
);
static
Handle
<
Value
>
Close
(
const
Arguments
&
args
);
static
bool
Close
(
Database
*
db
);
static
int
EIO_Close
(
eio_req
*
req
);
static
int
EIO_AfterClose
(
eio_req
*
req
);
// static Handle<Value> LastInsertRowid(const Arguments& args);
static
int
EIO_AfterPrepareAndStep
(
eio_req
*
req
);
static
int
EIO_AfterPrepareAndStep
(
eio_req
*
req
);
static
int
EIO_PrepareAndStep
(
eio_req
*
req
);
static
int
EIO_PrepareAndStep
(
eio_req
*
req
);
static
Handle
<
Value
>
PrepareAndStep
(
const
Arguments
&
args
);
static
Handle
<
Value
>
PrepareAndStep
(
const
Arguments
&
args
);
...
@@ -56,35 +72,29 @@ class Database : public EventEmitter {
...
@@ -56,35 +72,29 @@ class Database : public EventEmitter {
static
int
EIO_Prepare
(
eio_req
*
req
);
static
int
EIO_Prepare
(
eio_req
*
req
);
static
Handle
<
Value
>
Prepare
(
const
Arguments
&
args
);
static
Handle
<
Value
>
Prepare
(
const
Arguments
&
args
);
// Return a pointer to the Sqlite handle pointer so that EIO_Open can
void
Wrap
(
Handle
<
Object
>
handle
);
// pass it to sqlite3_open which wants a pointer to an sqlite3 pointer. This
static
void
Destruct
(
Persistent
<
Value
>
value
,
void
*
data
);
// is because it wants to initialize our original (sqlite3*) pointer to
static
int
EIO_Destruct
(
eio_req
*
req
);
// point to an valid object.
static
int
EIO_AfterDestruct
(
eio_req
*
req
);
sqlite3
**
GetDBPtr
(
void
)
{
return
&
db_
;
}
protected
:
protected
:
sqlite3
*
handle
;
std
::
string
filename
;
int
open_mode
;
std
::
string
error_message
;
int
error_status
;
sqlite3
*
db_
;
int
pending
;
ReadyState
readyState
;
};
};
enum
ExecMode
enum
ExecMode
{
{
EXEC_EMPTY
=
0
,
EXEC_EMPTY
=
0
,
EXEC_LAST_INSERT_ID
=
1
,
EXEC_LAST_INSERT_ID
=
1
,
EXEC_AFFECTED_ROWS
=
2
EXEC_AFFECTED_ROWS
=
2
};
};
struct
open_request
{
Persistent
<
Function
>
cb
;
Database
*
db
;
char
filename
[
1
];
};
struct
close_request
{
Persistent
<
Function
>
cb
;
Database
*
db
;
};
struct
prepare_request
{
struct
prepare_request
{
Persistent
<
Function
>
cb
;
Persistent
<
Function
>
cb
;
Database
*
db
;
Database
*
db
;
...
...
src/macros.h
View file @
db72749d
...
@@ -15,6 +15,9 @@
...
@@ -15,6 +15,9 @@
#ifndef NODE_SQLITE3_SRC_MACROS_H
#ifndef NODE_SQLITE3_SRC_MACROS_H
#define NODE_SQLITE3_SRC_MACROS_H
#define NODE_SQLITE3_SRC_MACROS_H
const
char
*
sqlite_code_string
(
int
code
);
#define CHECK(rc) { if ((rc) != SQLITE_OK) \
#define CHECK(rc) { if ((rc) != SQLITE_OK) \
return ThrowException(Exception::Error(String::New( \
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(*db)))); }
sqlite3_errmsg(*db)))); }
...
@@ -23,37 +26,110 @@
...
@@ -23,37 +26,110 @@
return ThrowException(Exception::Error(String::New( \
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(sqlite3_db_handle(sto->stmt_))))); }
sqlite3_errmsg(sqlite3_db_handle(sto->stmt_))))); }
#define REQ_ARGS(N) \
if (args.Length() < (N)) \
return ThrowException(Exception::TypeError( \
String::New("Expected " #N "arguments")));
#define REQ_STR_ARG(I, VAR) \
#define REQUIRE_ARGUMENTS(n) \
if (args.Length() <= (I) || !args[I]->IsString()) \
if (args.Length() < (n)) { \
return ThrowException( \
Exception::TypeError(String::New("Expected " #n "arguments")) \
); \
}
#define REQUIRE_ARGUMENT_EXTERNAL(i, var) \
if (args.Length() <= (i) || !args[i]->IsExternal()) { \
return ThrowException( \
Exception::TypeError(String::New("Argument " #i " invalid")) \
); \
} \
Local<External> var = Local<External>::Cast(args[i]);
#define REQUIRE_ARGUMENT_FUNCTION(i, var) \
if (args.Length() <= (i) || !args[i]->IsFunction()) { \
return ThrowException(Exception::TypeError( \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a string"))); \
String::New("Argument " #i " must be a function")) \
String::Utf8Value VAR(args[I]->ToString());
); \
} \
Local<Function> var = Local<Function>::Cast(args[i]);
#define REQ
_FUN_ARG(I, VAR)
\
#define REQ
UIRE_ARGUMENT_STRING(i, var)
\
if (args.Length() <= (I) || !args[I]->IsFunction())
\
if (args.Length() <= (i) || !args[i]->IsString()) {
\
return ThrowException(Exception::TypeError( \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a function"))); \
String::New("Argument " #i " must be a string")) \
Local<Function> VAR = Local<Function>::Cast(args[I]);
); \
} \
String::Utf8Value var(args[i]->ToString());
#define REQ_EXT_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsExternal()) \
#define OPTIONAL_ARGUMENT_FUNCTION(i, var) \
Local<Function> var; \
bool var ## _exists = false; \
if (args.Length() >= i) { \
if (!args[i]->IsFunction()) { \
return ThrowException(Exception::TypeError( \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " invalid"))); \
String::New("Argument " #i " must be a function")) \
Local<External> VAR = Local<External>::Cast(args[I]);
); \
} \
#define OPT_INT_ARG(I, VAR, DEFAULT) \
var = Local<Function>::Cast(args[i]); \
int VAR; \
var ## _exists = true; \
if (args.Length() <= (I)) { \
}
VAR = (DEFAULT); \
} else if (args[I]->IsInt32()) { \
VAR = args[I]->Int32Value(); \
#define OPTIONAL_ARGUMENT_INTEGER(i, var, default) \
} else { \
int var; \
if (args.Length() <= (i)) { \
var = (default); \
} \
else if (args[i]->IsInt32()) { \
var = args[i]->Int32Value(); \
} \
else { \
return ThrowException(Exception::TypeError( \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be an integer"))); \
String::New("Argument " #i " must be an integer")) \
); \
}
}
#define DEFINE_CONSTANT_INTEGER(target, constant, name) \
(target)->Set( \
String::NewSymbol(#name), \
Integer::New(constant), \
static_cast<PropertyAttribute>(ReadOnly | DontDelete) \
);
#define DEFINE_CONSTANT_STRING(target, constant, name) \
(target)->Set( \
String::NewSymbol(#name), \
String::NewSymbol(constant), \
static_cast<PropertyAttribute>(ReadOnly | DontDelete) \
);
#define NODE_SET_GETTER(target, name, function) \
(target)->InstanceTemplate() \
->SetAccessor(String::NewSymbol(name), (function));
#define GET_STRING(source, name, property) \
String::Utf8Value name((source)->Get(String::NewSymbol(property)));
#define GET_INTEGER(source, name, property) \
int name = (source)->Get(String::NewSymbol(property))->Int32Value();
#define EXCEPTION(msg, errno, name) \
Local<Value> name = Exception::Error( \
String::Concat( \
String::Concat( \
String::NewSymbol(sqlite_code_string(errno)), \
String::NewSymbol(": ") \
), \
String::New(msg) \
) \
); \
Local<Object> name ## _obj = name->ToObject(); \
name ## _obj->Set(NODE_PSYMBOL("errno"), Integer::New(errno)); \
name ## _obj->Set(NODE_PSYMBOL("code"), \
String::NewSymbol(sqlite_code_string(errno)));
#endif
#endif
src/sqlite3_bindings.cc
View file @
db72749d
...
@@ -16,11 +16,54 @@
...
@@ -16,11 +16,54 @@
#include <node.h>
#include <node.h>
#include <node_events.h>
#include <node_events.h>
#include <sqlite3.h>
#include "macros.h"
#include "database.h"
#include "database.h"
#include "statement.h"
#include "statement.h"
extern
"C"
void
init
(
v8
::
Handle
<
Object
>
target
)
{
extern
"C"
void
init
(
v8
::
Handle
<
Object
>
target
)
{
Database
::
Init
(
target
);
Database
::
Init
(
target
);
Statement
::
Init
(
target
);
Statement
::
Init
(
target
);
DEFINE_CONSTANT_INTEGER
(
target
,
SQLITE_OPEN_READONLY
,
OPEN_READONLY
);
DEFINE_CONSTANT_INTEGER
(
target
,
SQLITE_OPEN_READWRITE
,
OPEN_READWRITE
);
DEFINE_CONSTANT_INTEGER
(
target
,
SQLITE_OPEN_CREATE
,
OPEN_CREATE
);
DEFINE_CONSTANT_STRING
(
target
,
SQLITE_VERSION
,
VERSION
);
DEFINE_CONSTANT_INTEGER
(
target
,
SQLITE_VERSION_NUMBER
,
VERSION_NUMBER
);
}
}
const
char
*
sqlite_code_string
(
int
code
)
{
switch
(
code
)
{
case
SQLITE_OK
:
return
"SQLITE_OK"
;
case
SQLITE_ERROR
:
return
"SQLITE_ERROR"
;
case
SQLITE_INTERNAL
:
return
"SQLITE_INTERNAL"
;
case
SQLITE_PERM
:
return
"SQLITE_PERM"
;
case
SQLITE_ABORT
:
return
"SQLITE_ABORT"
;
case
SQLITE_BUSY
:
return
"SQLITE_BUSY"
;
case
SQLITE_LOCKED
:
return
"SQLITE_LOCKED"
;
case
SQLITE_NOMEM
:
return
"SQLITE_NOMEM"
;
case
SQLITE_READONLY
:
return
"SQLITE_READONLY"
;
case
SQLITE_INTERRUPT
:
return
"SQLITE_INTERRUPT"
;
case
SQLITE_IOERR
:
return
"SQLITE_IOERR"
;
case
SQLITE_CORRUPT
:
return
"SQLITE_CORRUPT"
;
case
SQLITE_NOTFOUND
:
return
"SQLITE_NOTFOUND"
;
case
SQLITE_FULL
:
return
"SQLITE_FULL"
;
case
SQLITE_CANTOPEN
:
return
"SQLITE_CANTOPEN"
;
case
SQLITE_PROTOCOL
:
return
"SQLITE_PROTOCOL"
;
case
SQLITE_EMPTY
:
return
"SQLITE_EMPTY"
;
case
SQLITE_SCHEMA
:
return
"SQLITE_SCHEMA"
;
case
SQLITE_TOOBIG
:
return
"SQLITE_TOOBIG"
;
case
SQLITE_CONSTRAINT
:
return
"SQLITE_CONSTRAINT"
;
case
SQLITE_MISMATCH
:
return
"SQLITE_MISMATCH"
;
case
SQLITE_MISUSE
:
return
"SQLITE_MISUSE"
;
case
SQLITE_NOLFS
:
return
"SQLITE_NOLFS"
;
case
SQLITE_AUTH
:
return
"SQLITE_AUTH"
;
case
SQLITE_FORMAT
:
return
"SQLITE_FORMAT"
;
case
SQLITE_RANGE
:
return
"SQLITE_RANGE"
;
case
SQLITE_NOTADB
:
return
"SQLITE_NOTADB"
;
case
SQLITE_ROW
:
return
"SQLITE_ROW"
;
case
SQLITE_DONE
:
return
"SQLITE_DONE"
;
default
:
return
"UNKNOWN"
;
}
}
src/statement.cc
View file @
db72749d
...
@@ -50,7 +50,7 @@ void Statement::Init(v8::Handle<Object> target) {
...
@@ -50,7 +50,7 @@ void Statement::Init(v8::Handle<Object> target) {
Handle
<
Value
>
Statement
::
New
(
const
Arguments
&
args
)
{
Handle
<
Value
>
Statement
::
New
(
const
Arguments
&
args
)
{
HandleScope
scope
;
HandleScope
scope
;
REQ
_EXT_ARG
(
0
,
stmt
);
REQ
UIRE_ARGUMENT_EXTERNAL
(
0
,
stmt
);
int
first_rc
=
args
[
1
]
->
IntegerValue
();
int
first_rc
=
args
[
1
]
->
IntegerValue
();
int
mode
=
args
[
2
]
->
IntegerValue
();
int
mode
=
args
[
2
]
->
IntegerValue
();
...
@@ -169,8 +169,8 @@ Handle<Value> Statement::BindObject(const Arguments& args) {
...
@@ -169,8 +169,8 @@ Handle<Value> Statement::BindObject(const Arguments& args) {
HandleScope
scope
;
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
_FUN_ARG
(
1
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
1
,
cb
);
if
(
!
args
[
0
]
->
IsObject
())
if
(
!
args
[
0
]
->
IsObject
())
return
ThrowException
(
Exception
::
TypeError
(
return
ThrowException
(
Exception
::
TypeError
(
...
@@ -253,8 +253,8 @@ Handle<Value> Statement::BindArray(const Arguments& args) {
...
@@ -253,8 +253,8 @@ Handle<Value> Statement::BindArray(const Arguments& args) {
HandleScope
scope
;
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
_FUN_ARG
(
1
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
1
,
cb
);
if
(
!
args
[
0
]
->
IsArray
())
if
(
!
args
[
0
]
->
IsArray
())
return
ThrowException
(
Exception
::
TypeError
(
return
ThrowException
(
Exception
::
TypeError
(
String
::
New
(
"First argument must be an Array."
)));
String
::
New
(
"First argument must be an Array."
)));
...
@@ -349,8 +349,8 @@ Handle<Value> Statement::Bind(const Arguments& args) {
...
@@ -349,8 +349,8 @@ Handle<Value> Statement::Bind(const Arguments& args) {
HandleScope
scope
;
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
_FUN_ARG
(
2
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
2
,
cb
);
if
(
!
(
args
[
0
]
->
IsString
()
if
(
!
(
args
[
0
]
->
IsString
()
||
args
[
0
]
->
IsInt32
()
||
args
[
0
]
->
IsInt32
()
...
@@ -475,7 +475,7 @@ Handle<Value> Statement::Finalize(const Arguments& args) {
...
@@ -475,7 +475,7 @@ Handle<Value> Statement::Finalize(const Arguments& args) {
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
}
}
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
sto
->
SetCallback
(
cb
);
sto
->
SetCallback
(
cb
);
...
@@ -740,7 +740,7 @@ Handle<Value> Statement::Step(const Arguments& args) {
...
@@ -740,7 +740,7 @@ Handle<Value> Statement::Step(const Arguments& args) {
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
}
}
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
sto
->
SetCallback
(
cb
);
sto
->
SetCallback
(
cb
);
...
@@ -1011,7 +1011,7 @@ int Statement::EIO_FetchAll(eio_req *req) {
...
@@ -1011,7 +1011,7 @@ int Statement::EIO_FetchAll(eio_req *req) {
Handle
<
Value
>
Statement
::
FetchAll
(
const
Arguments
&
args
)
{
Handle
<
Value
>
Statement
::
FetchAll
(
const
Arguments
&
args
)
{
HandleScope
scope
;
HandleScope
scope
;
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
struct
fetchall_request
*
fetchall_req
=
(
struct
fetchall_request
*
)
struct
fetchall_request
*
fetchall_req
=
(
struct
fetchall_request
*
)
calloc
(
1
,
sizeof
(
struct
fetchall_request
));
calloc
(
1
,
sizeof
(
struct
fetchall_request
));
...
...
test/blob.test.js
View file @
db72749d
...
@@ -14,11 +14,10 @@ exports['Blob overflow test'] = function(beforeExit) {
...
@@ -14,11 +14,10 @@ exports['Blob overflow test'] = function(beforeExit) {
var
inserted
=
0
;
var
inserted
=
0
;
var
retrieved
=
0
;
var
retrieved
=
0
;
db
.
openSync
(
''
);
Step
(
Step
(
function
()
{
function
()
{
db
.
open
(
''
,
this
);
},
function
()
{
var
next
=
this
;
var
next
=
this
;
db
.
prepare
(
'CREATE TABLE elmos (image BLOB);'
,
function
(
err
,
statement
)
{
db
.
prepare
(
'CREATE TABLE elmos (image BLOB);'
,
function
(
err
,
statement
)
{
assert
.
isUndefined
(
err
);
assert
.
isUndefined
(
err
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment