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
63893a9e
Commit
63893a9e
authored
Mar 02, 2010
by
Orlando Vazquez
Committed by
Orlando Vazquez
Mar 02, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial stab at using libeio for when doing synchronous io
parent
8a2e0682
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
185 additions
and
53 deletions
+185
-53
sqlite3_bindings.cc
sqlite3_bindings.cc
+155
-53
test2.js
test2.js
+30
-0
No files found.
sqlite3_bindings.cc
View file @
63893a9e
...
...
@@ -13,40 +13,49 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sqlite3.h>
#include <string.h>
#include <v8.h>
#include <node.h>
#include <node_events.h>
#include <sqlite3.h>
using
namespace
v8
;
using
namespace
node
;
#define CHECK(rc) { if ((rc) != SQLITE_OK) \
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(*db)))); }
#define SCHECK(rc) { if ((rc) != SQLITE_OK) \
#define SCHECK(rc) { if ((rc) != SQLITE_OK)
\
return ThrowException(Exception::Error(String::New( \
sqlite3_errmsg(sqlite3_db_handle(*stmt))))); }
#define REQ_ARGS(N) \
if (args.Length() < (N)) \
return ThrowException(Exception::TypeError( \
String::New("Expected " #N "arguments")));
String::New("Expected " #N "arguments")));
#define REQ_STR_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsString()) \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a string"))); \
String::New("Argument " #I " must be a string")));
\
String::Utf8Value VAR(args[I]->ToString());
#define REQ_FUN_ARG(I, VAR) \
if (args.Length() <= (I) || !args[I]->IsFunction()) \
return ThrowException(Exception::TypeError( \
String::New("Argument " #I " must be a function"))); \
Local<Function> cb = Local<Function>::Cast(args[I]);
#define REQ_EXT_ARG(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 OPT_INT_ARG(I, VAR, DEFAULT) \
int VAR; \
if (args.Length() <= (I)) { \
...
...
@@ -55,36 +64,35 @@ using namespace node;
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")));
\
}
class
Sqlite3Db
:
public
EventEmitter
{
public
:
static
void
Init
(
v8
::
Handle
<
Object
>
target
)
static
void
Init
(
v8
::
Handle
<
Object
>
target
)
{
HandleScope
scope
;
Local
<
FunctionTemplate
>
t
=
FunctionTemplate
::
New
(
New
);
t
->
Inherit
(
EventEmitter
::
constructor_template
);
t
->
InstanceTemplate
()
->
SetInternalFieldCount
(
1
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"open"
,
Open
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"printIt"
,
PrintIt
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"changes"
,
Changes
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"close"
,
Close
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"lastInsertRowid"
,
LastInsertRowid
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"prepare"
,
Prepare
);
target
->
Set
(
v8
::
String
::
NewSymbol
(
"Database
Sync
"
),
t
->
GetFunction
());
target
->
Set
(
v8
::
String
::
NewSymbol
(
"Database"
),
t
->
GetFunction
());
Statement
::
Init
(
target
);
}
protected
:
Sqlite3Db
(
sqlite3
*
db
)
:
db_
(
db
)
{
}
Sqlite3Db
()
:
db_
(
NULL
)
{
}
~
Sqlite3Db
()
{
sqlite3_close
(
db_
);
...
...
@@ -94,24 +102,120 @@ protected:
operator
sqlite3
*
()
const
{
return
db_
;
}
// 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_
;
}
protected
:
static
Handle
<
Value
>
New
(
const
Arguments
&
args
)
{
HandleScope
scope
;
REQ_STR_ARG
(
0
,
filename
);
sqlite3
*
db
;
int
rc
=
sqlite3_open
(
*
filename
,
&
db
);
if
(
rc
)
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Error opening database"
)));
Sqlite3Db
*
dbo
=
new
Sqlite3Db
(
db
);
Sqlite3Db
*
dbo
=
new
Sqlite3Db
();
dbo
->
Wrap
(
args
.
This
());
return
args
.
This
();
}
sqlite3_commit_hook
(
db
,
CommitHook
,
dbo
);
sqlite3_rollback_hook
(
db
,
RollbackHook
,
dbo
);
sqlite3_update_hook
(
db
,
UpdateHook
,
dbo
);
// To pass arguments to the functions that will run in the thread-pool we
// have to pack them into a struct and pass eio_custom a pointer to it.
return
args
.
This
();
struct
open_request
{
Persistent
<
Function
>
cb
;
Sqlite3Db
*
dbo
;
sqlite3
**
dbptr
;
char
filename
[
1
];
};
static
int
EIO_AfterOpen
(
eio_req
*
req
)
{
ev_unref
(
EV_DEFAULT_UC
);
HandleScope
scope
;
struct
open_request
*
open_req
=
(
struct
open_request
*
)(
req
->
data
);
printf
(
"EIO_AfterOpen; rc = %d
\n
"
,
(
int
)
req
->
result
);
printf
(
"result was %d
\n
"
,
(
int
)
req
->
result
);
Local
<
Value
>
argv
[
1
];
bool
err
=
false
;
if
(
req
->
result
)
{
err
=
true
;
argv
[
0
]
=
Exception
::
Error
(
String
::
New
(
"Error opening database"
));
}
TryCatch
try_catch
;
open_req
->
cb
->
Call
(
Context
::
GetCurrent
()
->
Global
(),
err
&&
1
,
argv
);
if
(
try_catch
.
HasCaught
())
{
FatalException
(
try_catch
);
}
open_req
->
cb
.
Dispose
();
free
(
open_req
);
return
0
;
}
static
int
EIO_Open
(
eio_req
*
req
)
{
struct
open_request
*
open_req
=
(
struct
open_request
*
)(
req
->
data
);
printf
(
"The filename was %s
\n
"
,
open_req
->
filename
);
printf
(
"before assn %p
\n
"
,
*
(
open_req
->
dbptr
));
int
rc
=
sqlite3_open
(
open_req
->
filename
,
open_req
->
dbptr
);
printf
(
"after addr %p
\n
"
,
*
(
open_req
->
dbptr
));
sqlite3
*
db
=
*
(
open_req
->
dbptr
);
sqlite3_commit_hook
(
db
,
CommitHook
,
open_req
->
dbo
);
sqlite3_rollback_hook
(
db
,
RollbackHook
,
open_req
->
dbo
);
sqlite3_update_hook
(
db
,
UpdateHook
,
open_req
->
dbo
);
req
->
result
=
rc
;
return
0
;
}
static
Handle
<
Value
>
PrintIt
(
const
Arguments
&
args
)
{
HandleScope
scope
;
Sqlite3Db
*
dbo
=
ObjectWrap
::
Unwrap
<
Sqlite3Db
>
(
args
.
This
());
sqlite3
*
db
=
*
dbo
;
printf
(
"print it %p
\n
"
,
db
);
return
Undefined
();
}
static
Handle
<
Value
>
Open
(
const
Arguments
&
args
)
{
HandleScope
scope
;
REQ_STR_ARG
(
0
,
filename
);
REQ_FUN_ARG
(
1
,
cb
);
Sqlite3Db
*
dbo
=
ObjectWrap
::
Unwrap
<
Sqlite3Db
>
(
args
.
This
());
printf
(
"way before addr %p
\n
"
,
((
sqlite3
*
)
*
dbo
));
struct
open_request
*
open_req
=
(
struct
open_request
*
)
calloc
(
1
,
sizeof
(
struct
open_request
));
if
(
!
open_req
)
{
V8
::
LowMemoryNotification
();
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
"Could not allocate enough memory"
)));
}
open_req
->
dbptr
=
dbo
->
GetDBPtr
();
strcpy
(
open_req
->
filename
,
*
filename
);
open_req
->
cb
=
Persistent
<
Function
>::
New
(
cb
);
open_req
->
dbo
=
dbo
;
eio_custom
(
EIO_Open
,
EIO_PRI_DEFAULT
,
EIO_AfterOpen
,
open_req
);
ev_ref
(
EV_DEFAULT_UC
);
dbo
->
Ref
();
return
Undefined
();
}
//
// JS DatabaseSync bindings
...
...
@@ -142,7 +246,7 @@ protected:
static
int
CommitHook
(
void
*
v_this
)
{
HandleScope
scope
;
Sqlite3Db
*
db
=
static_cast
<
Sqlite3Db
*>
(
v_this
);
db
->
Emit
(
String
::
New
(
"commit"
),
0
,
NULL
);
db
->
Emit
(
String
::
New
(
"commit"
),
0
,
NULL
);
// TODO: allow change in return value to convert to rollback...somehow
return
0
;
}
...
...
@@ -150,10 +254,10 @@ protected:
static
void
RollbackHook
(
void
*
v_this
)
{
HandleScope
scope
;
Sqlite3Db
*
db
=
static_cast
<
Sqlite3Db
*>
(
v_this
);
db
->
Emit
(
String
::
New
(
"rollback"
),
0
,
NULL
);
db
->
Emit
(
String
::
New
(
"rollback"
),
0
,
NULL
);
}
static
void
UpdateHook
(
void
*
v_this
,
int
operation
,
const
char
*
database
,
static
void
UpdateHook
(
void
*
v_this
,
int
operation
,
const
char
*
database
,
const
char
*
table
,
sqlite_int64
rowid
)
{
HandleScope
scope
;
Sqlite3Db
*
db
=
static_cast
<
Sqlite3Db
*>
(
v_this
);
...
...
@@ -185,7 +289,7 @@ protected:
sqlite3_stmt
*
stmt
=
NULL
;
const
char
*
tail
=
NULL
;
CHECK
(
sqlite3_prepare_v2
(
*
db
,
*
sql
,
-
1
,
&
stmt
,
&
tail
));
if
(
!
stmt
)
if
(
!
stmt
)
return
Null
();
Local
<
Value
>
arg
=
External
::
New
(
stmt
);
Persistent
<
Object
>
statement
(
Statement
::
constructor_template
->
...
...
@@ -195,27 +299,27 @@ protected:
return
scope
.
Close
(
statement
);
}
class
Statement
:
public
EventEmitter
{
class
Statement
:
public
EventEmitter
{
public
:
static
Persistent
<
FunctionTemplate
>
constructor_template
;
static
void
Init
(
v8
::
Handle
<
Object
>
target
)
{
HandleScope
scope
;
Local
<
FunctionTemplate
>
t
=
FunctionTemplate
::
New
(
New
);
constructor_template
=
Persistent
<
FunctionTemplate
>::
New
(
t
);
t
->
Inherit
(
EventEmitter
::
constructor_template
);
t
->
InstanceTemplate
()
->
SetInternalFieldCount
(
1
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"bind"
,
Bind
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"clearBindings"
,
ClearBindings
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"finalize"
,
Finalize
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"bindParameterCount"
,
BindParameterCount
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"reset"
,
Reset
);
NODE_SET_PROTOTYPE_METHOD
(
t
,
"step"
,
Step
);
//target->Set(v8::String::NewSymbol("SQLStatement"), t->GetFunction());
}
...
...
@@ -229,9 +333,9 @@ protected:
protected
:
Statement
(
sqlite3_stmt
*
stmt
)
:
stmt_
(
stmt
)
{}
~
Statement
()
{
if
(
stmt_
)
sqlite3_finalize
(
stmt_
);
}
sqlite3_stmt
*
stmt_
;
operator
sqlite3_stmt
*
()
const
{
return
stmt_
;
}
...
...
@@ -239,14 +343,14 @@ protected:
//
// JS prepared statement bindings
//
static
Handle
<
Value
>
Bind
(
const
Arguments
&
args
)
{
HandleScope
scope
;
Statement
*
stmt
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
REQ_ARGS
(
2
);
if
(
!
args
[
0
]
->
IsString
()
&&
!
args
[
0
]
->
IsInt32
())
return
ThrowException
(
Exception
::
TypeError
(
return
ThrowException
(
Exception
::
TypeError
(
String
::
New
(
"First argument must be a string or integer"
)));
int
index
=
args
[
0
]
->
IsString
()
?
sqlite3_bind_parameter_index
(
*
stmt
,
*
String
::
Utf8Value
(
args
[
0
]))
:
...
...
@@ -262,12 +366,12 @@ protected:
}
else
if
(
args
[
1
]
->
IsNull
()
||
args
[
1
]
->
IsUndefined
())
{
sqlite3_bind_null
(
*
stmt
,
index
);
}
else
{
return
ThrowException
(
Exception
::
TypeError
(
return
ThrowException
(
Exception
::
TypeError
(
String
::
New
(
"Unable to bind value of this type"
)));
}
return
args
.
This
();
}
static
Handle
<
Value
>
BindParameterCount
(
const
Arguments
&
args
)
{
HandleScope
scope
;
Statement
*
stmt
=
ObjectWrap
::
Unwrap
<
Statement
>
(
args
.
This
());
...
...
@@ -310,10 +414,10 @@ protected:
case
SQLITE_INTEGER
:
value
=
Integer
::
New
(
sqlite3_column_int
(
*
stmt
,
c
));
break
;
case
SQLITE_FLOAT
:
case
SQLITE_FLOAT
:
value
=
Number
::
New
(
sqlite3_column_double
(
*
stmt
,
c
));
break
;
case
SQLITE_TEXT
:
case
SQLITE_TEXT
:
value
=
String
::
New
((
const
char
*
)
sqlite3_column_text
(
*
stmt
,
c
));
break
;
case
SQLITE_NULL
:
...
...
@@ -321,15 +425,15 @@ protected:
value
=
Undefined
();
break
;
}
row
->
Set
(
String
::
NewSymbol
(
sqlite3_column_name
(
*
stmt
,
c
)),
row
->
Set
(
String
::
NewSymbol
(
sqlite3_column_name
(
*
stmt
,
c
)),
value
);
}
return
row
;
}
else
if
(
rc
==
SQLITE_DONE
)
{
return
Null
();
}
else
{
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
sqlite3_errmsg
(
sqlite3_db_handle
(
*
stmt
)))));
return
ThrowException
(
Exception
::
Error
(
String
::
New
(
sqlite3_errmsg
(
sqlite3_db_handle
(
*
stmt
)))));
}
}
...
...
@@ -344,18 +448,16 @@ protected:
return thus;
}
*/
};
};
Persistent
<
FunctionTemplate
>
Sqlite3Db
::
Statement
::
constructor_template
;
extern
"C"
void
init
(
v8
::
Handle
<
Object
>
target
)
{
extern
"C"
void
init
(
v8
::
Handle
<
Object
>
target
)
{
Sqlite3Db
::
Init
(
target
);
}
test2.js
0 → 100644
View file @
63893a9e
var
fs
=
require
(
"fs"
);
process
.
mixin
(
GLOBAL
,
require
(
"assert"
));
process
.
mixin
(
GLOBAL
,
require
(
"sys"
));
var
sqlite
=
require
(
"./sqlite3_bindings"
);
var
db
=
new
sqlite
.
Database
();
throws
(
function
()
{
db
.
open
();
});
throws
(
function
()
{
db
.
open
(
"my.db"
);
});
throws
(
function
()
{
db
.
open
(
"/tmp"
);
});
db
.
open
(
"my.db"
,
function
(
err
)
{
puts
(
inspect
(
arguments
));
if
(
err
)
{
puts
(
"There was an error"
);
throw
err
;
}
puts
(
"open callback"
);
db
.
printIt
();
});
puts
(
"done"
);
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