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
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
199 additions
and
66 deletions
+199
-66
sqlite3.js
lib/sqlite3.js
+6
-1
database.cc
src/database.cc
+0
-0
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 @@
var
sqlite3
=
module
.
exports
=
exports
=
require
(
'./sqlite3_bindings'
);
var
sys
=
require
(
"sys"
);
/*
sqlite3.Database.prototype.query = function(sql, bindings, rowCallback) {
var self = this;
...
...
@@ -68,7 +71,7 @@ function _doStep(db, statement, rowCallback) {
// Execute a single SQL query with the given optional parameters. Calls
// `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 bindings, callback;
var n = arguments.length;
...
...
@@ -248,3 +251,4 @@ sqlite3.sanitizeError = function(err, data) {
'" with values ' + JSON.stringify(data, false, 4);
return err;
};
*/
\ No newline at end of file
src/database.cc
View file @
db72749d
This diff is collapsed.
Click to expand it.
src/database.h
View file @
db72749d
...
...
@@ -19,35 +19,51 @@
#include <node.h>
#include <node_events.h>
#include <string>
#include <sqlite3.h>
using
namespace
v8
;
using
namespace
node
;
enum
ReadyState
{
CLOSED
,
OPENING
,
OPEN
,
CLOSING
};
class
Database
:
public
EventEmitter
{
public
:
static
Persistent
<
FunctionTemplate
>
constructor_template
;
static
void
Init
(
v8
::
Handle
<
Object
>
target
);
protected
:
Database
()
:
EventEmitter
(),
db_
(
NULL
)
{
}
Database
()
:
EventEmitter
(),
handle
(
NULL
),
pending
(
0
),
readyState
(
CLOSED
)
{
}
~
Database
()
{
assert
(
db_
==
NULL
);
printf
(
"Destroying database
\n
"
);
fprintf
(
stderr
,
"Calling destructor
\n
"
);
}
static
Handle
<
Value
>
New
(
const
Arguments
&
args
);
static
int
EIO_AfterOpen
(
eio_req
*
req
);
static
int
EIO_Open
(
eio_req
*
req
);
static
Handle
<
Value
>
OpenSync
(
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
int
EIO_Close
(
eio_req
*
req
);
static
Handle
<
Value
>
CloseSync
(
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_PrepareAndStep
(
eio_req
*
req
);
static
Handle
<
Value
>
PrepareAndStep
(
const
Arguments
&
args
);
...
...
@@ -56,35 +72,29 @@ class Database : public EventEmitter {
static
int
EIO_Prepare
(
eio_req
*
req
);
static
Handle
<
Value
>
Prepare
(
const
Arguments
&
args
);
// Return a pointer to the Sqlite handle pointer so that EIO_Open can
// pass it to sqlite3_open which wants a pointer to an sqlite3 pointer. This
// is because it wants to initialize our original (sqlite3*) pointer to
// point to an valid object.
sqlite3
**
GetDBPtr
(
void
)
{
return
&
db_
;
}
void
Wrap
(
Handle
<
Object
>
handle
);
static
void
Destruct
(
Persistent
<
Value
>
value
,
void
*
data
);
static
int
EIO_Destruct
(
eio_req
*
req
);
static
int
EIO_AfterDestruct
(
eio_req
*
req
);
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_LAST_INSERT_ID
=
1
,
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
{
Persistent
<
Function
>
cb
;
Database
*
db
;
...
...
src/macros.h
View file @
db72749d
...
...
@@ -15,6 +15,9 @@
#ifndef 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) \
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(*db)))); }
...
...
@@ -23,37 +26,110 @@
return ThrowException(Exception::Error(String::New( \
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) \
if (args.Length() <= (I) || !args[I]->IsString()) \
#define REQUIRE_ARGUMENTS(n) \
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( \
String::New("Argument " #I " must be a string"))); \
String::Utf8Value VAR(args[I]->ToString());
String::New("Argument " #i " must be a function")) \
); \
} \
Local<Function> var = Local<Function>::Cast(args[i]);
#define REQ
_FUN_ARG(I, VAR)
\
if (args.Length() <= (I) || !args[I]->IsFunction())
\
#define REQ
UIRE_ARGUMENT_STRING(i, var)
\
if (args.Length() <= (i) || !args[i]->IsString()) {
\
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a function"))); \
Local<Function> VAR = Local<Function>::Cast(args[I]);
String::New("Argument " #i " must be a string")) \
); \
} \
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( \
String::New("Argument " #I " invalid"))); \
Local<External> VAR = Local<External>::Cast(args[I]);
#define OPT_INT_ARG(I, VAR, DEFAULT) \
int VAR; \
if (args.Length() <= (I)) { \
VAR = (DEFAULT); \
} else if (args[I]->IsInt32()) { \
VAR = args[I]->Int32Value(); \
} else { \
String::New("Argument " #i " must be a function")) \
); \
} \
var = Local<Function>::Cast(args[i]); \
var ## _exists = true; \
}
#define OPTIONAL_ARGUMENT_INTEGER(i, var, default) \
int var; \
if (args.Length() <= (i)) { \
var = (default); \
} \
else if (args[i]->IsInt32()) { \
var = args[i]->Int32Value(); \
} \
else { \
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
src/sqlite3_bindings.cc
View file @
db72749d
...
...
@@ -16,11 +16,54 @@
#include <node.h>
#include <node_events.h>
#include <sqlite3.h>
#include "macros.h"
#include "database.h"
#include "statement.h"
extern
"C"
void
init
(
v8
::
Handle
<
Object
>
target
)
{
Database
::
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) {
Handle
<
Value
>
Statement
::
New
(
const
Arguments
&
args
)
{
HandleScope
scope
;
REQ
_EXT_ARG
(
0
,
stmt
);
REQ
UIRE_ARGUMENT_EXTERNAL
(
0
,
stmt
);
int
first_rc
=
args
[
1
]
->
IntegerValue
();
int
mode
=
args
[
2
]
->
IntegerValue
();
...
...
@@ -169,8 +169,8 @@ Handle<Value> Statement::BindObject(const Arguments& args) {
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
_FUN_ARG
(
1
,
cb
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
UIRE_ARGUMENT_FUNCTION
(
1
,
cb
);
if
(
!
args
[
0
]
->
IsObject
())
return
ThrowException
(
Exception
::
TypeError
(
...
...
@@ -253,8 +253,8 @@ Handle<Value> Statement::BindArray(const Arguments& args) {
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
_FUN_ARG
(
1
,
cb
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
UIRE_ARGUMENT_FUNCTION
(
1
,
cb
);
if
(
!
args
[
0
]
->
IsArray
())
return
ThrowException
(
Exception
::
TypeError
(
String
::
New
(
"First argument must be an Array."
)));
...
...
@@ -349,8 +349,8 @@ Handle<Value> Statement::Bind(const Arguments& args) {
HandleScope
scope
;
Statement
*
sto
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ
_ARG
S
(
2
);
REQ
_FUN_ARG
(
2
,
cb
);
REQ
UIRE_ARGUMENT
S
(
2
);
REQ
UIRE_ARGUMENT_FUNCTION
(
2
,
cb
);
if
(
!
(
args
[
0
]
->
IsString
()
||
args
[
0
]
->
IsInt32
()
...
...
@@ -475,7 +475,7 @@ Handle<Value> Statement::Finalize(const Arguments& args) {
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
}
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
sto
->
SetCallback
(
cb
);
...
...
@@ -740,7 +740,7 @@ Handle<Value> Statement::Step(const Arguments& args) {
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Already stepping"
)));
}
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
sto
->
SetCallback
(
cb
);
...
...
@@ -1011,7 +1011,7 @@ int Statement::EIO_FetchAll(eio_req *req) {
Handle
<
Value
>
Statement
::
FetchAll
(
const
Arguments
&
args
)
{
HandleScope
scope
;
REQ
_FUN_ARG
(
0
,
cb
);
REQ
UIRE_ARGUMENT_FUNCTION
(
0
,
cb
);
struct
fetchall_request
*
fetchall_req
=
(
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) {
var
inserted
=
0
;
var
retrieved
=
0
;
db
.
openSync
(
''
);
Step
(
function
()
{
db
.
open
(
''
,
this
);
},
function
()
{
var
next
=
this
;
db
.
prepare
(
'CREATE TABLE elmos (image BLOB);'
,
function
(
err
,
statement
)
{
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