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
d9d87db7
Commit
d9d87db7
authored
Feb 22, 2011
by
Konstantin Käfer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
named parameters when inserting
parent
e16b8bc7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
191 additions
and
63 deletions
+191
-63
sqlite3.js
lib/sqlite3.js
+3
-6
statement.cc
src/statement.cc
+101
-50
statement.h
src/statement.h
+28
-7
named_params.test.js
test/named_params.test.js
+59
-0
No files found.
lib/sqlite3.js
View file @
d9d87db7
...
@@ -9,15 +9,12 @@ var Statement = sqlite3.Statement;
...
@@ -9,15 +9,12 @@ var Statement = sqlite3.Statement;
Database
.
prototype
.
prepare
=
function
(
sql
)
{
Database
.
prototype
.
prepare
=
function
(
sql
)
{
var
callback
,
params
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
);
var
callback
,
params
=
Array
.
prototype
.
slice
.
call
(
arguments
,
1
);
if
(
params
.
length
&&
typeof
params
[
params
.
length
-
1
]
!==
'function'
)
{
if
(
!
params
.
length
||
(
params
.
length
===
1
&&
typeof
params
[
0
]
===
'function'
)
)
{
params
.
push
(
undefined
);
return
new
Statement
(
this
,
sql
,
params
[
0
]
);
}
}
else
{
if
(
params
.
length
>
1
)
{
var
statement
=
new
Statement
(
this
,
sql
);
var
statement
=
new
Statement
(
this
,
sql
);
return
statement
.
bind
.
apply
(
statement
,
params
);
return
statement
.
bind
.
apply
(
statement
,
params
);
}
else
{
return
new
Statement
(
this
,
sql
,
params
.
pop
());
}
}
};
};
...
...
src/statement.cc
View file @
d9d87db7
...
@@ -162,6 +162,38 @@ int Statement::EIO_AfterPrepare(eio_req *req) {
...
@@ -162,6 +162,38 @@ int Statement::EIO_AfterPrepare(eio_req *req) {
return
0
;
return
0
;
}
}
inline
Data
::
Field
*
Statement
::
BindParameter
(
const
Handle
<
Value
>
source
)
{
if
(
source
->
IsString
()
||
source
->
IsRegExp
())
{
String
::
Utf8Value
val
(
source
->
ToString
());
return
new
Data
::
Text
(
val
.
length
(),
*
val
);
}
else
if
(
source
->
IsInt32
())
{
return
new
Data
::
Integer
(
source
->
Int32Value
());
}
else
if
(
source
->
IsNumber
())
{
return
new
Data
::
Float
(
source
->
NumberValue
());
}
else
if
(
source
->
IsBoolean
())
{
return
new
Data
::
Integer
(
source
->
BooleanValue
()
?
1
:
0
);
}
else
if
(
source
->
IsNull
())
{
return
new
Data
::
Null
();
}
else
if
(
Buffer
::
HasInstance
(
source
))
{
Local
<
Object
>
buffer
=
source
->
ToObject
();
return
new
Data
::
Blob
(
Buffer
::
Length
(
buffer
),
Buffer
::
Data
(
buffer
));
}
else
if
(
source
->
IsDate
())
{
return
new
Data
::
Float
(
source
->
NumberValue
());
}
else
if
(
source
->
IsUndefined
())
{
return
NULL
;
}
else
{
return
NULL
;
}
}
template
<
class
T
>
T
*
Statement
::
Bind
(
const
Arguments
&
args
,
int
start
)
{
template
<
class
T
>
T
*
Statement
::
Bind
(
const
Arguments
&
args
,
int
start
)
{
int
last
=
args
.
Length
();
int
last
=
args
.
Length
();
Local
<
Function
>
callback
;
Local
<
Function
>
callback
;
...
@@ -172,33 +204,46 @@ template <class T> T* Statement::Bind(const Arguments& args, int start) {
...
@@ -172,33 +204,46 @@ template <class T> T* Statement::Bind(const Arguments& args, int start) {
T
*
baton
=
new
T
(
this
,
callback
);
T
*
baton
=
new
T
(
this
,
callback
);
for
(
int
i
=
start
;
i
<
last
;
i
++
)
{
if
(
start
<
last
)
{
if
(
args
[
i
]
->
IsString
()
||
args
[
i
]
->
IsRegExp
())
{
if
(
args
[
start
]
->
IsArray
())
{
String
::
Utf8Value
val
(
args
[
i
]
->
ToString
());
Local
<
Array
>
array
=
Local
<
Array
>::
Cast
(
args
[
start
]);
baton
->
parameters
.
push_back
(
new
Data
::
Text
(
val
.
length
(),
*
val
));
int
length
=
array
->
Length
();
}
// Note: bind parameters start with 1.
else
if
(
args
[
i
]
->
IsInt32
())
{
for
(
int
i
=
0
,
pos
=
1
;
i
<
length
;
i
++
,
pos
++
)
{
baton
->
parameters
.
push_back
(
new
Data
::
Integer
(
args
[
i
]
->
Int32Value
()));
baton
->
parameters
.
push_back
(
}
new
Data
::
Parameter
(
pos
,
BindParameter
(
array
->
Get
(
i
))));
else
if
(
args
[
i
]
->
IsNumber
()
||
args
[
i
]
->
IsDate
())
{
}
baton
->
parameters
.
push_back
(
new
Data
::
Float
(
args
[
i
]
->
NumberValue
()));
}
else
if
(
args
[
i
]
->
IsBoolean
())
{
baton
->
parameters
.
push_back
(
new
Data
::
Integer
(
args
[
i
]
->
BooleanValue
()
?
1
:
0
));
}
else
if
(
args
[
i
]
->
IsNull
())
{
baton
->
parameters
.
push_back
(
new
Data
::
Null
());
}
}
else
if
(
Buffer
::
HasInstance
(
args
[
i
]))
{
else
if
(
!
args
[
start
]
->
IsObject
()
||
args
[
start
]
->
IsRegExp
()
||
args
[
start
]
->
IsDate
())
{
Local
<
Object
>
buffer
=
args
[
i
]
->
ToObject
();
// Parameters directly in array.
baton
->
parameters
.
push_back
(
new
Data
::
Blob
(
Buffer
::
Length
(
buffer
),
Buffer
::
Data
(
buffer
)));
// Note: bind parameters start with 1.
for
(
int
i
=
start
,
pos
=
1
;
i
<
last
;
i
++
,
pos
++
)
{
baton
->
parameters
.
push_back
(
new
Data
::
Parameter
(
pos
,
BindParameter
(
args
[
i
])));
}
}
}
else
if
(
args
[
i
]
->
IsUndefined
())
{
else
if
(
args
[
start
]
->
IsObject
())
{
// Skip parameter position.
Local
<
Object
>
object
=
Local
<
Object
>::
Cast
(
args
[
start
]);
baton
->
parameters
.
push_back
(
NULL
);
Local
<
Array
>
array
=
object
->
GetPropertyNames
();
int
length
=
array
->
Length
();
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
Local
<
Value
>
name
=
array
->
Get
(
i
);
if
(
name
->
IsInt32
())
{
baton
->
parameters
.
push_back
(
new
Data
::
Parameter
(
name
->
Int32Value
(),
BindParameter
(
object
->
Get
(
name
))
));
}
else
{
baton
->
parameters
.
push_back
(
new
Data
::
Parameter
(
*
String
::
Utf8Value
(
Local
<
String
>::
Cast
(
name
)),
BindParameter
(
object
->
Get
(
name
))
));
}
}
}
}
else
{
else
{
delete
baton
;
return
NULL
;
return
NULL
;
}
}
}
}
...
@@ -217,35 +262,41 @@ bool Statement::Bind(const Data::Parameters parameters) {
...
@@ -217,35 +262,41 @@ bool Statement::Bind(const Data::Parameters parameters) {
Data
::
Parameters
::
const_iterator
it
=
parameters
.
begin
();
Data
::
Parameters
::
const_iterator
it
=
parameters
.
begin
();
Data
::
Parameters
::
const_iterator
end
=
parameters
.
end
();
Data
::
Parameters
::
const_iterator
end
=
parameters
.
end
();
// Note: bind parameters start with 1.
for
(;
it
<
end
;
it
++
)
{
for
(
int
i
=
1
;
it
<
end
;
it
++
,
i
++
)
{
Data
::
Parameter
*
param
=
*
it
;
Data
::
Field
*
field
=
*
it
;
if
(
field
==
NULL
)
{
int
pos
;
continue
;
if
(
param
->
position
>
0
)
{
pos
=
param
->
position
;
}
else
{
pos
=
sqlite3_bind_parameter_index
(
handle
,
param
->
name
.
c_str
());
}
}
switch
(
field
->
type
)
{
if
(
param
->
field
!=
NULL
)
{
case
SQLITE_INTEGER
:
{
switch
(
param
->
field
->
type
)
{
status
=
sqlite3_bind_int
(
handle
,
i
,
case
SQLITE_INTEGER
:
{
((
Data
::
Integer
*
)
field
)
->
value
);
status
=
sqlite3_bind_int
(
handle
,
pos
,
}
break
;
((
Data
::
Integer
*
)
param
->
field
)
->
value
);
case
SQLITE_FLOAT
:
{
}
break
;
status
=
sqlite3_bind_double
(
handle
,
i
,
case
SQLITE_FLOAT
:
{
((
Data
::
Float
*
)
field
)
->
value
);
status
=
sqlite3_bind_double
(
handle
,
pos
,
}
break
;
((
Data
::
Float
*
)
param
->
field
)
->
value
);
case
SQLITE_TEXT
:
{
}
break
;
status
=
sqlite3_bind_text
(
handle
,
i
,
case
SQLITE_TEXT
:
{
((
Data
::
Text
*
)
field
)
->
value
.
c_str
(),
status
=
sqlite3_bind_text
(
handle
,
pos
,
((
Data
::
Text
*
)
field
)
->
value
.
size
(),
SQLITE_TRANSIENT
);
((
Data
::
Text
*
)
param
->
field
)
->
value
.
c_str
(),
}
break
;
((
Data
::
Text
*
)
param
->
field
)
->
value
.
size
(),
SQLITE_TRANSIENT
);
case
SQLITE_BLOB
:
{
}
break
;
status
=
sqlite3_bind_blob
(
handle
,
i
,
case
SQLITE_BLOB
:
{
((
Data
::
Blob
*
)
field
)
->
value
,
status
=
sqlite3_bind_blob
(
handle
,
pos
,
((
Data
::
Blob
*
)
field
)
->
length
,
SQLITE_TRANSIENT
);
((
Data
::
Blob
*
)
param
->
field
)
->
value
,
}
break
;
((
Data
::
Blob
*
)
param
->
field
)
->
length
,
SQLITE_TRANSIENT
);
case
SQLITE_NULL
:
{
}
break
;
status
=
sqlite3_bind_null
(
handle
,
i
);
case
SQLITE_NULL
:
{
}
break
;
status
=
sqlite3_bind_null
(
handle
,
pos
);
}
break
;
}
}
}
if
(
status
!=
SQLITE_OK
)
{
if
(
status
!=
SQLITE_OK
)
{
...
...
src/statement.h
View file @
d9d87db7
...
@@ -21,31 +21,31 @@ namespace node_sqlite3 {
...
@@ -21,31 +21,31 @@ namespace node_sqlite3 {
namespace
Data
{
namespace
Data
{
struct
Field
{
struct
Field
{
Field
(
unsigned
short
_type
=
SQLITE_NULL
)
:
type
(
_type
)
{}
inline
Field
(
unsigned
short
_type
=
SQLITE_NULL
)
:
type
(
_type
)
{}
unsigned
short
type
;
unsigned
short
type
;
};
};
struct
Integer
:
Field
{
struct
Integer
:
Field
{
Integer
(
int
val
)
:
Field
(
SQLITE_INTEGER
),
value
(
val
)
{}
inline
Integer
(
int
val
)
:
Field
(
SQLITE_INTEGER
),
value
(
val
)
{}
int
value
;
int
value
;
};
};
struct
Float
:
Field
{
struct
Float
:
Field
{
Float
(
double
val
)
:
Field
(
SQLITE_FLOAT
),
value
(
val
)
{}
inline
Float
(
double
val
)
:
Field
(
SQLITE_FLOAT
),
value
(
val
)
{}
double
value
;
double
value
;
};
};
struct
Text
:
Field
{
struct
Text
:
Field
{
Text
(
size_t
len
,
const
char
*
val
)
:
Field
(
SQLITE_TEXT
),
value
(
val
,
len
)
{}
inline
Text
(
size_t
len
,
const
char
*
val
)
:
Field
(
SQLITE_TEXT
),
value
(
val
,
len
)
{}
std
::
string
value
;
std
::
string
value
;
};
};
struct
Blob
:
Field
{
struct
Blob
:
Field
{
Blob
(
size_t
len
,
const
void
*
val
)
:
Field
(
SQLITE_BLOB
),
length
(
len
)
{
inline
Blob
(
size_t
len
,
const
void
*
val
)
:
Field
(
SQLITE_BLOB
),
length
(
len
)
{
value
=
(
char
*
)
malloc
(
len
);
value
=
(
char
*
)
malloc
(
len
);
memcpy
(
value
,
val
,
len
);
memcpy
(
value
,
val
,
len
);
}
}
~
Blob
()
{
inline
~
Blob
()
{
free
(
value
);
free
(
value
);
}
}
int
length
;
int
length
;
...
@@ -54,8 +54,24 @@ namespace Data {
...
@@ -54,8 +54,24 @@ namespace Data {
typedef
Field
Null
;
typedef
Field
Null
;
typedef
std
::
vector
<
Field
*>
Row
;
typedef
std
::
vector
<
Field
*>
Row
;
typedef
Row
Parameters
;
typedef
std
::
vector
<
Row
*>
Rows
;
typedef
std
::
vector
<
Row
*>
Rows
;
struct
Parameter
{
unsigned
short
position
;
std
::
string
name
;
Field
*
field
;
inline
Parameter
(
unsigned
short
pos_
,
Field
*
field_
)
:
position
(
pos_
),
field
(
field_
)
{}
inline
Parameter
(
const
char
*
name_
,
Field
*
field_
)
:
position
(
0
),
name
(
name_
),
field
(
field_
)
{}
inline
~
Parameter
()
{
if
(
field
)
{
delete
field
;
}
}
};
typedef
std
::
vector
<
Parameter
*>
Parameters
;
}
}
...
@@ -74,6 +90,10 @@ public:
...
@@ -74,6 +90,10 @@ public:
Data
::
Parameters
parameters
;
Data
::
Parameters
parameters
;
Baton
(
Statement
*
stmt_
,
Handle
<
Function
>
cb_
)
:
stmt
(
stmt_
)
{
Baton
(
Statement
*
stmt_
,
Handle
<
Function
>
cb_
)
:
stmt
(
stmt_
)
{
Data
::
Parameters
::
const_iterator
it
=
parameters
.
begin
();
Data
::
Parameters
::
const_iterator
end
=
parameters
.
end
();
for
(;
it
<
end
;
it
++
)
delete
*
it
;
stmt
->
Ref
();
stmt
->
Ref
();
ev_ref
(
EV_DEFAULT_UC
);
ev_ref
(
EV_DEFAULT_UC
);
callback
=
Persistent
<
Function
>::
New
(
cb_
);
callback
=
Persistent
<
Function
>::
New
(
cb_
);
...
@@ -177,6 +197,7 @@ protected:
...
@@ -177,6 +197,7 @@ protected:
static
void
Finalize
(
Baton
*
baton
);
static
void
Finalize
(
Baton
*
baton
);
void
Finalize
();
void
Finalize
();
Data
::
Field
*
BindParameter
(
const
Handle
<
Value
>
source
);
template
<
class
T
>
T
*
Bind
(
const
Arguments
&
args
,
int
start
=
0
);
template
<
class
T
>
T
*
Bind
(
const
Arguments
&
args
,
int
start
=
0
);
bool
Bind
(
const
Data
::
Parameters
parameters
);
bool
Bind
(
const
Data
::
Parameters
parameters
);
...
...
test/named_params.test.js
0 → 100644
View file @
d9d87db7
var
sqlite3
=
require
(
'sqlite3'
);
var
assert
=
require
(
'assert'
);
exports
[
'test named parameters'
]
=
function
(
beforeExit
)
{
var
db
=
new
sqlite3
.
Database
(
':memory:'
);
var
finished
=
false
;
db
.
serialize
(
function
()
{
db
.
run
(
"CREATE TABLE foo (txt TEXT, num INT)"
);
db
.
run
(
"INSERT INTO foo VALUES($text, $id)"
,
{
$id
:
1
,
$text
:
"Lorem Ipsum"
});
db
.
run
(
"INSERT INTO foo VALUES(:text, :id)"
,
{
":id"
:
2
,
":text"
:
"Dolor Sit Amet"
});
db
.
run
(
"INSERT INTO foo VALUES(@txt, @id)"
,
{
"@id"
:
3
,
"@txt"
:
"Consectetur Adipiscing Elit"
});
db
.
run
(
"INSERT INTO foo VALUES(@txt, @id)"
,
[
'Sed Do Eiusmod'
,
4
]);
db
.
run
(
"INSERT INTO foo VALUES(?2, ?4)"
,
[
null
,
'Tempor Incididunt'
,
null
,
5
]);
db
.
run
(
"INSERT INTO foo VALUES(?, ?)"
,
{
2
:
6
,
1
:
"Ut Labore Et Dolore"
});
db
.
all
(
"SELECT txt, num FROM foo ORDER BY num"
,
function
(
err
,
rows
)
{
if
(
err
)
throw
err
;
assert
.
equal
(
rows
[
0
][
0
],
"Lorem Ipsum"
);
assert
.
equal
(
rows
[
0
][
1
],
1
);
assert
.
equal
(
rows
[
1
][
0
],
"Dolor Sit Amet"
);
assert
.
equal
(
rows
[
1
][
1
],
2
);
assert
.
equal
(
rows
[
2
][
0
],
"Consectetur Adipiscing Elit"
);
assert
.
equal
(
rows
[
2
][
1
],
3
);
assert
.
equal
(
rows
[
3
][
0
],
"Sed Do Eiusmod"
);
assert
.
equal
(
rows
[
3
][
1
],
4
);
assert
.
equal
(
rows
[
4
][
0
],
"Tempor Incididunt"
);
assert
.
equal
(
rows
[
4
][
1
],
5
);
assert
.
equal
(
rows
[
5
][
0
],
"Ut Labore Et Dolore"
);
assert
.
equal
(
rows
[
5
][
1
],
6
);
finished
=
true
;
});
});
beforeExit
(
function
()
{
assert
.
ok
(
finished
);
});
};
\ No newline at end of file
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