[v8-juice] r2236 committed - pulled in latest cpdo, accommodated API changes. Made JSPDO.Statement....

2 views
Skip to first unread message

v8-j...@googlecode.com

unread,
Apr 12, 2012, 9:23:28 AM4/12/12
to v8-juice-...@googlegroups.com
Revision: 2236
Author: sgbeal
Date: Thu Apr 12 06:23:08 2012
Log: pulled in latest cpdo, accommodated API changes. Made
JSPDO.Statement.bind() return (this).
http://code.google.com/p/v8-juice/source/detail?r=2236

Modified:
/convert/addons/jspdo/Makefile
/convert/addons/jspdo/cpdo_amalgamation.cpp
/convert/addons/jspdo/cpdo_amalgamation.hpp
/convert/addons/jspdo/jspdo-init.js
/convert/addons/jspdo/jspdo.cpp

=======================================
--- /convert/addons/jspdo/Makefile Mon Feb 20 07:40:22 2012
+++ /convert/addons/jspdo/Makefile Thu Apr 12 06:23:08 2012
@@ -75,6 +75,8 @@
# The rest of the code "shouldn't" need to be hacked for most Unix
# systems.

+cpdo_amalgamation.o jspdo.o: CPPFLAGS+=-DCPDO_CPP_ENABLE_SAFETY_NET=1
+
########################################################################
# Build shared library and link it against the underlying db libs
# (so client binaries won't have to)...
=======================================
--- /convert/addons/jspdo/cpdo_amalgamation.cpp Sat Feb 18 03:59:26 2012
+++ /convert/addons/jspdo/cpdo_amalgamation.cpp Thu Apr 12 06:23:08 2012
@@ -107,8 +107,6 @@
{
#define X cpdo_driver_reg_empty_m
X,X,X,X,X,
-X,X,X,X,X,
-X,X,X,X,X,
X,X,X,X,X
#undef X
};
@@ -1170,6 +1168,60 @@
if(!drv || !str) return cpdo_rc.ArgError;
else return drv->api->free_string(drv, str);
}
+
+int cpdo_step_each( cpdo_stmt * stmt, cpdo_step_each_f f, void * state )
+{
+ if(!stmt || !f) return cpdo_rc.ArgError;
+ else {
+ int rc = 0;
+ cpdo_step_code scode;
+ while( CPDO_STEP_OK==(scode=stmt->api->step(stmt))){
+ rc = f( stmt, state );
+ if(rc) break;
+ }
+ if(!rc && (CPDO_STEP_DONE!=scode) ){
+ rc = cpdo_rc.CheckDbError;
+ }
+ return rc;
+ }
+}
+
+int cpdo_exec_each( cpdo_driver * db, cpdo_step_each_f f, void * state,
char const * sql, unsigned int sqlLength )
+{
+ int rc = 0;
+ cpdo_stmt * st = NULL;
+ if(!db || !f || !sql || !sqlLength) return cpdo_rc.ArgError;
+ rc = cpdo_prepare( db, &st, sql, sqlLength );
+ if(rc) return rc;
+ rc = cpdo_step_each( st, f, state );
+ st->api->finalize(st);
+ return rc;
+}
+
+int cpdo_exec_each_f_v( cpdo_driver * db, cpdo_step_each_f f, void *
state, char const * fmt, va_list vargs )
+{
+ int rc = 0;
+ char * sql = NULL;
+ if(!db || !f || !fmt) return cpdo_rc.ArgError;
+ sql = cpdo_mprintf_v( fmt, vargs );
+ if( ! sql ) return cpdo_rc.AllocError;
+ rc = cpdo_exec_each( db, f, state, sql, strlen(sql) );
+ free(sql);
+ return rc;
+
+}
+
+int cpdo_exec_each_f( cpdo_driver * db, cpdo_step_each_f f, void * state,
char const * fmt, ... )
+{
+ int rc;
+ va_list vargs;
+ va_start( vargs, fmt );
+ rc = cpdo_exec_each_f_v( db, f, state, fmt, vargs );
+ va_end( vargs );
+ return rc;
+}
+
+

#undef MARKER
#if defined(__cplusplus)
@@ -1248,7 +1300,6 @@
static char cpdo_skel_driver_in_trans( cpdo_driver * self );
static int cpdo_skel_driver_opt_set( cpdo_driver * self, char const * key,
va_list vargs );
static int cpdo_skel_driver_opt_get( cpdo_driver * self, char const * key,
va_list vargs );
-static int cpdo_skel_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch );
const cpdo_driver_api cpdo_skel_driver_api =
{
cpdo_skel_driver_details,
@@ -1269,8 +1320,7 @@
},
{/*opt*/
cpdo_skel_driver_opt_set,
- cpdo_skel_driver_opt_get,
- cpdo_skel_driver_opt_get_string_quote_char
+ cpdo_skel_driver_opt_get
},
{/*constants*/
CPDO_DRIVER_NAME /*driver_name*/
@@ -1762,16 +1812,6 @@
{
return cpdo_rc.NYIError;
}
-
-static int cpdo_skel_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch )
-{
- if( NULL == ch ) return cpdo_rc.ArgError;
- else
- {
- *ch = '\'';
- return 0;
- }
-}

static cpdo_step_code cpdo_skel_stmt_step( cpdo_stmt * self )
{
@@ -3388,11 +3428,11 @@


*/
+#include <assert.h>
#include <sqlite3.h>
#include <stdlib.h> /* malloc()/free() */
#include <string.h> /* strlen() */

-
#if defined(__cplusplus)
extern "C" {
#endif
@@ -3419,7 +3459,6 @@

static int cpdo_sq3_driver_opt_set( cpdo_driver * self, char const * key,
va_list vargs );
static int cpdo_sq3_driver_opt_get( cpdo_driver * self, char const * key,
va_list vargs );
-static int cpdo_sq3_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch );

const cpdo_driver_api cpdo_sq3_driver_api =
{
@@ -3441,8 +3480,7 @@
},
{/*opt*/
cpdo_sq3_driver_opt_set,
- cpdo_sq3_driver_opt_get,
- cpdo_sq3_driver_opt_get_string_quote_char
+ cpdo_sq3_driver_opt_get
},
{/*constants*/
CPDO_DRIVER_NAME /*driver_name*/
@@ -3656,6 +3694,29 @@
{
DRV_DECL(cpdo_rc.ArgError);
if( ! v ) return cpdo_rc.ArgError;
+#if 0 /* enabling this adds LOTS of mallocs()! */
+ else if(hint && *hint) { /* check sqlite_sequence table... */
+ char const * sql = "SELECT seq FROM sqlite_sequence WHERE name=?";
+ sqlite3_stmt * st3 = NULL;
+ int rc = sqlite3_prepare( drv->db, sql, (int)strlen(sql), &st3,
NULL );
+ if(rc){
+ return cpdo_rc.CheckDbError;
+ }
+ rc = sqlite3_bind_text( st3, 1, hint, (int)strlen(hint),
SQLITE_STATIC );
+ if(rc) goto end;
+ rc = sqlite3_step( st3 );
+ if( SQLITE_ROW != rc ) {
+ *v = sqlite3_last_insert_rowid(drv->db);
+ rc = 0;
+ goto end;
+ }
+ rc = 0;
+ *v = (uint64_t) sqlite3_column_int64( st3, 0 );
+ end:
+ sqlite3_finalize(st3);
+ return rc ? cpdo_rc.CheckDbError : 0;;
+ }
+#endif
else
{
*v = sqlite3_last_insert_rowid(drv->db);
@@ -3665,8 +3726,7 @@
static int cpdo_sq3_close( cpdo_driver * self )
{
DRV_DECL(cpdo_rc.ArgError);
- cpdo_sq3_driver_free(drv);
- return 0;
+ return cpdo_sq3_driver_free(drv);
}

static char cpdo_sq3_is_connected( cpdo_driver * self )
@@ -3726,14 +3786,23 @@
static int cpdo_sq3_sql_qualify( cpdo_driver * self, char const * str,
uint32_t * len, char ** dest )
{
if(!str || !dest || !*str) return cpdo_rc.ArgError;
+ else if( (NULL != strstr(str, ";"))
+ || (NULL != strstr(str, "'"))
+ || (NULL != strstr(str, "["))
+ )
+ {
+ return cpdo_rc.RangeError;
+ }
else
{
- char * rc = cpdo_mprintf("[%s]", str);
+ int sz = 0;
+ char * rc = cpdo_mprintf("[%s]%n", str, &sz);
if(!rc) return cpdo_rc.AllocError;
else
{
+ assert( sz > 0 );
*dest = rc;
- if(len) *len = strlen(rc);
+ if(len) *len = (uint32_t) sz; /*strlen(rc);*/
return 0;
}
}
@@ -3771,6 +3840,15 @@
*tgt = &stmt->self;
return 0;
}
+
+static int cpdo_sq3_mode_to_flags( char const * m ){
+
+ if(!m || !*m) return 0;
+ else if(0 == strcmp("rwc",m)) return SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE;
+ else if(0 == strcmp("rw",m)) return SQLITE_OPEN_READWRITE;
+ else if(0 == strcmp("ro",m)) return SQLITE_OPEN_READONLY;
+ else return -1;
+}

int cpdo_sq3_connect( cpdo_driver * self, cpdo_connect_opt const * opt )
{
@@ -3781,20 +3859,84 @@
{
enum { BufSize = 256U };
char buf[BufSize];
- char const * params = NULL;
+ char const * tokBegin = NULL;
+ char const * tokEnd = NULL;
+ char kbuf[BufSize] = {0,0};
+ char nameBuf[BufSize] = {0,0};
+ char * pos;
+ char const * key = NULL;
#if (SQLITE_VERSION_NUMBER >= 3005001)
int flags; flags = 0; /* not yet used */
#endif
- rc = cpdo_split_dsn( opt->dsn, buf, BufSize, &params );
+ rc = cpdo_split_dsn( opt->dsn, buf, BufSize, &tokBegin );
if( rc ) return rc;
+ assert( NULL != tokBegin );
+ pos = nameBuf;
+ while( *tokBegin && (';'!=*tokBegin) ){ /* skip filename part */
+ if((pos-nameBuf) >= (BufSize-1)){
+ return cpdo_rc.RangeError;
+ }
+ *(pos++) = *(tokBegin++);
+ }
+ *pos = 0; /* NUL-terminate file name */
+ if(';'==*tokBegin) ++tokBegin;
+ while( cpdo_next_token( &tokBegin, ';', &tokEnd ) ){
+ if(tokBegin==tokEnd) break;
+ else {
+ char const * value = NULL;
+ char * at = kbuf;
+ if( (tokEnd - tokBegin) >= (BufSize-1) ) return
cpdo_rc.RangeError;
+ memset( kbuf, 0, BufSize );
+ key = tokBegin;
+ /* Write the key part to the buffer... */
+ for( ; (key<tokEnd) && *key && ('='!=*key); ++key ) {
+ *(at++) = *key;
+ }
+ *(at++) = 0;
+ value = at;
+ if( '=' == *key ) {
+ ++key;
+ }
+ /* Write the value part to the buffer... */
+ for( ; (key<tokEnd) && *key; ++key ) {
+ *(at++) = *key;
+ }
+ key = kbuf;
+ /* Done parsing. Now see if we understand how to use
+ this option... */
+ if( 0 == strcmp("openmode",key) )
+ {
+#if (SQLITE_VERSION_NUMBER >= 3005001)
+ flags = cpdo_sq3_mode_to_flags( value );
+ if(flags<0){
+ /* FIXME: add error string to db class */
+ return cpdo_rc.RangeError;
+ }
+#else
+ /* TODO: emit a warning here. */
+#endif
+ }
+ else
+ {
+ /* ignore unknown keys: this is optional in the CPDO
+ interface. If we add warning support, i'll add the
+ warning here. Or if i'm feeling pedantic later i'll
+ throw the error here.
+ */
+ }
+ /* set up for the next token... */
+ tokBegin = tokEnd;
+ tokEnd = NULL;
+ }
+ }
/*
FIXME: strip any parameters after the first ';' separator
(just replace the first ';' with a NUL).
*/
#if (SQLITE_VERSION_NUMBER >= 3005001)
rc = flags
- ? sqlite3_open_v2( params, &drv->db, flags, NULL )
- : sqlite3_open( params, &drv->db );
+ ? sqlite3_open_v2( nameBuf, &drv->db, flags, NULL )
+ : sqlite3_open( nameBuf, &drv->db );
#else
rc = sqlite3_open( params, &drv->db );
#endif
@@ -3852,17 +3994,6 @@
{
return cpdo_rc.NYIError;
}
-
-static int cpdo_sq3_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch )
-{
- if( NULL == ch ) return cpdo_rc.ArgError;
- else
- {
- *ch = '\'';
- return 0;
- }
-}
-

static cpdo_step_code cpdo_sq3_stmt_step( cpdo_stmt * self )
{
@@ -4212,10 +4343,11 @@

- dbname=STRING

- - fieldbuffersize=INTEGER. When fetching string/blob data, if the
- db cannot tell us the maximum length for the field then this value
- is used as a fallback. The driver ignores "very small" values, but
- how small "very small" is is not specified.
+ - DEPRECATED (not needed): fieldbuffersize=INTEGER. When fetching
+ string/blob data, if the db cannot tell us the maximum length for
+ the field then this value is used as a fallback. The driver ignores
+ "very small" values, but how small "very small" is is not
+ specified.


TODO:
@@ -4317,6 +4449,7 @@

#define MARKER if(1)
printf("MARKER: %s:%d:%s():\t",__FILE__,__LINE__,__func__); if(1) printf

+#if !defined(CPDO_MY5_HAS_PRINT64)
/** CPDO_MY5_HAS_PRINT64 is used to determine whether or not to install
our own int64-to-string logic. C89 does not specify the equivalent
of C99's PRIi64 format specifier.
@@ -4325,6 +4458,7 @@
otherwise we use cpdo_printf() to do the conversion.
*/
#define CPDO_MY5_HAS_PRINT64 (CPDO_ENABLE_64_BIT || (__STDC_VERSION__ >=
199901L) || (HAVE_LONG_LONG == 1))
+#endif

#if !CPDO_MY5_HAS_PRINT64
#endif
@@ -4355,7 +4489,6 @@

static int cpdo_my5_driver_opt_set( cpdo_driver * self, char const * key,
va_list vargs );
static int cpdo_my5_driver_opt_get( cpdo_driver * self, char const * key,
va_list vargs );
-static int cpdo_my5_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch );

const cpdo_driver_api cpdo_my5_driver_api =
{
@@ -4377,8 +4510,7 @@
},
{/*opt*/
cpdo_my5_driver_opt_set,
- cpdo_my5_driver_opt_get,
- cpdo_my5_driver_opt_get_string_quote_char
+ cpdo_my5_driver_opt_get
},
{/*constants*/
CPDO_DRIVER_NAME /*driver_name*/
@@ -4548,7 +4680,7 @@
/** The number of columns in the result set.
*/
uint16_t count;
- /** MySQL's interface into the result data columsn.
+ /** MySQL's interface into the result data colums.
This is an array count items long.
*/
MYSQL_BIND * myBinders;
@@ -4557,8 +4689,11 @@
*/
cpdo_bind_val * cBinders;
/**
- Buffers for holding T-to-String conversions.
- This is an array count items long.
+ Buffers for holding T-to-String conversions. This is an
+ array count items long. We use this in the get_string() op
+ to cache the result of the string conversions so that the
+ lifetime of the returned bytes can be extended to a usable
+ duration.
*/
cpdo_bind_val * convBuf;
} rbind;
@@ -4856,6 +4991,10 @@
*/
#define RESET_DRV_ERR(DRIVER) cpdo_my5_drv_err2( (DRIVER), 0, NULL )

+#define TRY_SHARED_NULL 0
+#if TRY_SHARED_NULL
+static char my5_null_string[] = {'N','U','L','L',0};
+#endif
static int cpdo_my5_sql_quote( cpdo_driver * self, char const * str,
uint32_t * len, char ** dest )
{
DRV_DECL(cpdo_rc.ArgError);
@@ -4863,12 +5002,18 @@
if( ! len || !dest ) return cpdo_rc.ArgError;
else if( NULL == str )
{
+#if TRY_SHARED_NULL
+ *dest = my5_null_string;
+ *len = 4;
+ return 0;
+#else
char * tmp = (char *)malloc(5);
if( ! tmp ) return cpdo_rc.AllocError;
strcpy( tmp, "NULL" );
*dest = tmp;
*len = 4;
return 0;
+#endif
}
else
{
@@ -4883,17 +5028,27 @@
return 0;
}
}
+
static int cpdo_my5_sql_qualify( cpdo_driver * self, char const * str,
uint32_t * len, char ** dest )
{
if(!str || !dest || !*str) return cpdo_rc.ArgError;
+ else if( (NULL != strstr(str, ";"))
+ || (NULL != strstr(str, "'"))
+ || (NULL != strstr(str, "`"))
+ )
+ {
+ return cpdo_rc.RangeError;
+ }
else
{
- char * rc = cpdo_mprintf("`%s`", str);
+ int sz = 0;
+ char * rc = cpdo_mprintf("`%s`%n", str, &sz);
if(!rc) return cpdo_rc.AllocError;
else
{
+ assert( sz > 0 );
*dest = rc;
- if(len) *len = strlen(rc);
+ if(len) *len = (uint32_t)sz; /*strlen(rc);*/
return 0;
}
}
@@ -4901,7 +5056,13 @@

static int cpdo_my5_free_string( cpdo_driver * self, char * str)
{
- return str ? (free(str),0) : cpdo_rc.ArgError;
+#if TRY_SHARED_NULL
+ if(my5_null_string == str) return 0;
+ else
+#endif
+ {
+ return str ? (free(str),0) : cpdo_rc.ArgError;
+ }
}


@@ -4935,9 +5096,7 @@
stmt->rbind.cBinders = cpdo_bind_val_list_new(stmt->rbind.count);
if( ! stmt->rbind.cBinders ) return cpdo_rc.AllocError;

- stmt->rbind.convBuf = cpdo_bind_val_list_new(stmt->rbind.count);
- if( ! stmt->rbind.convBuf ) return cpdo_rc.AllocError;
-
+ /* stmt->rbind.convBuf initialization is delayed until
get_string(). */
}
if( stmt->colMeta && !stmt->rbind.count ) return cpdo_rc.InternalError;
return 0;
@@ -4990,32 +5149,26 @@
case MYSQL_TYPE_TINY:
cpdo_bind_val_int8( bv, 0 );
bin->buffer = (char *)&bv->valu.i8;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_SHORT:
cpdo_bind_val_int16( bv, 0 );
bin->buffer = (char *)&bv->valu.i16;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_LONG:
cpdo_bind_val_int32( bv, 0 );
bin->buffer = (char *)&bv->valu.i32;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_LONGLONG:
cpdo_bind_val_int64( bv, 0 );
bin->buffer = (char *)&bv->valu.i64;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_FLOAT:
cpdo_bind_val_float( bv, 0.0 );
bin->buffer = (char *)&bv->valu.flt;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_DOUBLE:
cpdo_bind_val_double( bv, 0.0 );
bin->buffer = (char *)&bv->valu.dbl;
- bin->buffer_type = fld->type;
break;
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING: {
@@ -5026,7 +5179,6 @@
rc = cpdo_bind_val_string( bv, NULL, allocLen );
if( rc ) return rc;
bin->buffer = (char *)bv->valu.blob.mem;
- bin->buffer_type = fld->type;
bin->buffer_length = bv->valu.blob.length;
bin->length = &bv->valu.blob.length;
break;
@@ -5039,7 +5191,6 @@
rc = cpdo_bind_val_blob( bv, NULL, allocLen );
if( rc ) return rc;
bin->buffer = (char *)bv->valu.blob.mem;
- bin->buffer_type = fld->type;
bin->buffer_length = bv->valu.blob.length;
bin->length = &bv->valu.blob.length;
break;
@@ -5059,7 +5210,6 @@
return rc;
}
bin->buffer = (char *)mt;
- bin->buffer_type = fld->type;
bin->buffer_length = sizeof(MYSQL_TIME);
bin->length = &bv->valu.custom.length;
break;
@@ -5068,6 +5218,7 @@
MARKER("WARNING: UNHANDLED MYSQL_TYPE_XXX #%d IN
PARAMETER DATA\n",fld->type);
return cpdo_rc.TypeError;
};
+ bin->buffer_type = fld->type;
}
return 0;
}
@@ -5337,17 +5488,6 @@
{
return cpdo_rc.NYIError;
}
-
-static int cpdo_my5_driver_opt_get_string_quote_char( cpdo_driver * self,
char * ch )
-{
- /* TODO: support configurable single- or double-quote char. */
- if( NULL == ch ) return cpdo_rc.ArgError;
- else
- {
- *ch = '\'';
- return 0;
- }
-}

static int cpdo_my5_driver_commit( cpdo_driver * self )
{
@@ -5401,9 +5541,11 @@
{
uint16_t i;
assert( st );
- for( i = 0; i < st->rbind.count; ++i )
- {
- cpdo_bind_val_clean( &st->rbind.convBuf[i] );
+ if(st->rbind.convBuf) {
+ for( i = 0; i < st->rbind.count; ++i )
+ {
+ cpdo_bind_val_clean( &st->rbind.convBuf[i] );
+ }
}
}

@@ -5801,6 +5943,7 @@
if( (0 == rc) && val ) *val = (float)d;
return rc;
}
+
#if !CPDO_MY5_HAS_PRINT64
typedef struct {
char * str;
@@ -5828,7 +5971,7 @@
else if( ndx >= stmt->rbind.count ) return cpdo_rc.RangeError;
else
{
- enum { NumBufSize = 64 };
+ enum { NumBufSize = 80 };
int rc;
cpdo_bind_val * scratch = NULL;
cpdo_bind_val * bv = &stmt->rbind.cBinders[ndx];
@@ -5838,156 +5981,168 @@
if( len ) *len = 0;
return 0;
}
- else if( bv->type == CPDO_TYPE_CUSTOM )
- {
- enum { BufSize = 20 /* for time/date-to-string (timestamp
sz=19)*/ };
- MYSQL_BIND * bin = &stmt->rbind.myBinders[ndx];
- if(! cpdo_bind_val_tag_type_check_origin(&cpdo_my5_driver_api,
- bv->valu.custom.type_tag ))
- {
- return cpdo_rc.TypeError;
- }
- switch( bin->buffer_type )
- {
- case MYSQL_TYPE_DATE:
- case MYSQL_TYPE_TIME:
- case MYSQL_TYPE_DATETIME:
- case MYSQL_TYPE_TIMESTAMP: {
- MYSQL_TIME * tm;
- scratch = &stmt->rbind.convBuf[ndx];
- if( CPDO_TYPE_STRING == scratch->type )
- {/* already done the conversion, so re-use it.. */
- *val = (char const *)scratch->valu.blob.mem;
- if(len) *len = scratch->valu.blob.length;
- return 0;
- }
- rc = cpdo_bind_val_string( scratch, NULL, BufSize );
- if( rc ) return rc;
- tm = (MYSQL_TIME*)bv->valu.custom.mem;
- assert( tm );
- if( ! tm ) return cpdo_rc.InternalError;
- if( MYSQL_TYPE_DATE == bin->buffer_type )
- {
- sprintf( (char *)scratch->valu.blob.mem,
- "%04d-%02d-%02d",
- tm->year, tm->month, tm->day);
- }
- else if( MYSQL_TYPE_TIME == bin->buffer_type )
- {
- sprintf( (char *)scratch->valu.blob.mem,
- "%02d:%02d:%02d",
- tm->hour, tm->minute, tm->second);
- }
- else
- {
- assert( (MYSQL_TYPE_TIMESTAMP == bin->buffer_type)
- || (MYSQL_TYPE_DATETIME == bin->buffer_type)
- );
- sprintf( (char *)scratch->valu.blob.mem,
- "%04d-%02d-%02d %02d:%02d:%02d",
- tm->year, tm->month, tm->day,
- tm->hour, tm->minute, tm->second);
- }
- scratch->valu.blob.length = strlen( (char
*)scratch->valu.blob.mem );
- *val = (char const *)scratch->valu.blob.mem;
- if(len) *len = scratch->valu.blob.length;
- return 0;
- }
- default:
- break;
- }
- return cpdo_rc.TypeError;
- }
- else if( CPDO_TYPE_STRING == bv->type )
- { /* shortcut - no need to convert this */
+ else if( CPDO_TYPE_STRING == bv->type ) {
+ /* shortcut - no need to convert this */
*val = (char const *)bv->valu.blob.mem;
- if( len )
- {
- *len = bv->valu.blob.length;
- }
+ if( len ) *len = bv->valu.blob.length;
return 0;
}
-#if 0
- else if( CPDO_TYPE_BLOB == bv->type )
- { /* Arguable: optimistically assume blob is a legal string */
- *val = (char const *)bv->valu.blob.mem;
- if( len )
- {
- *len = bv->valu.blob.length;
- }
- return 0;
- }
-#endif
- else
- { /* convert numbers to strings... */
- cpdo_bind_val * scratch = &stmt->rbind.convBuf[ndx];
- int sprc;
- char buf[NumBufSize];
+ else if(!stmt->rbind.convBuf)
+ {
+ stmt->rbind.convBuf =
cpdo_bind_val_list_new(stmt->rbind.count);
+ if( ! stmt->rbind.convBuf ) return cpdo_rc.AllocError;
+ }
+ else {
+ /* check for a cached value */
+ scratch = &stmt->rbind.convBuf[ndx];
if( CPDO_TYPE_STRING == scratch->type )
{/* already done the conversion, so re-use it.. */
*val = (char const *)scratch->valu.blob.mem;
if(len) *len = scratch->valu.blob.length;
return 0;
}
- switch( bv->type )
- {
- case CPDO_TYPE_INT8:
- sprc = sprintf( buf, "%"PRIi8, bv->valu.i8 );
- break;
- case CPDO_TYPE_INT16:
- sprc = sprintf( buf, "%"PRIi16, bv->valu.i16 );
- break;
- case CPDO_TYPE_INT32:
- sprc = sprintf( buf, "%"PRIi32, bv->valu.i32 );
- break;
- case CPDO_TYPE_INT64:
-#if CPDO_MY5_HAS_PRINT64
-
- sprc = sprintf( buf, "%"PRIi64, bv->valu.i64 );
+ }
+
+ switch( bv->type ){
+ case CPDO_TYPE_STRING: { /* shortcut - no need to convert this */
+ *val = (char const *)bv->valu.blob.mem;
+ if( len ) *len = bv->valu.blob.length;
+ return 0;
+ }
+#if 0
+ case CPDO_TYPE_BLOB: { /* Arguable: optimistically assume blob
is a legal string */
+ *val = (char const *)bv->valu.blob.mem;
+ if( len ) *len = bv->valu.blob.length;
+ return 0;
+ }
+#endif
+ case CPDO_TYPE_INT8:
+ case CPDO_TYPE_INT16:
+ case CPDO_TYPE_INT32:
+ case CPDO_TYPE_INT64:
+ case CPDO_TYPE_DOUBLE:
+ case CPDO_TYPE_FLOAT: { /* convert numbers to strings... */
+ cpdo_bind_val * scratch = &stmt->rbind.convBuf[ndx];
+ int sprc;
+ char buf[NumBufSize];
+ assert( (CPDO_TYPE_STRING != scratch->type) && "This should
have been caught by an earlier block.");
+ switch( bv->type )
+ {
+ case CPDO_TYPE_INT8:
+ sprc = sprintf( buf, "%"PRIi8, bv->valu.i8 );
+ break;
+ case CPDO_TYPE_INT16:
+ sprc = sprintf( buf, "%"PRIi16, bv->valu.i16 );
+ break;
+ case CPDO_TYPE_INT32:
+ sprc = sprintf( buf, "%"PRIi32, bv->valu.i32 );
+ break;
+ case CPDO_TYPE_INT64:
+#if CPDO_MY5_HAS_PRINT64
+
+ sprc = sprintf( buf, "%"PRIi64, bv->valu.i64 );
#else
- /*
- We use cpdo_printf() to implement this on 32-bit platforms
- because the PRIi64 specifier can map to a value which is not
- specified in C89.
- */
- {
- enum { I64BufLen = 80 };
- char buf[I64BufLen];
- My5StringAppender myStr;
- myStr.str = buf;
- myStr.maxLen = I64BufLen;
- myStr.pos = 0;
- sprc = cpdo_printf( cpdo_my5_appender_string,
&myStr, "%"PRIi64, bv->valu.i64 );
- }
+ /*
+ We use cpdo_printf() to implement this on 32-bit
platforms
+ because the PRIi64 specifier can map to a value
which is not
+ specified in C89.
+ */
+ {
+ enum { I64BufLen = 80 };
+ char buf[I64BufLen];
+ My5StringAppender myStr;
+ myStr.str = buf;
+ myStr.maxLen = I64BufLen;
+ myStr.pos = 0;
+ sprc = cpdo_printf( cpdo_my5_appender_string,
&myStr, "%"PRIi64, bv->valu.i64 );
+ }
#endif
- break;
- case CPDO_TYPE_DOUBLE:
- sprc = sprintf( buf, "%f", bv->valu.dbl );
+ break;
+ case CPDO_TYPE_DOUBLE:
+ sprc = sprintf( buf, "%f", bv->valu.dbl );
break;
- case CPDO_TYPE_FLOAT:
- sprc = sprintf( buf, "%f", bv->valu.flt );
+ case CPDO_TYPE_FLOAT:
+ sprc = sprintf( buf, "%f", bv->valu.flt );
break;
- default:
- MARKER("WARNING: UNHANDLED MYSQL_TYPE_XXX #%d IN RESULT
DATA\n",
- stmt->rbind.myBinders[ndx].buffer_type);
+ default:
+ assert(0 && "Unhandled statement column data type in
switch().");
+ return cpdo_rc.TypeError;
+ };
+ if(sprc>0)
+ { /* Strip trailing zeroes before passing it on... */
+ unsigned int urc = (unsigned int)sprc;
+ char * pos = buf + urc - 1;
+ for( ; ('0' == *pos) && urc && (*(pos-1) != '.')&&
(*(pos-1) != ',');
+ --pos, --urc )
+ {
+ *pos = 0;
+ }
+ assert(urc && *pos);
+ }
+ rc = cpdo_bind_val_string( scratch, buf, strlen(buf) );
+ if( rc ) return rc;
+ *val = (char const *)scratch->valu.blob.mem;
+ if( len ) *len = scratch->valu.blob.length;
+ return 0;
+ }
+ case CPDO_TYPE_CUSTOM:{ /* convert date/time fields to
strings... */
+ enum { BufSize = 20 /* for time/date-to-string (timestamp
sz=19)*/ };
+ MYSQL_BIND * bin = &stmt->rbind.myBinders[ndx];
+ if(!
cpdo_bind_val_tag_type_check_origin(&cpdo_my5_driver_api,
+
bv->valu.custom.type_tag ))
+ {
return cpdo_rc.TypeError;
- };
- if(sprc>0)
- { /* Strip trailing zeroes before passing it on... */
- unsigned int urc = (unsigned int)sprc;
- char * pos = buf + urc - 1;
- for( ; ('0' == *pos) && urc && (*(pos-1) != '.')&&
(*(pos-1) != ',');
- --pos, --urc )
- {
- *pos = 0;
- }
- assert(urc && *pos);
- }
- rc = cpdo_bind_val_string( scratch, buf, strlen(buf) );
- if( rc ) return rc;
- *val = (char const *)scratch->valu.blob.mem;
- if( len ) *len = scratch->valu.blob.length;
- return 0;
+ }
+ switch( bin->buffer_type )
+ {
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_TIMESTAMP: {
+ MYSQL_TIME * tm;
+ scratch = &stmt->rbind.convBuf[ndx];
+ assert( (CPDO_TYPE_STRING != scratch->type) && "This
should have been caught by an earlier block.");
+ rc = cpdo_bind_val_string( scratch, NULL, BufSize );
+ if( rc ) return rc;
+ tm = (MYSQL_TIME*)bv->valu.custom.mem;
+ assert( tm );
+ if( ! tm ) return cpdo_rc.InternalError;
+ if( MYSQL_TYPE_DATE == bin->buffer_type )
+ {
+ sprintf( (char *)scratch->valu.blob.mem,
+ "%04d-%02d-%02d",
+ tm->year, tm->month, tm->day);
+ }
+ else if( MYSQL_TYPE_TIME == bin->buffer_type )
+ {
+ sprintf( (char *)scratch->valu.blob.mem,
+ "%02d:%02d:%02d",
+ tm->hour, tm->minute, tm->second);
+ }
+ else
+ {
+ assert( (MYSQL_TYPE_TIMESTAMP == bin->buffer_type)
+ || (MYSQL_TYPE_DATETIME ==
bin->buffer_type)
+ );
+ sprintf( (char *)scratch->valu.blob.mem,
+ "%04d-%02d-%02d %02d:%02d:%02d",
+ tm->year, tm->month, tm->day,
+ tm->hour, tm->minute, tm->second);
+ }
+ scratch->valu.blob.length = strlen( (char
*)scratch->valu.blob.mem );
+ *val = (char const *)scratch->valu.blob.mem;
+ if(len) *len = scratch->valu.blob.length;
+ return 0;
+ }
+ default:
+ break;
+ }
+ return cpdo_rc.TypeError;
+ }
+ default:
+ MARKER("WARNING: UNHANDLED MYSQL_TYPE_XXX #%d IN RESULT
DATA\n",
+ stmt->rbind.myBinders[ndx].buffer_type);
+ return cpdo_rc.TypeError;
}
}
}
@@ -6010,9 +6165,13 @@
switch( bv->type )
{
case CPDO_TYPE_BLOB:
- *val = (char const *)bv->valu.blob.mem;
+ *val = (void const *)bv->valu.blob.mem;
if(len) *len = bv->valu.blob.length;
break;
+ case CPDO_TYPE_CUSTOM:
+ *val = (void const *)bv->valu.custom.mem;
+ if(len) *len = bv->valu.custom.length;
+ break;
case CPDO_TYPE_NULL:
*val = 0;
if(len) *len = 0;
@@ -6088,6 +6247,8 @@
#include <cassert>
#include <cstring>
#include <sstream>
+#include <iterator>
+//#include <iostream> /* only for debuggering */

/** @def CPDO_CPP_ENABLE_SAFETY_NET

@@ -6132,11 +6293,19 @@
<<").";
this->msg = os.str();
}
-
- statement::statement( cpdo_stmt * st )
- : st(st)
+
+ void statement::updateCounts(){
+ assert(this->st);
+ this->colCount = this->st->api->get.column_count( this->st );
+ this->paramCount = this->st->api->bind.param_count( this->st );
+ }
+ statement::statement( cpdo_stmt * st_ )
+ : st(st_),
+ colCount(0),
+ paramCount(0)
{
assert( NULL != st );
+ this->updateCounts();
}

statement::~statement() throw()
@@ -6155,7 +6324,8 @@

void statement::check_code( int code )
{
- if( cpdo_rc.AllocError == code )
+ if(!code) return;
+ else if( cpdo_rc.AllocError == code )
{
throw std::bad_alloc();
}
@@ -6168,7 +6338,7 @@
(0 != dbc),
msg ? msg : "Unknown error" );
}
- else if( code )
+ else
{
throw exception( code );
}
@@ -6189,21 +6359,19 @@

void statement::assert_index( uint16_t ndx, unsigned char base )
{
+ assert((1==base) || (0==base));
if( 1 == base )
{
- if(!ndx || (ndx > this->param_count()))
+ if(!ndx || (ndx > this->paramCount))
{
throw exception( cpdo_rc.RangeError, false,
"Bound parameter index out of range.");
}
}
- else
- {
- if(ndx >= this->col_count())
- {
- throw exception( cpdo_rc.RangeError, false,
- "Column index out of range.");
- }
+ else if(ndx >= this->colCount)
+ {
+ throw exception( cpdo_rc.RangeError, false,
+ "Column index out of range.");
}
}

@@ -6233,10 +6401,11 @@
***The diff for this file has been truncated for email.***
=======================================
--- /convert/addons/jspdo/cpdo_amalgamation.hpp Sat Feb 18 03:59:26 2012
+++ /convert/addons/jspdo/cpdo_amalgamation.hpp Thu Apr 12 06:23:08 2012
@@ -194,10 +194,10 @@

Requirements:

-- C99, but only for the fixed-size integer defined in stdint.h. The
-rest of the code "should" work fine in C89 mode. In theory it should
-work fine in C89 mode when including the C99-specified stdint.h, but
-the portability of that approach is questionable.
+- C99, but only for the fixed-size integer defined in stdint.h. The rest
of
+the code "should" work fine in C89 mode. It works fine in C89 mode when
+including the C99-specified stdint.h, but the portability of that approach
+is questionable.

- A db back-end for which we have a driver, including the required
headers and libraries needed for using that back-end.
@@ -205,9 +205,9 @@

Current code status:

-- The public API is more or less complete. There will be some
-additions to the cpdo_driver_api. e.g. for working with bound
-parameters by name. Some utility (non-member) functions are probably
+- The public API is more or less complete. There will likely be some
+additions to the cpdo_driver_api. e.g. for fetching table lists and similar
+driver-specific utilities. Some utility (non-member) functions are probably
missing, but those will be added as the need for them is found.

- The sqlite3 driver implementation seems to work as documented for
@@ -699,10 +699,10 @@
int (*qualify)( cpdo_driver * self, char const * identifier,
uint32_t * len, char ** dest );

/**
- Frees a string allocated by quote(). Results are undefined
- if the string came from another source. It must return 0 on
- success. It must, like free(), gracefully ignore a NULL string
- value.
+ Frees a string allocated by quote() or qualify(). Results are
+ undefined if the string came from another source. It must return
+ 0 on success. It must, like free(), gracefully ignore a NULL
+ string value.
*/
int (*free_string)( cpdo_driver * self, char * str);

@@ -740,8 +740,8 @@

Returns 0 on success (meaning that it fetched the info from the
underlying driver). On success *dest and/or *len and/or
- *errorCode may be set to 0 if the driver has no error to
- report. Some drivers may return other strings on error (sqlite3
+ *errorCode may be set to 0 if the driver has no error to report.
+ Some drivers may return other strings on non-error (sqlite3
infamously uses "not an error" for this case).

It is ASSUMED that the underlying driver owns the returned
@@ -888,27 +888,6 @@
yet.
*/
int (*get)( cpdo_driver * self, char const * key, va_list
vargs );
-
- /** @deprecated Use cpdo_driver_api::qualify().
-
- Must set *ch to the character used for quoting strings.
- Must return 0 on success, non-0 on error.
- Must return cpdo_rc.ArgError if ch is NULL.
-
- The driver may support a NULL value for the self object
- (e.g. if the quote character is constant for that driver),
- in which case it should set *ch to the quoting character
- and return 0. If the driver requires a non-NULL self
- pointer and a NULL is passed then the function must
- return cpdo_rc.ArgError. Alternately, it may set *ch to
- "some sane default" (i.e. a single-quote character) and
- return 0.
-
- Some drivers support both single- and double-quotes,
- but the use of double quotes is discouraged for
compatibility
- reasons.
- */
- int (*get_string_quote_char)( cpdo_driver * self, char * ch );
} opt;
/**
Holds non-function constants used by the driver implementation.
@@ -1933,7 +1912,81 @@
Convenience form of drv->api->free_string(drv,str).
*/
int cpdo_free_string( cpdo_driver * drv, char * str );
-
+
+ /**
+ Callback type used by cpdo_step_each(). It is called only in
+ response to a successful step() operation on st, and this function
+ may use st to fetch the current row's data, but must not step()
+ the statement or otherwise modify it. The state argument is the
+ 3rd argument passed to cpdo_step_each().
+
+ Implementations must return 0 on success, non-zero on error,
+ preferably a value from cson_rc.
+
+ @see cpdo_step_each()
+ @see cpdo_exec_each()
+ */
+ typedef int (*cpdo_step_each_f)( cpdo_stmt * st, void * state );
+
+ /**
+ Iterates over a SELECT-style curstor and calls a callback for
+ each iteration.
+
+ For each row it calls f(stmt,state), stopping if f() returns
+ non-0. Returns 0 on success, non-0 on error. If f() returns
+ non-0, that value is returned. If step() fails then
+ cpdo_rc.CheckDbError will be returned, a sign that the caller
+ should ask the statement for the driver-level error
+ information.
+
+ The client is free to return some magic value (e.g. -9999) from
+ his step function to indicate to the caller of this function
+ that it aborted early on purpose, as opposed to due to an
+ error.
+
+ @see cpdo_exec_each()
+ @see cpdo_exec_each_f()
+ @see cpdo_exec_each_f_v()
+ */
+ int cpdo_step_each( cpdo_stmt * stmt, cpdo_step_each_f f, void * state
);
+
+ /**
+ Convenience form of cpdo_step_each() which steps through the
+ first sqlLength bytes of the given SQL string, which is assumed
+ to be a statement which is capable of returning results. The
+ SQL must represent a single statement.
+
+ Returns 0 on success.
+
+ @see cpdo_step_each()
+ @see cpdo_exec_each_f()
+ @see cpdo_exec_each_f_v()
+ */
+ int cpdo_exec_each( cpdo_driver * db, cpdo_step_each_f f, void * state,
+ char const * sql, unsigned int sqlLength );
+
+ /**
+ Variadic form of cpdo_exec_each(), accepts the same formatting
+ specifies supported by cpdo_prepare_f_v().
+
+ @see cpdo_step_each()
+ @see cpdo_exec_each()
+ @see cpdo_exec_each_f()
+ */
+ int cpdo_exec_each_f_v( cpdo_driver * db, cpdo_step_each_f f, void *
state,
+ char const * sql, va_list args );
+
+ /**
+ Variadic form of cpdo_exec_each(), accepts the same formatting
+ specifies supported by cpdo_prepare_f().
+
+ @see cpdo_step_each()
+ @see cpdo_exec_each()
+ @see cpdo_exec_each_f_v()
+ */
+ int cpdo_exec_each_f( cpdo_driver * db, cpdo_step_each_f f, void *
state,
+ char const * sql, ... );
+
/** LICENSE

This software's source code, including accompanying documentation and
@@ -2240,11 +2293,12 @@
*/
void * mem;
/**
- Arbitrary value. e.g. (MYSQL_TIME*) for a
- MYSQL_TYPE_TIMESTAMP value (or equivalent for a
- given driver). Drivers can use this to
- distinguish between multiple types bound with the
- cpdo type CPDO_TYPE_CUSTOM.
+ Arbitrary value. e.g. a value from
+ enum_mysql_timestamp_type for a
+ MYSQL_TYPE_TIMESTAMP value (or equivalent for a
+ given driver). Drivers can use this to distinguish
+ between multiple types bound with the cpdo type
+ CPDO_TYPE_CUSTOM.

See cpdo_bind_val_custom() for more notes on this.
*/
@@ -2354,6 +2408,20 @@
option. The client would probably need to call into the driver
API to generate such a mask, or we could add it to the public API,
and use driver->api as the address to mask against. Hmmm...
+
+ FIXME: use a (void const *) as the type tag here, and let the
+ driver choose some internal static pointer to associate with
+ each type. Disadvantage: can't use it in a
+ switch/case. Alternately, take 2 params here: one identifies
+ the driver name and one a driver-specific type id. We could
+ then construct an internal tag with no collisions based on
+ that. BUT... since we only have MySQL for now (and the
+ foreseeable future), that might be getting ahead of myself.
+ And, in hindsight, since the only way for values bound this way
+ to cross into another driver's implementation is if a client
+ swaps the impl or api members of cpdo_stmt object, we could
+ safely just allow each driver to pass any value as typeTag, and
+ not do any type of hashing/verification on it.
*/
int cpdo_bind_val_custom( cpdo_bind_val * b, void * mem,
void (*dtor)(void *), int typeTag );
@@ -2691,7 +2759,7 @@
into the Public Domain.

In jurisdictions which do not recognize Public Domain property
- (e.g. Germany as of 2011), this software is Copyright (c) 2011
+ (e.g. Germany as of 2011), this software is Copyright (c) 2011-2012
by Stephan G. Beal, and is released under the terms of the MIT License
(see below).

@@ -2790,8 +2858,12 @@
/* start of file include/wh/cpdo/cpdo.hpp */
#if !defined(WANDERINGHORSE_NET_CPDO_CPDO_HPP_H_INCLUDED)
#define WANDERINGHORSE_NET_CPDO_CPDO_HPP_H_INCLUDED
+#include <cassert>
#include <stdexcept>
#include <string>
+#include <cstring>
+#include <algorithm> /* copy() */
+#include <sstream>

/**
The cpdo namespace houses a C++ wrapper around the cpdo C API.
@@ -2821,7 +2893,7 @@
{
public:
~exception() throw() {}
-
+
/**
Returns this exception's message string.
*/
@@ -2845,28 +2917,27 @@
*/
bool is_db_error() const throw()
{ return this->is_db_err; }
+
+ /**
+ Extracts error information from drv and closes drv. Ownership
+ of drv is passed to this object, and it is destroyed before the
+ constructor returns.
+
+ this->is_db_error() will return true if drv is not NULL, else
+ it will return false.
+ */
+ explicit exception( cpdo_driver * drv );
+ //TODO?: exception( cpdo_stmt * st );
+ exception( int code, bool isDbErr, std::string const & msg )
+ : code(code), is_db_err(isDbErr), msg(msg)
+ {}
+ /**
+ Assumes code is a cpdo_rc error code and builds a basic
+ error string from it.
+ */
+ explicit exception( int code );

private:
- friend class statement;
- friend class driver;
- /**
- Extracts error information from drv and closes drv.
Ownership
- of drv is passed to this object, and it is destroyed
before the
- constructor returns.
-
- this->is_db_error() will return true if drv is not NULL,
else
- it will return false.
- */
- exception( cpdo_driver * drv );
- //TODO?: exception( cpdo_stmt * st );
- exception( int code, bool isDbErr, std::string const & msg )
- : code(code), is_db_err(isDbErr), msg(msg)
- {}
- /**
- Assumes code is a cpdo_rc error code and builds a basic
- error string from it.
- */
- exception( int code );
int code;
bool is_db_err;
std::string msg;
@@ -2874,496 +2945,1758 @@
};

/**
- A simple wrapper around the cpdo_stmt C class.
- These objects can only be instantiated by using driver::prepare(),
- and each instance MUST be destroyed (using the delete operator)
- BEFORE its parent driver is destroyed, or undefined results will
- ensue. If a statement is destroyed after its underlying driver,
- a segfault is almost certain. If it is not destroyed, a leak is
certain.
+ A simple wrapper around the cpdo_stmt C class. These objects
+ can only be instantiated by using driver::prepare(), and each
+ instance MUST be destroyed (using the delete operator) BEFORE
+ its parent driver is destroyed, or undefined results will
+ ensue. If a statement is destroyed after its underlying driver,
+ a segfault is almost certain. If it is not destroyed, a leak is
+ certain and the driver may misbehave (e.g. not be able to
+ prepare new queries or be unable to close the connection
+ properly).
*/
class statement
{
- private:
- cpdo_stmt * st;
- friend class driver;
- //! Instantiated only via driver::prepare().
- statement( cpdo_stmt * );
- //! Not allowed/implemented.
- statement( statement const & );
- //! Not allowed/implemented.
- statement & operator=( statement const & );
- //! Throws if code is not 0.
- void check_code( int code );
- /**
- Throws if code ndx is out of range. If base is 1
- then BIND (1-based) indexes as assumed, else GET
- (0-based) are assumed.
- */
- void assert_index( uint16_t ndx, unsigned char base );
- /**
- Closes the underlying statement handle, but does not
- destroy this object. It is illegal to use any member
- functions of this object after calling this.
- */
- void finalize() throw();
-
- /**
- Throws if finalize() has been called.
- */
- void assert_alive() const THROWS_ON_ERROR;
- public:
- ~statement() throw();
-
- /** Returns true for CPDO_STEP_ROW, false for CPDO_STEP_DONE,
- and throws on CPDO_STEP_ERROR.
- */
- bool step() THROWS_ON_ERROR;
- /**
- Returns the last driver-level error code, or 0 if there is
none.
- */
- int error_code();
-
- /**
- Returns the last driver-level error message. If there was
no
- recent error, this function _might_ return an empty string
or
- _might_ return some other value, depending on how the
underlying
- db driver does it (e.g. sqlite3 uses "not an error").
- */
- std::string error_text();
-
- /**
- Returns the number of bound parameter placeholders are in
- the prepared query.
- */
- uint16_t param_count();
-
- /**
- Returns the 1-based BIND parameter for the given
placeholder name,
- or 0 if no such parameter is found or on error (e.g. if the
- driver does not support named parameters).
- */
- uint16_t param_index( char const * name );
-
- /**
- Returns the name for the given 1-based BIND parameter
- index, throwing on error (e.g. out of bounds).
- Returns NULL if the driver reports no name for the
- given parameter.
- */
- char const * param_name( uint16_t ndx ) THROWS_ON_ERROR;
-
- /**
- Binds the NULL value to the given 1-based index.
- Throws if ndx is out of bounds.
- */
- void bind( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, int8_t v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, int16_t v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, int32_t v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, int64_t v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, float v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, double v ) THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, char const * v, uint32_t len )
THROWS_ON_ERROR;
- /**
- Binds the given value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value.
- */
- void bind( uint16_t ndx, std::string const & v )
THROWS_ON_ERROR;
- /**
- Binds the given "blob" value to the given 1-based index.
- Throws if ndx is out of bounds or if there is a
driver-level
- error when binding the value as a blob.
- */
- void bind( uint16_t ndx, void const * v, uint32_t len )
THROWS_ON_ERROR;
-
- /**
- Resets a statement to its pre-execution state so that it
- can be executed again. This is most often used between loop
- iterations when performing INSERT operations.
- See cpdo_stmt_api::reset().
- */
- void reset() THROWS_ON_ERROR;
-
- /**
- Returns the number of columns in the result set, or 0 for
- non-fetching queries or on error.
- */
- uint16_t col_count();
- /**
- Returns the name of the column at the given index.
- Throws if ndx is out of bounds
- or there is a driver-level error while fetching the data.
- The returned bytes are owned by the underlying driver and
may
- be invalidated on the next step() operation (or when the
statement
- is freed), so they must be copied if needed for later.
- See cpdo_stmt_api::get::col_name().
- */
- char const * col_name( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::type(). Throws if ndx is out of
bounds.
- */
- cpdo_data_type col_type( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::i8(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- int8_t get_int8( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::i16(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- int16_t get_int16( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::i32(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- int32_t get_int32( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::i64(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- int64_t get_int64( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::flt(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- float get_float( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::dbl(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- NULL values translate to 0.
- */
- double get_double( uint16_t ndx ) THROWS_ON_ERROR;
- /**
- See cpdo_stmt_api::get::string(). Throws if ndx is out of
bounds
- or there is a driver-level error while fetching the data.
- If size is not NULL then the length of the fetched string
- is written to it.
- */
- char const * get_string( uint16_t ndx, uint32_t * size = NULL
) THROWS_ON_ERROR;
-
- /**
- Fetches blob data from the given 0-based column.
- A length-0 blob is returned as a NULL pointer.
- On success a pointer to the bytes is returned and
- *size is set to their length. size may be NULL,
- but if it is then the caller will have no way of
- knowing the length.
- */
- void const * get_blob( uint16_t ndx, uint32_t * size )
THROWS_ON_ERROR;
-
- /**
- Returns the underlying cpdo_stmt handle. The handle is
owned
- by this object and MUST NOT be closed/destroyed by the
caller,
- nor may it be used concurrently with this object (e.g.
- multi-threaded). This function is primarily provided so
that the
- C++ API can be used with generic C routines which are not
part
- of the cpdo_stmt_api interface.
- */
- cpdo_stmt * handle();
+ private:
+ cpdo_stmt * st;
+ uint16_t colCount;
+ uint16_t paramCount;
+ friend class driver;
+ friend class chainer;
+ //! Instantiated only via driver::prepare().
+ statement( cpdo_stmt * );
+ //! Not allowed/implemented.
+ statement( statement const & );
+ //! Not allowed/implemented.
+ statement & operator=( statement const & );
+ void updateCounts();
+ //! Throws if code is not 0.
+ void check_code( int code );
+ /**
+ Throws if code ndx is out of range. If base is 1
+ then BIND (1-based) indexes as assumed, else GET
+ (0-based) are assumed.
+ */
+ void assert_index( uint16_t ndx, unsigned char base );
+ /**
+ Closes the underlying statement handle, but does not
+ destroy this object. It is illegal to use any member
+ functions of this object after calling this.
+ */
+ void finalize() throw();
+
+ /**
+ Throws if finalize() has been called.
+ */
+ void assert_alive() const THROWS_ON_ERROR;
+ public:
+ /**
+ finalize()es the underlying statement handle.
+ */
+ ~statement() throw();
+
+ /** Returns true for CPDO_STEP_ROW, false for CPDO_STEP_DONE,
+ and throws on CPDO_STEP_ERROR.
+ */
+ bool step() THROWS_ON_ERROR;
+
+ /**
+ Returns the last driver-level error code, or 0 if there is none.
+ */
+ int error_code();
+
+ /**
+ Returns the last driver-level error message. If there was no
+ recent error, this function _might_ return an empty string or
+ _might_ return some other value, depending on how the underlying
+ db driver does it (e.g. sqlite3 uses "not an error").
+ */
+ std::string error_text();
+
+ /**
+ Returns the number of bound parameter placeholders are in
+ the prepared query.
+ */
+ uint16_t param_count() const;
+
+ /**
+ Returns the 1-based BIND parameter for the given placeholder
name,
+ or 0 if no such parameter is found or on error (e.g. if the
+ driver does not support named parameters).
+ */
+ uint16_t param_index( char const * name );
+
+ /**
+ Returns the name for the given 1-based BIND parameter
+ index, throwing on error (e.g. out of bounds).
+ Returns NULL if the driver reports no name for the
+ given parameter.
+ */
+ char const * param_name( uint16_t ndx ) THROWS_ON_ERROR;
+
+ /**
+ Binds the NULL value to the given 1-based index.
+ Throws if ndx is out of bounds.
+ */
+ void bind( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, int8_t v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, int16_t v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, int32_t v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, int64_t v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, float v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, double v ) THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, char const * v, uint32_t len )
THROWS_ON_ERROR;
+ /**
+ Binds the given value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value.
+ */
+ void bind( uint16_t ndx, std::string const & v ) THROWS_ON_ERROR;
+ /**
+ Binds the given "blob" value to the given 1-based index.
+ Throws if ndx is out of bounds or if there is a driver-level
+ error when binding the value as a blob.
+ */
+ void bind( uint16_t ndx, void const * v, uint32_t len )
THROWS_ON_ERROR;
+
+ /**
+ Resets a statement to its pre-execution state so that
+ it can be executed again. This is most often used
+ between loop iterations when performing INSERT
+ operations. See cpdo_stmt_api::reset(). When called on
+ a fetching query this will effectively re-set the
+ cursor to the beginning of the result set.
+ */
+ void reset() THROWS_ON_ERROR;
+
+ /**
+ Returns the number of columns in the result set, or 0 for
+ non-fetching queries or on error.
+ */
+ uint16_t col_count() const;
+
+ /**
+ Returns the name of the column at the given index.
+ Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ The returned bytes are owned by the underlying driver and may
+ be invalidated on the next step() operation (or when the
statement
+ is freed), so they must be copied if needed for later.
+ See cpdo_stmt_api::get::col_name().
+ */
+ char const * col_name( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::type(). Throws if ndx is out of bounds.
+ */
+ cpdo_data_type col_type( uint16_t ndx ) THROWS_ON_ERROR;
+
+ /**
+ Returns true if the result column at the given index
+ has a NULL value, else false.
+ */
+ bool col_is_null( uint16_t ndx ) THROWS_ON_ERROR;
+
+ /**
+ See cpdo_stmt_api::get::i8(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ int8_t get_int8( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::i16(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ int16_t get_int16( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::i32(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ int32_t get_int32( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::i64(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ int64_t get_int64( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::flt(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ float get_float( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::dbl(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ NULL values translate to 0.
+ */
+ double get_double( uint16_t ndx ) THROWS_ON_ERROR;
+ /**
+ See cpdo_stmt_api::get::string(). Throws if ndx is out of bounds
+ or there is a driver-level error while fetching the data.
+ If size is not NULL then the length of the fetched string
+ is written to it.
+ */
+ char const * get_string( uint16_t ndx, uint32_t * size = NULL )
THROWS_ON_ERROR;
+
+ /**
+ Fetches blob data from the given 0-based column.
+ A length-0 blob is returned as a NULL pointer.
+ On success a pointer to the bytes is returned and
+ *size is set to their length. size may be NULL,
+ but if it is then the caller will have no way of
+ knowing the length.
+ */
+ void const * get_blob( uint16_t ndx, uint32_t * size )
THROWS_ON_ERROR;
+
+ /**
+ Returns the underlying cpdo_stmt handle. The handle is owned
+ by this object and MUST NOT be closed/destroyed by the caller,
+ nor may it be used concurrently with this object (e.g.
+ multi-threaded). This function is primarily provided so that the
+ C++ API can be used with generic C routines which are not part
+ of the cpdo_stmt_api interface.
+ */
+ cpdo_stmt * handle();

};

+
/**
- This convenience class is intended to be used similarly to
- std::auto_ptr to protect against leaks when a locally-created
- statement object throws an exception. It is recommended that
- client code use these objects in conjunction with the return
- values from driver::prepare() to simplify error handling in the
- case that using the prepared statement throws. Statements will
- be returned from a function, do not use this class or use its
- take() member to transfer ownership to the caller.
-
- These objects are intended to be created only on the stack, not via
- (new stmt).
-
- Example:
-
- @code
- stmt st( myDriver->prepare(...) );
- // Now use the '->' operator to access the statement's API, e.g.:
- while( st->step() ) { puts(st->get_string(0)); }
- // To take over ownership of the statement object:
- statement * s = st.take();
- @endcode
+ Convenience base for col_bind and col_get templates.
+ */
+ template <cpdo_data_type TypeID>
+ struct col_base
+ {
+ private:
+ static const char AssertTypeIsOk[(TypeID==CPDO_TYPE_ERROR) ? -1 :
1];
+ public:
+ static const cpdo_data_type data_type = TypeID;
+ };
+
+ /**
+ Base (unimplemented) instantiation of a template which
+ implements statement::bind() operations in terms of
+ operator(). The template type T specifies the native
+ data type to be stored in the DB, and specializations
+ of this type are then responsible for binding values of
+ that type.
+ */
+ template <typename T>
+ struct col_bind;
+
+ template <typename T>
+ struct col_bind<T const> : col_bind<T>
+ {};
+ template <typename T>
+ struct col_bind<T const &> : col_bind<T>
+ {};
+ template <typename T>
+ struct col_bind<T &> : col_bind<T>
+ {};
+#if 0
+ template <typename T>
+ struct col_bind<T *> : col_bind<T>
+ {};
+ template <typename T>
+ struct col_bind<T const *> : col_bind<T>
+ {};
+#endif
+
+ template <>
+ struct col_bind<void> : col_base<CPDO_TYPE_NULL> {
+ void operator()( statement & st, uint16_t ndx ){st.bind( ndx );}
+ };
+ template <>
+ struct col_bind<int8_t> : col_base<CPDO_TYPE_INT8> {
+ typedef int8_t value_type;
+ void operator()( statement & st, uint16_t ndx, int8_t v ){st.bind(
ndx, v );}
+ };
+ template <>
+ struct col_bind<int16_t> : col_base<CPDO_TYPE_INT16> {
+ typedef int16_t value_type;
+ void operator()( statement & st, uint16_t ndx, int16_t v
){st.bind( ndx, v );}
+ };
+ template <>
+ struct col_bind<int32_t> : col_base<CPDO_TYPE_INT32> {
+ typedef int32_t value_type;
+ void operator()( statement & st, uint16_t ndx, int32_t v
){st.bind( ndx, v );}
+ };
+ template <>
+ struct col_bind<int64_t> : col_base<CPDO_TYPE_INT64> {
+ typedef int64_t value_type;
+ void operator()( statement & st, uint16_t ndx, int64_t v
){st.bind( ndx, v );}
+ };
+ template <>
+ struct col_bind<float> : col_base<CPDO_TYPE_FLOAT> {
+ typedef float value_type;
+ void operator()( statement & st, uint16_t ndx, float v ){st.bind(
ndx, v );}
+ };
+ template <>
+ struct col_bind<double> : col_base<CPDO_TYPE_DOUBLE> {
+ typedef double value_type;
+ void operator()( statement & st, uint16_t ndx, double v ){st.bind(
ndx, v );}
+ };
+ template <>
+ struct col_bind<char const *> : col_base<CPDO_TYPE_STRING> {
+ typedef char const * value_type;
+ void operator()( statement & st, uint16_t ndx, char const * v,
uint32_t len ){
+ st.bind( ndx, v, len );
+ }
+ void operator()( statement & st, uint16_t ndx, char const * v ){
+ st.bind( ndx, v, v ? std::strlen(v) : 0 );
+ }
+ };
+
+ template <>
+ struct col_bind<char *> : col_bind<char const *> {};
+
+ template <>
+ struct col_bind<std::string> : col_base<CPDO_TYPE_STRING>{
+ typedef std::string value_type;
+ void operator()( statement & st, uint16_t ndx, std::string const &
v ){
+ st.bind( ndx, v );
+ }
+ };
+
+ template <>
+ struct col_bind<void const *> : col_base<CPDO_TYPE_BLOB>{
+ typedef void const * value_type;
+ void operator()( statement & st, uint16_t ndx, void const * v,
uint32_t len ){
+ st.bind( ndx, v, len );
+ }
+ };
+
+ template <>
+ struct col_bind<void *> : col_bind<void const *> {};
+
+ /**
+ Internal convenience base type.
+ */
+ template <typename T>
+ struct col_bind0_base
+ {
+ public:
+ typedef typename col_bind<T>::value_type value_type;
+ protected:
+ statement * st;
+ uint16_t ndx;
+ value_type val;
+ col_bind0_base() {}
+ };
+
+
+ /**
+ Experimental.
+ */
+ template <typename T>
+ struct col_bind0 : col_bind0_base<T>
+ {
+ public:
+ typedef typename col_bind<T>::value_type value_type;
+ col_bind0( statement & s, uint16_t ndx, value_type v )
+ {
+ this->st = &s;
+ this->ndx = ndx;
+ this->val = v;
+ }
+ void operator()(){
+ typedef col_bind<T> B;
+ return B()( *this->st, this->ndx, this->val );
+ }
+ };
+
+ /**
+ Experimental.
+ */
+ template <typename T>
+ struct col_bind0_2 : col_bind0_base<T>
+ {
+ protected:
+ uint32_t len;
+ public:
+ typedef typename col_bind<T>::value_type value_type;
+ col_bind0_2( statement & s, uint16_t ndx, value_type v, uint32_t
len )
+ {
+ this->st = &s;
+ this->ndx = ndx;
+ this->val = v;
+ this->len = len;
+ }
+ void operator()(){
+ typedef col_bind<T> B;
+ return B()( *this->st, this->ndx, this->val, this->len );
+ }
+ };
+ template <>
+ struct col_bind0<void const *> : col_bind0_2<void const *> {};
+ template <>
+ struct col_bind0<void *> : col_bind0<void const *> {};
+ template <>
+ struct col_bind0<char const *> : col_bind0_2<char const *> {};
+
+ template <>
+ struct col_bind0<std::string> : col_bind0_base<std::string>
+ {
+ public:
+ typedef col_bind<std::string>::value_type value_type;
+ col_bind0( statement & s, uint16_t ndx, std::string const & v )
+ {
+ this->st = &s;
+ this->ndx = ndx;
+ this->val = v;
+ }
+ void operator()(){
+ typedef col_bind<char const *> B;
+ return B()( *this->st, this->ndx, this->val.c_str(),
this->val.size() );
+ }
+ };
+
+
+ /**
+ Base (unimplemented) declaration for a family of templates
+ which should use T to figure out which statement::get_xxx()
+ function to call to fetch a value. Implementations must have an
+ operator() which takes (StatementLike &, uint16_t) parameters,
+ and may take additional parameters. StatementLike must be
+ statement, stmt_row, or compatible.
+ */
+ template <typename T>
+ struct col_get;
+
+ template <typename T>
+ struct col_get<volatile T> : col_get<T>
+ {};
+
+ template <typename T>
+ struct col_get<T const> : col_get<T>
+ {};
+
+ template <typename T>
+ struct col_get<T const &> : col_get<T>
+ {};
***The diff for this file has been truncated for email.***
=======================================
--- /convert/addons/jspdo/jspdo-init.js Fri Mar 30 15:11:13 2012
+++ /convert/addons/jspdo/jspdo-init.js Thu Apr 12 06:23:08 2012
@@ -193,17 +193,20 @@
is called in a loop, where N is the set [0,opt.columnCount).
*/
sp.bind = function(opt) {
- if( (1!==arguments.length) || !(opt instanceof ctor.Statement) )
- return origImpls.bind.apply(this, argvToArray(arguments));
+ if( (1!==arguments.length) || !(opt instanceof ctor.Statement) ) {
+ origImpls.bind.apply(this, argvToArray(arguments));
+ return this;
+ }
else if( ! opt.columnCount )
- throw new Error("Statement to bind from has no result
columns.");
+ throw new Error("Source Statement has no result columns.");
else if( opt.columnCount !== this.paramCount )
throw new Error("Source and destination column counts do not
match "+
opt.columnCount+' vs. '+this.paramCount);
- var i;
- for( i = 0; i < opt.columnCount;++i ) {
+ var i, l = opt.columnCount;
+ for( i = 0; i < l;++i ) {
this.bind( 1+i, opt.get(i) );
}
+ return this;
};


=======================================
--- /convert/addons/jspdo/jspdo.cpp Sun Feb 19 03:41:33 2012
+++ /convert/addons/jspdo/jspdo.cpp Thu Apr 12 06:23:08 2012
@@ -24,6 +24,7 @@
#include "cpdo_amalgamation.hpp"

#include "cvv8/ClassCreator.hpp"
+#include "cvv8/XTo.hpp"
#include "cvv8/properties.hpp"

#include "jspdo.hpp"
@@ -67,6 +68,9 @@
/** We don't really need the extra type-safety bits for Statement b/c
subclassing will never be an issue (b/c client code can't create
Statements directly (or it's not in the public API, anyway)).
+
+ We use an extra internal field for storing a statement-to-db
+ mapping for cleanup purposes.
*/
template <>
struct ClassCreator_InternalFields<cpdo::statement>
@@ -235,7 +239,6 @@
cpdo::driver const * drv = getDriverForStmt(nativeSelf,jsSelf);
if( drv )
{
- v8::Locker const lock;
jspdo::DbMapLocker().map()[drv][nativeSelf] = jsSelf;
}
return;
@@ -385,7 +388,7 @@
buf << "[cpdo::driver@"<<(void const *)drv;
if( drv )
{
- buf << ", driver="<<drv->driver_name();
+ buf << " driver="<<drv->driver_name();
}
return buf << ']';
}
@@ -399,7 +402,7 @@
if( st )
{
v8::Handle<v8::Value> const v(argv.This()->Get(JSTR("sql")));
- if( !v.IsEmpty() && v->IsString()) sb << ", sql=["<<v<<"]";
+ if( !v.IsEmpty() && v->IsString()) sb << "sql=["<<v<<"]";
}
return sb << ']';
}
@@ -680,7 +683,7 @@
}
if( 2 == argc )
{
- return Statement_bind( st, argv[0], argv[1] );
+ Statement_bind( st, argv[0], argv[1] );
}
else /* one argument */
{
@@ -688,18 +691,19 @@
if( val->IsArray() )
{
v8::Handle<v8::Array> ar((v8::Array::Cast(*val)));
- return Statement_bind( st, ar );
+ Statement_bind( st, ar );
}
else if( val->IsObject() )
{
v8::Handle<v8::Object> obj((v8::Object::Cast(*val)));
- return Statement_bind( st, obj );
+ Statement_bind( st, obj );
}
else
{
- return Statement_bind( st, val, v8::Null() );
+ Statement_bind( st, val, v8::Null() );
}
}
+ return argv.This();
}

//! JSPDO.Statement.stepArray() impl.
@@ -1169,16 +1173,16 @@
//SPB::BindGetterMethod<uint16_t
(),&ST::param_count>( "paramCount", stProto );
//SPB::BindGetterMethod<uint16_t
(),&ST::col_count>( "columnCount", stProto );
stProto->SetAccessor(JSTR("errorCode"),
- MethodToGetter<ST, int
(),&ST::error_code>::Get,
+ MethodTo< Getter, ST, int
(),&ST::error_code>::Get,
throwOnSet);
stProto->SetAccessor(JSTR("errorText"),
- MethodToGetter<ST, std::string
(),&ST::error_text>::Get,
+ MethodTo< Getter, ST, std::string
(),&ST::error_text>::Get,
throwOnSet);
stProto->SetAccessor(JSTR("columnCount"),
- MethodToGetter<ST, uint16_t
(),&ST::col_count>::Get,
+ MethodTo< Getter, ST const, uint16_t
(),&ST::col_count>::Get,
throwOnSet);
stProto->SetAccessor(JSTR("paramCount"),
- MethodToGetter<ST, uint16_t
(),&ST::param_count>::Get,
+ MethodTo< Getter, ST const, uint16_t
(),&ST::param_count>::Get,
throwOnSet);
stProto->SetAccessor(JSTR("columnNames"),
Statement_getColumnNames, throwOnSet );
// do not bind columnTypes for the time being because
@@ -1200,7 +1204,7 @@
)
("prepare", CATCHER< cv::InCaToInCa<JSPDO_prepare> >::Call
)
("qualify", CATCHER< cv::MethodToInCa<DRV,std::string
(std::string const &),&DRV::qualify> >::Call)
- ("quote", CATCHER< cv::MethodToInCa<DRV,std::string
(std::string const &),&DRV::quote> >::Call)
+ ("quote", CATCHER< cv::MethodToInCa<DRV,std::string (char
const *),&DRV::quote> >::Call)
("rollback", CATCHER< cv::MethodToInCa<DRV,void
(),&DRV::rollback> >::Call)
("toString", CATCHER< cv::InCaToInCa<JSPDO_toString>
>::Call)
;

Reply all
Reply to author
Forward
0 new messages