ext/odbc.c in ruby-odbc-0.99991 vs ext/odbc.c in ruby-odbc-0.99992
- old
+ new
@@ -1,16 +1,16 @@
/*
* ODBC-Ruby binding
- * Copyright (c) 2001-2009 Christian Werner <chw@ch-werner.de>
+ * Copyright (c) 2001-2010 Christian Werner <chw@ch-werner.de>
* Portions copyright (c) 2004 Ryszard Niewisiewicz <micz@fibernet.pl>
* Portions copyright (c) 2006 Carl Blakeley <cblakeley@openlinksw.co.uk>
*
* See the file "COPYING" for information on usage
* and redistribution of this file and for a
* DISCLAIMER OF ALL WARRANTIES.
*
- * $Id: odbc.c,v 1.62 2010/04/25 12:26:37 chw Exp chw $
+ * $Id: odbc.c,v 1.70 2010/09/16 06:52:23 chw Exp chw $
*/
#undef ODBCVER
#if defined(_WIN32) || defined(__CYGWIN32__) || defined(__MINGW32__)
@@ -53,10 +53,14 @@
#endif
#ifndef HAVE_TYPE_SQLULEN
#define SQLULEN SQLUINTEGER
#endif
+#if (RUBY_VERSION_MAJOR <= 1) && (RUBY_VERSION_MINOR < 9)
+#define TIME_USE_USEC 1
+#endif
+
/*
* Conditionally undefine aliases of ODBC installer UNICODE functions.
*/
#if defined(UNICODE) && defined(HAVE_SQLINSTALLERERRORW)
@@ -71,11 +75,11 @@
#if defined(UNICODE) && defined(HAVE_SQLWRITEFILEDSNW)
#undef SQLWriteFileDSN
#endif
#if defined(UNICODE) && defined(USE_DLOPEN_FOR_ODBC_LIBS)
-extern int ruby_odbc_have_func(char *name, void *addr);
+extern int ruby_odbc_have_func(const char *name, void *addr);
#endif
#ifdef UNICODE
/*
* Declarations of required installer APIs in case
@@ -92,10 +96,18 @@
BOOL INSTAPI SQLReadFileDSNW(LPWSTR, LPWSTR, LPWSTR, LPWSTR, WORD, WORD *);
#endif
#ifndef HAVE_SQLWRITEFILEDSNW
BOOL INSTAPI SQLWriteFileDSNW(LPWSTR, LPWSTR, LPWSTR, LPWSTR);
#endif
+
+#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
+#define USE_RB_ENC 1
+#include "ruby/encoding.h"
+static rb_encoding *rb_enc = NULL;
+static VALUE rb_encv = Qnil;
+#endif
+
#endif /* UNICODE */
#ifndef HAVE_RB_DEFINE_ALLOC_FUNC
#define rb_define_alloc_func(cls, func) \
rb_define_singleton_method(cls, "new", func, -1)
@@ -107,15 +119,20 @@
#define CVAR_SET(x, y, z) rb_cvar_set(x, y, z, 0)
#else
#define CVAR_SET(x, y, z) rb_cvar_set(x, y, z)
#endif
+#ifndef STR2CSTR
+#define STR2CSTR(x) StringValueCStr(x)
+#define NO_RB_STR2CSTR 1
+#endif
+
#ifdef TRACING
static int tracing = 0;
#define tracemsg(t, x) {if (tracing & t) { x }}
static SQLRETURN tracesql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt,
- SQLRETURN ret, char *m);
+ SQLRETURN ret, const char *m);
#else
#define tracemsg(t, x)
#define tracesql(a, b, c, d, e) d
#endif
@@ -146,10 +163,12 @@
VALUE self;
VALUE env;
struct env *envp;
LINK stmts;
SQLHDBC hdbc;
+ VALUE rbtime;
+ VALUE gmtime;
int upc;
} DBC;
typedef struct {
SQLSMALLINT type;
@@ -161,16 +180,16 @@
SQLSMALLINT iotype;
int override;
#ifdef UNICODE
SQLWCHAR *tofree;
#endif
- char buffer[sizeof (double) * 4];
+ char buffer[sizeof (double) * 4 + sizeof (TIMESTAMP_STRUCT)];
SQLSMALLINT ctype;
SQLSMALLINT outtype;
int outsize;
char *outbuf;
-} PINFO;
+} PARAMINFO;
typedef struct {
int type;
int size;
} COLTYPE;
@@ -180,14 +199,15 @@
VALUE self;
VALUE dbc;
struct dbc *dbcp;
SQLHSTMT hstmt;
int nump;
- PINFO *pinfo;
+ PARAMINFO *paraminfo;
int ncols;
COLTYPE *coltypes;
char **colnames;
+ VALUE *colvals;
char **dbufs;
int fetchc;
int upc;
int usef;
} STMT;
@@ -215,10 +235,12 @@
static ID IDatattrs;
static ID IDday;
static ID IDmonth;
static ID IDyear;
static ID IDmday;
+static ID IDnsec;
+static ID IDusec;
static ID IDsec;
static ID IDmin;
static ID IDhour;
static ID IDusec;
static ID IDkeyp;
@@ -246,10 +268,16 @@
static ID IDstatement;
static ID IDreturn_output_param;
static ID IDattrs;
static ID IDNULL;
static ID IDdefault;
+#ifdef USE_RB_ENC
+static ID IDencode;
+#endif
+static ID IDparse;
+static ID IDutc;
+static ID IDlocal;
/*
* Modes for dbc_info
*/
@@ -297,11 +325,11 @@
/*
* Forward declarations.
*/
static SQLRETURN callsql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt,
- SQLRETURN ret, char *m);
+ SQLRETURN ret, const char *m);
static VALUE stmt_exec(int argc, VALUE *argv, VALUE self);
static VALUE stmt_each(VALUE self);
static VALUE stmt_each_hash(int argc, VALUE *argv, VALUE self);
static VALUE stmt_close(VALUE self);
@@ -419,10 +447,13 @@
if ((cp != NULL) && (str != NULL)) {
ulen = mkutf(cp, str, len);
}
v = rb_tainted_str_new((cp != NULL) ? cp : "", ulen);
+#ifdef USE_RB_ENC
+ rb_enc_associate(v, rb_enc);
+#endif
if (cp != NULL) {
xfree(cp);
}
return v;
}
@@ -441,11 +472,15 @@
int ulen = 0;
if ((cp != NULL) && (str != NULL)) {
ulen = mkutf(cp, str, len);
}
+#ifdef USE_RB_ENC
+ v = rb_enc_str_new((cp != NULL) ? cp : "", ulen, rb_enc);
+#else
v = rb_str_new((cp != NULL) ? cp : "", ulen);
+#endif
if (cp != NULL) {
xfree(cp);
}
return v;
}
@@ -492,11 +527,11 @@
unsigned char c = str[0];
if (c < 0x80) {
uc[i++] = c;
++str;
- } else if (c <= 0xc1 || (c >= 0xf5 && c <= 0xff)) {
+ } else if ((c <= 0xc1) || (c >= 0xf5)) {
/* illegal, ignored */
++str;
} else if (c < 0xe0) {
if ((str[1] & 0xc0) == 0x80) {
unsigned long t = ((c & 0x1f) << 6) | (str[1] & 0x3f);
@@ -765,20 +800,20 @@
}
static void
free_stmt_sub(STMT *q)
{
- if (q->pinfo != NULL) {
+ if (q->paraminfo != NULL) {
int i;
for (i = 0; i < q->nump; i++) {
- if (q->pinfo[i].outbuf != NULL) {
- xfree(q->pinfo[i].outbuf);
+ if (q->paraminfo[i].outbuf != NULL) {
+ xfree(q->paraminfo[i].outbuf);
}
}
- xfree(q->pinfo);
- q->pinfo = NULL;
+ xfree(q->paraminfo);
+ q->paraminfo = NULL;
}
q->nump = 0;
q->ncols = 0;
if (q->coltypes != NULL) {
xfree(q->coltypes);
@@ -786,10 +821,14 @@
}
if (q->colnames != NULL) {
xfree(q->colnames);
q->colnames = NULL;
}
+ if (q->colvals != NULL) {
+ xfree(q->colvals);
+ q->colvals = NULL;
+ }
if (q->dbufs != NULL) {
xfree(q->dbufs);
q->dbufs = NULL;
}
if (q->self != Qnil) {
@@ -801,10 +840,14 @@
}
v = rb_iv_get(q->self, "@_h");
if (v != Qnil) {
rb_iv_set(q->self, "@_h", rb_hash_new());
}
+ v = rb_iv_get(q->self, "@_c");
+ if (v != Qnil) {
+ rb_iv_set(q->self, "@_c", rb_hash_new());
+ }
}
}
static void
link_stmt(STMT *q, DBC *p)
@@ -880,15 +923,18 @@
*
*----------------------------------------------------------------------
*/
static char *
-set_err(char *msg, int warn)
+set_err(const char *msg, int warn)
{
VALUE a, v = rb_str_new2("INTERN (0) [RubyODBC]");
v = rb_str_cat2(v, msg);
+#ifdef USE_RB_ENC
+ rb_enc_associate(v, rb_enc);
+#endif
a = rb_ary_new2(1);
rb_ary_push(a, rb_obj_taint(v));
CVAR_SET(Cobj, warn ? IDatatinfo : IDataterror, a);
return STR2CSTR(v);
}
@@ -1029,10 +1075,13 @@
case SQL_SUCCESS_WITH_INFO:
sprintf(buf, "INSTALLER (%d) ", (int) insterrcode);
v = rb_str_new2(buf);
#ifdef UNICODE
if (have_w) {
+#ifdef USE_RB_ENC
+ rb_enc_associate(v, rb_enc);
+#endif
v = uc_str_cat(v, msg, len);
} else {
v = rb_str_cat(v, (char *) msg, len);
}
#else
@@ -1076,11 +1125,12 @@
#ifdef TRACING
static void
trace_sql_ret(SQLRETURN ret)
{
- char msg[32], *p;
+ char msg[32];
+ const char *p;
switch (ret) {
case SQL_SUCCESS:
p = "SQL_SUCCESS";
break;
@@ -1103,11 +1153,12 @@
}
fprintf(stderr, " < %s\n", p);
}
static SQLRETURN
-tracesql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret, char *m)
+tracesql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret,
+ const char *m)
{
if (tracing & 1) {
fprintf(stderr, "SQLCall: %s", m);
fprintf(stderr, "\n > HENV=0x%lx, HDBC=0x%lx, HSTMT=0x%lx\n",
(long) henv, (long) hdbc, (long) hstmt);
@@ -1116,11 +1167,12 @@
return ret;
}
#endif
static SQLRETURN
-callsql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret, char *m)
+callsql(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret,
+ const char *m)
{
SQLRETURN err;
err = tracesql(henv, hdbc, hstmt, ret, m);
if (err != SQL_SUCCESS) {
@@ -1174,11 +1226,11 @@
return 1;
}
static int
succeeded(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret,
- char **msgp, char *m, ...)
+ char **msgp, const char *m, ...)
{
#ifdef TRACING
va_list args;
if (tracing & 1) {
@@ -1194,11 +1246,11 @@
return succeeded_common(henv, hdbc, hstmt, ret, msgp);
}
static int
succeeded_nodata(SQLHENV henv, SQLHDBC hdbc, SQLHSTMT hstmt, SQLRETURN ret,
- char **msgp, char *m, ...)
+ char **msgp, const char *m, ...)
{
#ifdef TRACING
va_list args;
if (tracing & 1) {
@@ -1233,20 +1285,20 @@
STMT *q;
Data_Get_Struct(self, STMT, q);
self = q->dbc;
if (self == Qnil) {
- rb_raise(Cerror, set_err("Stale ODBC::Statement", 0));
+ rb_raise(Cerror, "%s", set_err("Stale ODBC::Statement", 0));
}
}
if (rb_obj_is_kind_of(self, Cdbc) == Qtrue) {
DBC *p;
Data_Get_Struct(self, DBC, p);
self = p->env;
if (self == Qnil) {
- rb_raise(Cerror, set_err("Stale ODBC::Database", 0));
+ rb_raise(Cerror, "%s", set_err("Stale ODBC::Database", 0));
}
}
return self;
}
@@ -1276,11 +1328,11 @@
STMT *q;
Data_Get_Struct(self, STMT, q);
self = q->dbc;
if (self == Qnil) {
- rb_raise(Cerror, set_err("Stale ODBC::Statement", 0));
+ rb_raise(Cerror, "%s", set_err("Stale ODBC::Statement", 0));
}
}
Data_Get_Struct(self, DBC, p);
return p;
}
@@ -1336,11 +1388,11 @@
}
if (self == Cobj) {
self = Cenv;
}
if ((!SQL_SUCCEEDED(SQLAllocEnv(&henv))) || (henv == SQL_NULL_HENV)) {
- rb_raise(Cerror, set_err("Cannot allocate SQLHENV", 0));
+ rb_raise(Cerror, "%s", set_err("Cannot allocate SQLHENV", 0));
}
obj = Data_Make_Struct(self, ENV, NULL, free_env, e);
tracemsg(2, fprintf(stderr, "ObjAlloc: ENV %p\n", e););
e->self = obj;
e->henv = henv;
@@ -1388,18 +1440,20 @@
&descrLen),
NULL, "SQLDataSources")) {
VALUE odsn = rb_obj_alloc(Cdsn);
#ifdef UNICODE
- dsnLen = (dsnLen == 0) ? uc_strlen(dsn) : (dsnLen / sizeof (SQLWCHAR));
+ dsnLen = (dsnLen == 0) ? (SQLSMALLINT) uc_strlen(dsn) :
+ (SQLSMALLINT) (dsnLen / sizeof (SQLWCHAR));
descrLen = (descrLen == 0) ?
- uc_strlen(descr) : (descrLen / sizeof (SQLWCHAR));
+ (SQLSMALLINT) uc_strlen(descr) :
+ (SQLSMALLINT) (descrLen / sizeof (SQLWCHAR));
rb_iv_set(odsn, "@name", uc_tainted_str_new(dsn, dsnLen));
rb_iv_set(odsn, "@descr", uc_tainted_str_new(descr, descrLen));
#else
- dsnLen = (dsnLen == 0) ? strlen(dsn) : dsnLen;
- descrLen = (descrLen == 0) ? strlen(descr) : descrLen;
+ dsnLen = (dsnLen == 0) ? (SQLSMALLINT) strlen(dsn) : dsnLen;
+ descrLen = (descrLen == 0) ? (SQLSMALLINT) strlen(descr) : descrLen;
rb_iv_set(odsn, "@name", rb_tainted_str_new(dsn, dsnLen));
rb_iv_set(odsn, "@descr", rb_tainted_str_new(descr, descrLen));
#endif
rb_ary_push(aret, odsn);
first = dsnLen = descrLen = 0;
@@ -1445,11 +1499,12 @@
VALUE h = rb_hash_new();
int count = 0;
#ifdef UNICODE
driverLen = (driverLen == 0) ?
- uc_strlen(driver) : (driverLen / sizeof (SQLWCHAR));
+ (SQLSMALLINT) uc_strlen(driver) :
+ (SQLSMALLINT) (driverLen / sizeof (SQLWCHAR));
rb_iv_set(odrv, "@name", uc_tainted_str_new(driver, driverLen));
for (attr = attrs; *attr; attr += uc_strlen(attr) + 1) {
SQLWCHAR *p = uc_strchr(attr, (SQLWCHAR) '=');
if ((p != NULL) && (p != attr)) {
@@ -1459,11 +1514,11 @@
uc_tainted_str_new2(p + 1));
count++;
}
}
#else
- driverLen = (driverLen == 0) ? strlen(driver) : driverLen;
+ driverLen = (driverLen == 0) ? (SQLSMALLINT) strlen(driver) : driverLen;
rb_iv_set(odrv, "@name", rb_tainted_str_new(driver, driverLen));
for (attr = attrs; *attr; attr += strlen(attr) + 1) {
char *p = strchr(attr, '=');
if ((p != NULL) && (p != attr)) {
@@ -1545,16 +1600,20 @@
#ifdef UNICODE
#ifdef USE_DLOPEN_FOR_ODBC_LIBS
have_w = ruby_odbc_have_func("SQLConfigDataSourceW", SQLConfigDataSourceW);
#endif
if (have_w) {
+#ifdef USE_RB_ENC
+ drv = rb_funcall(drv, IDencode, 1, rb_encv);
+ astr = rb_funcall(astr, IDencode, 1, rb_encv);
+#endif
sdrv = uc_from_utf((unsigned char *) STR2CSTR(drv), -1);
sastr = uc_from_utf((unsigned char *) STR2CSTR(astr), -1);
if ((sdrv == NULL) || (sastr == NULL)) {
uc_free(sdrv);
uc_free(sastr);
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
if (SQLConfigDataSourceW(NULL, (WORD) op,
(LPWSTR) sdrv, (LPWSTR) sastr)) {
uc_free(sdrv);
uc_free(sastr);
@@ -1576,13 +1635,13 @@
if (SQLConfigDataSource(NULL, (WORD) op, sdrv, sastr)) {
return Qnil;
}
#endif
#if defined(HAVE_SQLINSTALLERERROR) || (defined(UNICODE) && defined(HAVE_SQLINSTALLERERRORW))
- rb_raise(Cerror, set_err(get_installer_err(), 0));
+ rb_raise(Cerror, "%s", set_err(get_installer_err(), 0));
#else
- rb_raise(Cerror, set_err("DSN configuration error", 0));
+ rb_raise(Cerror, "%s", set_err("DSN configuration error", 0));
#endif
return Qnil;
}
#endif
@@ -1590,33 +1649,33 @@
dbc_adddsn(int argc, VALUE *argv, VALUE self)
{
#ifdef HAVE_ODBCINST_H
return conf_dsn(argc, argv, self, ODBC_ADD_DSN);
#else
- rb_raise(Cerror, set_err("ODBC::add_dsn not supported", 0));
+ rb_raise(Cerror, "%s", set_err("ODBC::add_dsn not supported", 0));
return Qnil;
#endif
}
static VALUE
dbc_confdsn(int argc, VALUE *argv, VALUE self)
{
#ifdef HAVE_ODBCINST_H
return conf_dsn(argc, argv, self, ODBC_CONFIG_DSN);
#else
- rb_raise(Cerror, set_err("ODBC::config_dsn not supported", 0));
+ rb_raise(Cerror, "%s", set_err("ODBC::config_dsn not supported", 0));
return Qnil;
#endif
}
static VALUE
dbc_deldsn(int argc, VALUE *argv, VALUE self)
{
#ifdef HAVE_ODBCINST_H
return conf_dsn(argc, argv, self, ODBC_REMOVE_DSN);
#else
- rb_raise(Cerror, set_err("ODBC::del_dsn not supported", 0));
+ rb_raise(Cerror, "%s", set_err("ODBC::del_dsn not supported", 0));
return Qnil;
#endif
}
static VALUE
@@ -1647,19 +1706,27 @@
have_w = ruby_odbc_have_func("SQLWriteFileDSNW", SQLWriteFileDSNW);
#endif
if (have_w) {
BOOL rc;
+#ifdef USE_RB_ENC
+ fname = rb_funcall(fname, IDencode, 1, rb_encv);
+ aname = rb_funcall(aname, IDencode, 1, rb_encv);
+ kname = rb_funcall(kname, IDencode, 1, rb_encv);
+ if (val != Qnil) {
+ val = rb_funcall(val, IDencode, 1, rb_encv);
+ }
+#endif
sfname = uc_from_utf((unsigned char *) STR2CSTR(fname), -1);
saname = uc_from_utf((unsigned char *) STR2CSTR(aname), -1);
skname = uc_from_utf((unsigned char *) STR2CSTR(kname), -1);
if ((sfname == NULL) || (saname == NULL) || (skname == NULL)) {
nomem:
uc_free(sfname);
uc_free(saname);
uc_free(skname);
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
if (val != Qnil) {
sval = uc_from_utf((unsigned char *) STR2CSTR(val), -1);
if (sval == NULL) {
goto nomem;
@@ -1695,16 +1762,16 @@
if (SQLWriteFileDSN(sfname, saname, skname, sval)) {
return Qnil;
}
#endif
#if defined(HAVE_SQLINSTALLERERROR) || (defined(UNICODE) && defined(HAVE_SQLINSTALLERERRORW))
- rb_raise(Cerror, set_err(get_installer_err(), 0));
+ rb_raise(Cerror, "%s", set_err(get_installer_err(), 0));
#else
- rb_raise(Cerror, set_err("File DSN configuration error", 0));
+ rb_raise(Cerror, "%s", set_err("File DSN configuration error", 0));
#endif
#else
- rb_raise(Cerror, set_err("ODBC::write_file_dsn not supported", 0));
+ rb_raise(Cerror, "%s", set_err("ODBC::write_file_dsn not supported", 0));
#endif
return Qnil;
}
static VALUE
@@ -1732,19 +1799,24 @@
have_w = ruby_odbc_have_func("SQLReadFileDSNW", SQLReadFileDSNW);
#endif
if (have_w) {
BOOL rc;
+#ifdef USE_RB_ENC
+ fname = rb_funcall(fname, IDencode, 1, rb_encv);
+ aname = rb_funcall(aname, IDencode, 1, rb_encv);
+ kname = rb_funcall(kname, IDencode, 1, rb_encv);
+#endif
sfname = uc_from_utf((unsigned char *) STR2CSTR(fname), -1);
saname = uc_from_utf((unsigned char *) STR2CSTR(aname), -1);
skname = uc_from_utf((unsigned char *) STR2CSTR(kname), -1);
valbuf[0] = 0;
if ((sfname == NULL) || (saname == NULL) || (skname == NULL)) {
uc_free(sfname);
uc_free(saname);
uc_free(skname);
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
rc = SQLReadFileDSNW(sfname, saname, skname, valbuf,
sizeof (valbuf), NULL);
uc_free(sfname);
uc_free(saname);
@@ -1772,16 +1844,16 @@
sizeof (valbuf), NULL)) {
return rb_tainted_str_new2(valbuf);
}
#endif
#if defined(HAVE_SQLINSTALLERERROR) || (defined(UNICODE) && defined(HAVE_SQLINSTALLERERRORW))
- rb_raise(Cerror, set_err(get_installer_err(), 0));
+ rb_raise(Cerror, "%s", set_err(get_installer_err(), 0));
#else
- rb_raise(Cerror, set_err("File DSN configuration error", 0));
+ rb_raise(Cerror, "%s", set_err("File DSN configuration error", 0));
#endif
#else
- rb_raise(Cerror, set_err("ODBC::read_file_dsn not supported", 0));
+ rb_raise(Cerror, "%s", set_err("ODBC::read_file_dsn not supported", 0));
return Qnil;
#endif
}
/*
@@ -1832,10 +1904,12 @@
p->self = obj;
p->env = Qnil;
p->envp = NULL;
list_init(&p->stmts, offsetof(STMT, link));
p->hdbc = SQL_NULL_HDBC;
+ p->rbtime = Qfalse;
+ p->gmtime = Qfalse;
return obj;
}
#endif
static VALUE
@@ -1916,11 +1990,11 @@
if (passwd != Qnil) {
Check_Type(passwd, T_STRING);
}
p = get_dbc(self);
if (p->hdbc != SQL_NULL_HDBC) {
- rb_raise(Cerror, set_err("Already connected", 0));
+ rb_raise(Cerror, "%s", set_err("Already connected", 0));
}
if (p->env == Qnil) {
p->env = env_new(Cenv);
e = get_env(p->env);
link_dbc(p, e);
@@ -1930,23 +2004,32 @@
if (dsn == Qnil) {
return self;
}
#ifdef UNICODE
if (user != Qnil) {
+#ifdef USE_RB_ENC
+ user = rb_funcall(user, IDencode, 1, rb_encv);
+#endif
suser = uc_from_utf((unsigned char *) STR2CSTR(user), -1);
}
if (passwd != Qnil) {
+#ifdef USE_RB_ENC
+ passwd = rb_funcall(passwd, IDencode, 1, rb_encv);
+#endif
spasswd = uc_from_utf((unsigned char *) STR2CSTR(passwd), -1);
}
+#ifdef USE_RB_ENC
+ dsn = rb_funcall(dsn, IDencode, 1, rb_encv);
+#endif
sdsn = uc_from_utf((unsigned char *) STR2CSTR(dsn), -1);
if (((suser == NULL) && (user != Qnil)) ||
((spasswd == NULL) && (passwd != Qnil)) ||
(sdsn == NULL)) {
uc_free(sdsn);
uc_free(suser);
uc_free(spasswd);
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
#else
if (user != Qnil) {
suser = STR2CSTR(user);
}
@@ -2019,23 +2102,26 @@
drv = d;
}
Check_Type(drv, T_STRING);
p = get_dbc(self);
if (p->hdbc != SQL_NULL_HDBC) {
- rb_raise(Cerror, set_err("Already connected", 0));
+ rb_raise(Cerror, "%s", set_err("Already connected", 0));
}
if (p->env == Qnil) {
p->env = env_new(Cenv);
e = get_env(p->env);
link_dbc(p, e);
} else {
e = get_env(p->env);
}
#ifdef UNICODE
+#ifdef USE_RB_ENC
+ drv = rb_funcall(drv, IDencode, 1, rb_encv);
+#endif
sdrv = uc_from_utf((unsigned char *) STR2CSTR(drv), -1);
if (sdrv == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
#else
sdrv = STR2CSTR(drv);
#endif
if (!succeeded(e->henv, SQL_NULL_HDBC, SQL_NULL_HSTMT,
@@ -2068,10 +2154,36 @@
{
DBC *p = get_dbc(self);
return (p->hdbc == SQL_NULL_HDBC) ? Qfalse : Qtrue;
}
+
+static VALUE
+dbc_timefmt(int argc, VALUE *argv, VALUE self)
+{
+ DBC *p = get_dbc(self);
+ VALUE val;
+
+ if (argc > 0) {
+ rb_scan_args(argc, argv, "1", &val);
+ p->rbtime = (val != Qnil && val != Qfalse) ? Qtrue : Qfalse;
+ }
+ return p->rbtime;
+}
+
+static VALUE
+dbc_timeutc(int argc, VALUE *argv, VALUE self)
+{
+ DBC *p = get_dbc(self);
+ VALUE val;
+
+ if (argc > 0) {
+ rb_scan_args(argc, argv, "1", &val);
+ p->gmtime = (val != Qnil && val != Qfalse) ? Qtrue : Qfalse;
+ }
+ return p->gmtime;
+}
/*
*----------------------------------------------------------------------
*
* Drop all active statements from data source.
@@ -2910,20 +3022,23 @@
static VALUE
dbc_getinfo(int argc, VALUE *argv, VALUE self)
{
DBC *p = get_dbc(self);
- VALUE which, vtype;
+ VALUE which, vtype, vstr;
SQLRETURN ret;
int i, k, info = -1, maptype = -1, info_found = 0;
- char buffer[513], *string = NULL;
- SQLSMALLINT len_in = sizeof (buffer) - 1, len_out;
+ SQLUSMALLINT sbuffer;
+ SQLUINTEGER lbuffer;
+ SQLSMALLINT len_in, len_out;
+ char *string = NULL, buffer[513];
rb_scan_args(argc, argv, "11", &which, &vtype);
switch (TYPE(which)) {
default:
- string = STR2CSTR(rb_any_to_s(which));
+ vstr = rb_any_to_s(which);
+ string = STR2CSTR(vstr);
goto doString;
case T_STRING:
string = STR2CSTR(which);
doString:
for (i = 0; get_info_map[i].name != NULL; i++) {
@@ -2954,11 +3069,11 @@
}
break;
}
switch (info_found) {
case 0:
- rb_raise(Cerror,
+ rb_raise(Cerror, "%s",
set_err("Invalid info type for ODBC::Connection.get_info",
0));
return Qnil;
case 1:
sprintf(buffer, "Unknown info type %d for ODBC::Connection.get_info",
@@ -3004,22 +3119,40 @@
default:
maptype = SQL_C_CHAR;
break;
}
}
- memset(buffer, 0, sizeof (buffer));
- ret = SQLGetInfo(p->hdbc, (SQLUSMALLINT) info,
- (SQLPOINTER) buffer, len_in, &len_out);
+ switch (maptype) {
+ case SQL_C_SHORT:
+ len_in = sizeof (sbuffer);
+ sbuffer = 0;
+ ret = SQLGetInfo(p->hdbc, (SQLUSMALLINT) info,
+ (SQLPOINTER) &sbuffer, len_in, &len_out);
+ break;
+ case SQL_C_LONG:
+ len_in = sizeof (lbuffer);
+ lbuffer = 0;
+ ret = SQLGetInfo(p->hdbc, (SQLUSMALLINT) info,
+ (SQLPOINTER) &lbuffer, len_in, &len_out);
+ break;
+ default:
+ case SQL_C_CHAR:
+ len_in = sizeof (buffer) - 1;
+ memset(buffer, 0, sizeof (buffer));
+ ret = SQLGetInfo(p->hdbc, (SQLUSMALLINT) info,
+ (SQLPOINTER) buffer, len_in, &len_out);
+ break;
+ }
if (!SQL_SUCCEEDED(ret)) {
rb_raise(Cerror, "%s",
get_err(SQL_NULL_HENV, p->hdbc, SQL_NULL_HSTMT));
}
switch (maptype) {
case SQL_C_SHORT:
- return INT2NUM(*((SQLUSMALLINT *) buffer));
+ return INT2NUM(sbuffer);
case SQL_C_LONG:
- return INT2NUM(*((SQLUINTEGER *) buffer));
+ return INT2NUM(lbuffer);
default:
case SQL_C_CHAR:
return rb_str_new(buffer, len_out);
}
return Qnil;
@@ -3151,10 +3284,13 @@
size = sizeof (SQLBIGINT);
}
break;
#endif
default:
+ if ((size == 0) || (size > SEGSIZE)) {
+ size = SQL_NO_TOTAL;
+ }
#ifdef UNICODE
type = SQL_C_WCHAR;
if (size != SQL_NO_TOTAL) {
size *= sizeof (SQLWCHAR);
size += sizeof (SQLWCHAR);
@@ -3179,68 +3315,77 @@
* Fill parameter info array for statement.
*
*----------------------------------------------------------------------
*/
-static PINFO *
-make_pinfo(SQLHSTMT hstmt, int nump, char **msgp)
+static PARAMINFO *
+make_paraminfo(SQLHSTMT hstmt, int nump, char **msgp)
{
int i;
- PINFO *pinfo = NULL;
+ PARAMINFO *paraminfo = NULL;
- pinfo = ALLOC_N(PINFO, nump);
- if (pinfo == NULL) {
+ paraminfo = ALLOC_N(PARAMINFO, nump);
+ if (paraminfo == NULL) {
if (msgp != NULL) {
*msgp = set_err("Out of memory", 0);
}
return NULL;
}
for (i = 0; i < nump; i++) {
- pinfo[i].iotype = SQL_PARAM_INPUT;
- pinfo[i].outsize = 0;
- pinfo[i].outbuf = NULL;
- pinfo[i].rlen = SQL_NULL_DATA;
- pinfo[i].ctype = SQL_C_CHAR;
- pinfo[i].outtype = SQL_CHAR;
- pinfo[i].coldef_max = 0;
+ paraminfo[i].iotype = SQL_PARAM_INPUT;
+ paraminfo[i].outsize = 0;
+ paraminfo[i].outbuf = NULL;
+ paraminfo[i].rlen = SQL_NULL_DATA;
+ paraminfo[i].ctype = SQL_C_CHAR;
+#ifdef UNICODE
+ paraminfo[i].outtype = SQL_WCHAR;
+#else
+ paraminfo[i].outtype = SQL_WCHAR;
+#endif
+ paraminfo[i].coldef_max = 0;
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
SQLDescribeParam(hstmt, (SQLUSMALLINT) (i + 1),
- &pinfo[i].type, &pinfo[i].coldef,
- &pinfo[i].scale,
- &pinfo[i].nullable),
+ ¶minfo[i].type,
+ ¶minfo[i].coldef,
+ ¶minfo[i].scale,
+ ¶minfo[i].nullable),
NULL, "SQLDescribeParam")) {
- pinfo[i].type = SQL_VARCHAR;
- pinfo[i].coldef = 0;
- pinfo[i].scale = 0;
- pinfo[i].nullable = SQL_NULLABLE_UNKNOWN;
- pinfo[i].override = 0;
+#ifdef UNICODE
+ paraminfo[i].type = SQL_WVARCHAR;
+#else
+ paraminfo[i].type = SQL_VARCHAR;
+#endif
+ paraminfo[i].coldef = 0;
+ paraminfo[i].scale = 0;
+ paraminfo[i].nullable = SQL_NULLABLE_UNKNOWN;
+ paraminfo[i].override = 0;
}
}
- return pinfo;
+ return paraminfo;
}
static void
-retain_pinfo_override(STMT *q, int nump, PINFO *pinfo)
+retain_paraminfo_override(STMT *q, int nump, PARAMINFO *paraminfo)
{
- if ((q->pinfo != NULL) && (q->nump == nump)) {
+ if ((q->paraminfo != NULL) && (q->nump == nump)) {
int i;
for (i = 0; i < nump; i++) {
- pinfo[i].iotype = q->pinfo[i].iotype;
- pinfo[i].rlen = q->pinfo[i].rlen;
- pinfo[i].ctype = q->pinfo[i].ctype;
- pinfo[i].outtype = q->pinfo[i].outtype;
- pinfo[i].outsize = q->pinfo[i].outsize;
- if (q->pinfo[i].outbuf != NULL) {
- pinfo[i].outbuf = q->pinfo[i].outbuf;
- q->pinfo[i].outbuf = NULL;
+ paraminfo[i].iotype = q->paraminfo[i].iotype;
+ paraminfo[i].rlen = q->paraminfo[i].rlen;
+ paraminfo[i].ctype = q->paraminfo[i].ctype;
+ paraminfo[i].outtype = q->paraminfo[i].outtype;
+ paraminfo[i].outsize = q->paraminfo[i].outsize;
+ if (q->paraminfo[i].outbuf != NULL) {
+ paraminfo[i].outbuf = q->paraminfo[i].outbuf;
+ q->paraminfo[i].outbuf = NULL;
}
- if (q->pinfo[i].override) {
- pinfo[i].override = q->pinfo[i].override;
- pinfo[i].type = q->pinfo[i].type;
- pinfo[i].coldef = q->pinfo[i].coldef;
- pinfo[i].scale = q->pinfo[i].scale;
+ if (q->paraminfo[i].override) {
+ paraminfo[i].override = q->paraminfo[i].override;
+ paraminfo[i].type = q->paraminfo[i].type;
+ paraminfo[i].coldef = q->paraminfo[i].coldef;
+ paraminfo[i].scale = q->paraminfo[i].scale;
}
}
}
}
@@ -3263,19 +3408,25 @@
list_init(&q->link, offsetof(STMT, link));
q->self = stmt;
q->hstmt = hstmt;
q->dbc = dbc;
q->dbcp = NULL;
- q->pinfo = NULL;
+ q->paraminfo = NULL;
q->coltypes = NULL;
q->colnames = q->dbufs = NULL;
+ q->colvals = NULL;
q->fetchc = 0;
q->upc = p->upc;
q->usef = 0;
rb_iv_set(q->self, "@_a", rb_ary_new());
rb_iv_set(q->self, "@_h", rb_hash_new());
- link_stmt(q, p);
+ rb_iv_set(q->self, "@_c", rb_hash_new());
+ if (hstmt != SQL_NULL_HSTMT) {
+ link_stmt(q, p);
+ } else {
+ q->dbc = Qnil;
+ }
if (qp != NULL) {
*qp = q;
}
return stmt;
}
@@ -3293,25 +3444,27 @@
{
DBC *p;
STMT *q;
SQLSMALLINT cols = 0, nump;
COLTYPE *coltypes = NULL;
- PINFO *pinfo = NULL;
+ PARAMINFO *paraminfo = NULL;
char *msg = NULL;
Data_Get_Struct(dbc, DBC, p);
- if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
+ if ((hstmt == SQL_NULL_HSTMT) ||
+ !succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
SQLNumParams(hstmt, &nump), NULL, "SQLNumParams")) {
nump = 0;
}
if (nump > 0) {
- pinfo = make_pinfo(hstmt, nump, &msg);
- if (pinfo == NULL) {
+ paraminfo = make_paraminfo(hstmt, nump, &msg);
+ if (paraminfo == NULL) {
goto error;
}
}
if ((mode & MAKERES_PREPARE) ||
+ (hstmt == SQL_NULL_HSTMT) ||
(!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
SQLNumResultCols(hstmt, &cols), NULL,
"SQLNumResultCols"))) {
cols = 0;
}
@@ -3323,21 +3476,23 @@
}
if (result == Qnil) {
result = wrap_stmt(dbc, p, hstmt, &q);
} else {
Data_Get_Struct(result, STMT, q);
- retain_pinfo_override(q, nump, pinfo);
+ retain_paraminfo_override(q, nump, paraminfo);
free_stmt_sub(q);
if (q->dbc != dbc) {
unlink_stmt(q);
q->dbc = dbc;
- link_stmt(q, p);
+ if (hstmt != SQL_NULL_HSTMT) {
+ link_stmt(q, p);
+ }
}
q->hstmt = hstmt;
}
q->nump = nump;
- q->pinfo = pinfo;
+ q->paraminfo = paraminfo;
q->ncols = cols;
q->coltypes = coltypes;
if ((mode & MAKERES_BLOCK) && rb_block_given_p()) {
if (mode & MAKERES_NOCLOSE) {
return rb_yield(result);
@@ -3353,12 +3508,12 @@
if (q->hstmt == hstmt) {
q->hstmt = SQL_NULL_HSTMT;
unlink_stmt(q);
}
}
- if (pinfo != NULL) {
- xfree(pinfo);
+ if (paraminfo != NULL) {
+ xfree(paraminfo);
}
if (coltypes != NULL) {
xfree(coltypes);
}
rb_raise(Cerror, "%s", msg);
@@ -3393,11 +3548,11 @@
*
*----------------------------------------------------------------------
*/
static VALUE
-make_col(SQLHSTMT hstmt, int i, int upc)
+make_column(SQLHSTMT hstmt, int i, int upc)
{
VALUE obj, v;
SQLUSMALLINT ic = i + 1;
SQLLEN iv = 0;
#ifdef UNICODE
@@ -3415,28 +3570,33 @@
&name_len, NULL),
&msg, "SQLColAttributes(SQL_COLUMN_LABEL)")) {
rb_raise(Cerror, "%s", msg);
}
obj = rb_obj_alloc(Ccolumn);
- if (name_len >= sizeof (name)) {
+ if (name_len >= (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
#ifdef UNICODE
if (upc) {
int len = uc_strlen(name);
char tmpbuf[1];
char *tmp = xmalloc(len);
+ VALUE v;
if (tmp == NULL) {
tmp = tmpbuf;
len = 0;
}
mkutf(tmp, name, len);
- rb_iv_set(obj, "@name", rb_tainted_str_new2(upcase_if(tmp, 1)));
+ v = rb_tainted_str_new2(upcase_if(tmp, 1));
+#ifdef USE_RB_ENC
+ rb_enc_associate(v, rb_enc);
+#endif
+ rb_iv_set(obj, "@name", v);
if ((tmp != NULL) && (tmp != tmpbuf)) {
xfree(tmp);
}
} else {
rb_iv_set(obj, "@name", uc_tainted_str_new2(name));
@@ -3449,11 +3609,11 @@
if (succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
SQLColAttributes(hstmt, ic, SQL_COLUMN_TABLE_NAME, name,
(SQLSMALLINT) sizeof (name),
&name_len, NULL),
NULL, "SQLColAttributes(SQL_COLUMN_TABLE_NAME)")) {
- if (name_len > sizeof (name)) {
+ if (name_len > (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
@@ -3558,29 +3718,37 @@
*
*----------------------------------------------------------------------
*/
static VALUE
-make_par(STMT *q, int i)
+make_param(STMT *q, int i)
{
VALUE obj;
int v;
obj = rb_obj_alloc(Cparam);
- v = q->pinfo ? q->pinfo[i].type : SQL_VARCHAR;
+#ifdef UNICODE
+ v = q->paraminfo ? q->paraminfo[i].type : SQL_VARCHAR;
+#else
+ v = q->paraminfo ? q->paraminfo[i].type : SQL_WVARCHAR;
+#endif
rb_iv_set(obj, "@type", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].coldef : 0;
+ v = q->paraminfo ? q->paraminfo[i].coldef : 0;
rb_iv_set(obj, "@precision", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].scale : 0;
+ v = q->paraminfo ? q->paraminfo[i].scale : 0;
rb_iv_set(obj, "@scale", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].nullable : SQL_NULLABLE_UNKNOWN;
+ v = q->paraminfo ? q->paraminfo[i].nullable : SQL_NULLABLE_UNKNOWN;
rb_iv_set(obj, "@nullable", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].iotype : SQL_PARAM_INPUT;
+ v = q->paraminfo ? q->paraminfo[i].iotype : SQL_PARAM_INPUT;
rb_iv_set(obj, "@iotype", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].outsize : 0;
+ v = q->paraminfo ? q->paraminfo[i].outsize : 0;
rb_iv_set(obj, "@output_size", INT2NUM(v));
- v = q->pinfo ? q->pinfo[i].outtype : SQL_CHAR;
+#ifdef UNICODE
+ v = q->paraminfo ? q->paraminfo[i].outtype : SQL_WCHAR;
+#else
+ v = q->paraminfo ? q->paraminfo[i].outtype : SQL_CHAR;
+#endif
rb_iv_set(obj, "@output_type", INT2NUM(v));
return obj;
}
/*
@@ -3599,17 +3767,18 @@
#ifdef UNICODE
SQLWCHAR *swhich = NULL, *swhich2 = NULL;
#else
SQLCHAR *swhich = NULL, *swhich2 = NULL;
#endif
- char *msg, *argspec = NULL;
+ char *msg;
+ const char *argspec = NULL;
SQLHSTMT hstmt;
int needstr = 1, itype = SQL_ALL_TYPES;
int iid = SQL_BEST_ROWID, iscope = SQL_SCOPE_CURROW;
if (p->hdbc == SQL_NULL_HDBC) {
- rb_raise(Cerror, set_err("No connection", 0));
+ rb_raise(Cerror, "%s", set_err("No connection", 0));
}
switch (mode) {
case INFO_TYPES:
needstr = 0;
/* FALL THRU */
@@ -3629,11 +3798,11 @@
break;
case INFO_SPECCOLS:
argspec = "12";
break;
default:
- rb_raise(Cerror, set_err("Invalid info mode", 0));
+ rb_raise(Cerror, "%s", set_err("Invalid info mode", 0));
break;
}
rb_scan_args(argc, argv, argspec, &which, &which2, &which3);
if (which != Qnil) {
if (needstr) {
@@ -3659,20 +3828,30 @@
#endif
}
}
#ifdef UNICODE
if (swhich != NULL) {
- swhich = uc_from_utf((unsigned char *) STR2CSTR((VALUE) swhich), -1);
+ VALUE val = (VALUE) swhich;
+
+#ifdef USE_RB_ENC
+ val = rb_funcall(val, IDencode, 1, rb_encv);
+#endif
+ swhich = uc_from_utf((unsigned char *) STR2CSTR(val), -1);
if (swhich == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
}
if (swhich2 != NULL) {
- swhich2 = uc_from_utf((unsigned char *) STR2CSTR((VALUE) swhich2), -1);
+ VALUE val = (VALUE) swhich2;
+
+#ifdef USE_RB_ENC
+ val = rb_funcall(val, IDencode, 1, rb_encv);
+#endif
+ swhich2 = uc_from_utf((unsigned char *) STR2CSTR(val), -1);
if (swhich2 == NULL) {
uc_free(swhich);
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
}
#endif
if (which3 != Qnil) {
iscope = NUM2INT(which3);
@@ -3997,22 +4176,22 @@
env_cpooling(int argc, VALUE *argv, VALUE self)
{
#if (ODBCVER >= 0x0300)
return do_attr(argc, argv, self, SQL_ATTR_CONNECTION_POOLING);
#else
- rb_raise(Cerror, set_err("Unsupported in ODBC < 3.0", 0));
+ rb_raise(Cerror, "%s", set_err("Unsupported in ODBC < 3.0", 0));
return Qnil;
#endif
}
static VALUE
env_cpmatch(int argc, VALUE *argv, VALUE self)
{
#if (ODBCVER >= 0x0300)
return do_attr(argc, argv, self, SQL_ATTR_CP_MATCH);
#else
- rb_raise(Cerror, set_err("Unsupported in ODBC < 3.0", 0));
+ rb_raise(Cerror, "%s", set_err("Unsupported in ODBC < 3.0", 0));
return Qnil;
#endif
}
static VALUE
@@ -4025,11 +4204,11 @@
rb_scan_args(argc, argv, "01", &val);
if (val == Qnil) {
return rb_int2inum(ODBCVER >> 8);
}
- rb_raise(Cerror, set_err("Unsupported in ODBC < 3.0", 0));
+ rb_raise(Cerror, "%s", set_err("Unsupported in ODBC < 3.0", 0));
#endif
}
/*
*----------------------------------------------------------------------
@@ -4054,11 +4233,11 @@
#define OPT_LEVEL_BOTH (OPT_LEVEL_STMT | OPT_LEVEL_DBC)
#define OPT_CONST_INT(x, level) { #x, x, level }
#define OPT_CONST_END { NULL, -1 }
static struct {
- char *name;
+ const char *name;
int option;
int level;
} option_map[] = {
/* yielding ints */
@@ -4078,37 +4257,38 @@
static VALUE
do_option(int argc, VALUE *argv, VALUE self, int isstmt, int op)
{
DBC *p = NULL;
STMT *q = NULL;
- VALUE val, val2;
+ VALUE val, val2, vstr;
SQLINTEGER v;
char *msg;
int level = isstmt ? OPT_LEVEL_STMT : OPT_LEVEL_DBC;
rb_scan_args(argc, argv, (op == -1) ? "11" : "01", &val, &val2);
if (isstmt) {
Data_Get_Struct(self, STMT, q);
if (q->dbc == Qnil) {
- rb_raise(Cerror, set_err("Stale ODBC::Statement", 0));
+ rb_raise(Cerror, "%s", set_err("Stale ODBC::Statement", 0));
}
if (q->hstmt == SQL_NULL_HSTMT) {
- rb_raise(Cerror, set_err("No statement", 0));
+ rb_raise(Cerror, "%s", set_err("No statement", 0));
}
} else {
p = get_dbc(self);
if (p->hdbc == SQL_NULL_HDBC) {
- rb_raise(Cerror, set_err("No connection", 0));
+ rb_raise(Cerror, "%s", set_err("No connection", 0));
}
}
if (op == -1) {
char *string;
int i, op_found = 0;
switch (TYPE(val)) {
default:
- string = STR2CSTR(rb_any_to_s(val));
+ vstr = rb_any_to_s(val);
+ string = STR2CSTR(vstr);
goto doString;
case T_STRING:
string = STR2CSTR(val);
doString:
for (i = 0; option_map[i].name != NULL; i++) {
@@ -4136,18 +4316,19 @@
}
}
break;
}
if (!op_found) {
- rb_raise(Cerror, set_err("Unknown option", 0));
+ rb_raise(Cerror, "%s", set_err("Unknown option", 0));
return Qnil;
}
val = val2;
}
if ((isstmt && (!(level & OPT_LEVEL_STMT))) ||
(!isstmt && (!(level & OPT_LEVEL_DBC)))) {
- rb_raise(Cerror, set_err("Invalid option type for this level", 0));
+ rb_raise(Cerror, "%s",
+ set_err("Invalid option type for this level", 0));
return Qnil;
}
if (val == Qnil) {
if (p != NULL) {
if (!succeeded(SQL_NULL_HENV, p->hdbc, SQL_NULL_HSTMT,
@@ -4195,11 +4376,11 @@
return rb_int2inum(v);
}
Check_Type(val, T_FIXNUM);
v = FIX2INT(val);
if (op == SQL_ROWSET_SIZE) {
- rb_raise(Cerror, set_err("Read only attribute", 0));
+ rb_raise(Cerror, "%s", set_err("Read only attribute", 0));
}
break;
}
if (p != NULL) {
if (!succeeded(SQL_NULL_HENV, p->hdbc, SQL_NULL_HSTMT,
@@ -4368,11 +4549,11 @@
}
ff = ss = 0;
i = sscanf(cstr, "%d-%d-%d %d:%d:%d%c%d",
&yy, &mm, &dd, &hh, &mmm, &ss, &c, &ff);
if (i >= 5) {
- if ((i > 6) && (strchr(". \t", c) == NULL)) {
+ if ((i > 6) && (c != 0) && (strchr(". \t", c) == NULL)) {
goto next;
}
ts->year = yy;
ts->month = mm;
ts->day = dd;
@@ -5292,11 +5473,11 @@
static VALUE
stmt_nrows(VALUE self)
{
STMT *q;
- SQLLEN rows = 0;
+ SQLLEN rows = -1;
char *msg;
Data_Get_Struct(self, STMT, q);
if ((q->hstmt != SQL_NULL_HSTMT) &&
(!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
@@ -5314,42 +5495,42 @@
Data_Get_Struct(self, STMT, q);
return INT2FIX(q->nump);
}
static int
-param_num_check(STMT *q, VALUE pnum, int mkpinfo, int needout)
+param_num_check(STMT *q, VALUE pnum, int mkparaminfo, int needout)
{
int vnum;
Check_Type(pnum, T_FIXNUM);
vnum = NUM2INT(pnum);
- if (mkpinfo && (q->pinfo == NULL)) {
+ if (mkparaminfo && (q->paraminfo == NULL)) {
char *msg = NULL;
SQLSMALLINT nump = 0;
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLNumParams(q->hstmt, &nump), NULL, "SQLNumParams")) {
nump = 0;
}
if (nump > 0) {
- PINFO *pinfo = make_pinfo(q->hstmt, nump, &msg);
+ PARAMINFO *paraminfo = make_paraminfo(q->hstmt, nump, &msg);
- if (pinfo == NULL) {
+ if (paraminfo == NULL) {
rb_raise(Cerror, "%s", msg);
}
- q->pinfo = pinfo;
- if (q->pinfo != NULL) {
+ q->paraminfo = paraminfo;
+ if (q->paraminfo != NULL) {
q->nump = nump;
}
}
}
- if ((q->pinfo == NULL) || (vnum < 0) || (vnum >= q->nump)) {
+ if ((q->paraminfo == NULL) || (vnum < 0) || (vnum >= q->nump)) {
rb_raise(rb_eArgError, "parameter number out of bounds");
}
if (needout) {
- if ((q->pinfo[vnum].iotype != SQL_PARAM_OUTPUT) &&
- (q->pinfo[vnum].iotype != SQL_PARAM_INPUT_OUTPUT)) {
+ if ((q->paraminfo[vnum].iotype != SQL_PARAM_OUTPUT) &&
+ (q->paraminfo[vnum].iotype != SQL_PARAM_INPUT_OUTPUT)) {
rb_raise(Cerror, "not an output parameter");
}
}
return vnum;
}
@@ -5373,19 +5554,19 @@
Check_Type(pcoldef, T_FIXNUM);
vcoldef = NUM2INT(pcoldef);
if (argc > 3) {
Check_Type(pscale, T_FIXNUM);
vscale = NUM2INT(pscale);
- q->pinfo[vnum].scale = vscale;
+ q->paraminfo[vnum].scale = vscale;
}
- q->pinfo[vnum].coldef = vcoldef;
+ q->paraminfo[vnum].coldef = vcoldef;
}
- q->pinfo[vnum].type = vtype;
- q->pinfo[vnum].override = 1;
+ q->paraminfo[vnum].type = vtype;
+ q->paraminfo[vnum].override = 1;
return Qnil;
}
- return INT2NUM(q->pinfo[vnum].type);
+ return INT2NUM(q->paraminfo[vnum].type);
}
static VALUE
stmt_param_iotype(int argc, VALUE *argv, VALUE self)
{
@@ -5401,15 +5582,15 @@
viotype = NUM2INT(piotype);
switch (viotype) {
case SQL_PARAM_INPUT:
case SQL_PARAM_INPUT_OUTPUT:
case SQL_PARAM_OUTPUT:
- q->pinfo[vnum].iotype = viotype;
+ q->paraminfo[vnum].iotype = viotype;
break;
}
}
- return INT2NUM(q->pinfo[vnum].iotype);
+ return INT2NUM(q->paraminfo[vnum].iotype);
}
static VALUE
stmt_param_output_value(int argc, VALUE *argv, VALUE self)
{
@@ -5419,56 +5600,105 @@
rb_scan_args(argc, argv, "10", &pnum);
Data_Get_Struct(self, STMT, q);
vnum = param_num_check(q, pnum, 0, 1);
v = Qnil;
- if (q->pinfo[vnum].rlen == SQL_NULL_DATA) {
+ if (q->paraminfo[vnum].rlen == SQL_NULL_DATA) {
return v;
}
- if (q->pinfo[vnum].outbuf == NULL) {
+ if (q->paraminfo[vnum].outbuf == NULL) {
rb_raise(Cerror, "no output value available");
}
- switch (q->pinfo[vnum].ctype) {
+ switch (q->paraminfo[vnum].ctype) {
case SQL_C_LONG:
- v = INT2NUM(*((SQLINTEGER *) q->pinfo[vnum].outbuf));
+ v = INT2NUM(*((SQLINTEGER *) q->paraminfo[vnum].outbuf));
break;
case SQL_C_DOUBLE:
- v = rb_float_new(*((double *) q->pinfo[vnum].outbuf));
+ v = rb_float_new(*((double *) q->paraminfo[vnum].outbuf));
break;
case SQL_C_DATE:
{
DATE_STRUCT *date;
- v = Data_Make_Struct(Cdate, DATE_STRUCT, 0, xfree, date);
- *date = *((DATE_STRUCT *) q->pinfo[vnum].outbuf);
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ const char *p;
+ char buffer[128];
+ VALUE d;
+
+ date = (DATE_STRUCT *) q->paraminfo[vnum].outbuf;
+ p = (q->dbcp->gmtime == Qtrue) ? "+00:00" : "";
+ sprintf(buffer, "%d-%d-%dT00:00:00%s",
+ date->year, date->month, date->day, p);
+ d = rb_str_new2(buffer);
+ v = rb_funcall(rb_cDate, IDparse, 1, d);
+ } else {
+ v = Data_Make_Struct(Cdate, DATE_STRUCT, 0, xfree, date);
+ *date = *((DATE_STRUCT *) q->paraminfo[vnum].outbuf);
+ }
}
break;
case SQL_C_TIME:
{
TIME_STRUCT *time;
- v = Data_Make_Struct(Ctime, TIME_STRUCT, 0, xfree, time);
- *time = *((TIME_STRUCT *) q->pinfo[vnum].outbuf);
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ VALUE now, frac;
+
+ time = (TIME_STRUCT *) q->paraminfo[vnum].outbuf;
+ frac = rb_float_new(0.0);
+ now = rb_funcall(rb_cTime, IDnow, 0, NULL);
+ v = rb_funcall(rb_cTime,
+ (q->dbcp->gmtime == Qtrue) ? IDutc : IDlocal,
+ 7,
+ rb_funcall(now, IDyear, 0, NULL),
+ rb_funcall(now, IDmonth, 0, NULL),
+ rb_funcall(now, IDday, 0, NULL),
+ INT2NUM(time->hour),
+ INT2NUM(time->minute),
+ INT2NUM(time->second),
+ frac);
+ } else {
+ v = Data_Make_Struct(Ctime, TIME_STRUCT, 0, xfree, time);
+ *time = *((TIME_STRUCT *) q->paraminfo[vnum].outbuf);
+ }
}
break;
case SQL_C_TIMESTAMP:
{
TIMESTAMP_STRUCT *ts;
- v = Data_Make_Struct(Ctimestamp, TIMESTAMP_STRUCT,
- 0, xfree, ts);
- *ts = *((TIMESTAMP_STRUCT *) q->pinfo[vnum].outbuf);
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ VALUE frac;
+
+ ts = (TIMESTAMP_STRUCT *) q->paraminfo[vnum].outbuf;
+ frac = rb_float_new((double) 1.0e-3 * ts->fraction);
+ v = rb_funcall(rb_cTime,
+ (q->dbcp->gmtime == Qtrue) ? IDutc : IDlocal,
+ 7,
+ INT2NUM(ts->year),
+ INT2NUM(ts->month),
+ INT2NUM(ts->day),
+ INT2NUM(ts->hour),
+ INT2NUM(ts->minute),
+ INT2NUM(ts->second),
+ frac);
+ } else {
+ v = Data_Make_Struct(Ctimestamp, TIMESTAMP_STRUCT,
+ 0, xfree, ts);
+ *ts = *((TIMESTAMP_STRUCT *) q->paraminfo[vnum].outbuf);
+ }
}
break;
#ifdef UNICODE
case SQL_C_WCHAR:
- v = uc_tainted_str_new((SQLWCHAR *) q->pinfo[vnum].outbuf,
- q->pinfo[vnum].rlen / sizeof (SQLWCHAR));
+ v = uc_tainted_str_new((SQLWCHAR *) q->paraminfo[vnum].outbuf,
+ q->paraminfo[vnum].rlen / sizeof (SQLWCHAR));
break;
#endif
case SQL_C_CHAR:
- v = rb_tainted_str_new(q->pinfo[vnum].outbuf, q->pinfo[vnum].rlen);
+ v = rb_tainted_str_new(q->paraminfo[vnum].outbuf,
+ q->paraminfo[vnum].rlen);
break;
}
return v;
}
@@ -5483,16 +5713,16 @@
Data_Get_Struct(self, STMT, q);
vnum = param_num_check(q, pnum, 0, 1);
if (argc > 1) {
Check_Type(psize, T_FIXNUM);
vsize = NUM2INT(psize);
- if ((vsize > 0) && (vsize < 4 * sizeof (double))) {
+ if ((vsize > 0) && (vsize < (int) (4 * sizeof (double)))) {
vsize = 4 * sizeof (double);
}
- q->pinfo[vnum].outsize = (vsize > 0) ? vsize : 0;
+ q->paraminfo[vnum].outsize = (vsize > 0) ? vsize : 0;
}
- return INT2NUM(q->pinfo[vnum].outsize);
+ return INT2NUM(q->paraminfo[vnum].outsize);
}
static VALUE
stmt_param_output_type(int argc, VALUE *argv, VALUE self)
{
@@ -5504,13 +5734,13 @@
Data_Get_Struct(self, STMT, q);
vnum = param_num_check(q, pnum, 0, 1);
if (argc > 1) {
Check_Type(ptype, T_FIXNUM);
vtype = NUM2INT(ptype);
- q->pinfo[vnum].outtype = vtype;
+ q->paraminfo[vnum].outtype = vtype;
}
- return INT2NUM(q->pinfo[vnum].outtype);
+ return INT2NUM(q->paraminfo[vnum].outtype);
}
static VALUE
stmt_cursorname(int argc, VALUE *argv, VALUE self)
{
@@ -5534,24 +5764,28 @@
(SQLSMALLINT) sizeof (cname), &cnLen),
&msg, "SQLGetCursorName")) {
rb_raise(Cerror, "%s", msg);
}
#ifdef UNICODE
- cnLen = (cnLen == 0) ? uc_strlen(cname) : (cnLen / sizeof (SQLWCHAR));
+ cnLen = (cnLen == 0) ? (SQLSMALLINT) uc_strlen(cname) :
+ (SQLSMALLINT) (cnLen / sizeof (SQLWCHAR));
return uc_tainted_str_new(cname, cnLen);
#else
- cnLen = (cnLen == 0) ? strlen((char *) cname) : cnLen;
+ cnLen = (cnLen == 0) ? (SQLSMALLINT) strlen((char *) cname) : cnLen;
return rb_tainted_str_new((char *) cname, cnLen);
#endif
}
if (TYPE(cn) != T_STRING) {
cn = rb_any_to_s(cn);
}
#ifdef UNICODE
+#ifdef USE_RB_ENC
+ cn = rb_funcall(cn, IDencode, 1, rb_encv);
+#endif
cp = uc_from_utf((unsigned char *) STR2CSTR(cn), -1);
if (cp == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
#else
cp = (SQLCHAR *) STR2CSTR(cn);
#endif
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
@@ -5576,11 +5810,11 @@
rb_scan_args(argc, argv, "1", &col);
Check_Type(col, T_FIXNUM);
Data_Get_Struct(self, STMT, q);
check_ncols(q);
- return make_col(q->hstmt, FIX2INT(col), q->upc);
+ return make_column(q->hstmt, FIX2INT(col), q->upc);
}
static VALUE
stmt_columns(int argc, VALUE *argv, VALUE self)
{
@@ -5591,11 +5825,11 @@
rb_scan_args(argc, argv, "01", &as_ary);
Data_Get_Struct(self, STMT, q);
check_ncols(q);
if (rb_block_given_p()) {
for (i = 0; i < q->ncols; i++) {
- rb_yield(make_col(q->hstmt, i, q->upc));
+ rb_yield(make_column(q->hstmt, i, q->upc));
}
return self;
}
if (RTEST(as_ary)) {
res = rb_ary_new2(q->ncols);
@@ -5603,11 +5837,11 @@
res = rb_hash_new();
}
for (i = 0; i < q->ncols; i++) {
VALUE obj;
- obj = make_col(q->hstmt, i, q->upc);
+ obj = make_column(q->hstmt, i, q->upc);
if (RTEST(as_ary)) {
rb_ary_store(res, i, obj);
} else {
VALUE name = rb_iv_get(obj, "@name");
@@ -5634,13 +5868,13 @@
rb_scan_args(argc, argv, "1", &par);
Check_Type(par, T_FIXNUM);
Data_Get_Struct(self, STMT, q);
i = FIX2INT(par);
if ((i < 0) || (i >= q->nump)) {
- rb_raise(Cerror, set_err("Parameter out of bounds", 0));
+ rb_raise(Cerror, "%s", set_err("Parameter out of bounds", 0));
}
- return make_par(q, i);
+ return make_param(q, i);
}
static VALUE
stmt_params(VALUE self)
{
@@ -5649,19 +5883,19 @@
VALUE res;
Data_Get_Struct(self, STMT, q);
if (rb_block_given_p()) {
for (i = 0; i < q->nump; i++) {
- rb_yield(make_par(q, i));
+ rb_yield(make_param(q, i));
}
return self;
}
res = rb_ary_new2(q->nump);
for (i = 0; i < q->nump; i++) {
VALUE obj;
- obj = make_par(q, i);
+ obj = make_param(q, i);
rb_ary_store(res, i, obj);
}
return res;
}
@@ -5671,11 +5905,11 @@
int i, offc;
char **bufs, *msg;
VALUE res;
if (q->ncols <= 0) {
- rb_raise(Cerror, set_err("No columns in result set", 0));
+ rb_raise(Cerror, "%s", set_err("No columns in result set", 0));
}
if (++q->fetchc >= 500) {
q->fetchc = 0;
start_gc();
}
@@ -5691,11 +5925,11 @@
need += LEN_ALIGN(q->coltypes[i].size);
}
}
p = ALLOC_N(char, need);
if (p == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
q->dbufs = bufs = (char **) p;
p += needp;
for (i = 0; i < q->ncols; i++) {
int len = q->coltypes[i].size;
@@ -5737,11 +5971,11 @@
&name_len, NULL),
&msg,
"SQLColAttributes(SQL_COLUMN_TABLE_NAME)")) {
rb_raise(Cerror, "%s", msg);
}
- if (name_len >= sizeof (name)) {
+ if (name_len >= (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
@@ -5762,11 +5996,11 @@
sizeof (name),
&name_len, NULL),
&msg, "SQLColAttributes(SQL_COLUMN_LABEL)")) {
rb_raise(Cerror, "%s", msg);
}
- if (name_len >= sizeof (name)) {
+ if (name_len >= (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
@@ -5781,11 +6015,11 @@
}
}
need += max_len[0] + max_len[1] + 32;
p = ALLOC_N(char, need);
if (p == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
na = (char **) p;
p += sizeof (char *) * 4 * q->ncols + sizeof (char *);
for (i = 0; i < q->ncols; i++) {
char *p0;
@@ -5794,11 +6028,11 @@
callsql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1),
SQL_COLUMN_TABLE_NAME, name,
sizeof (name), &name_len, NULL),
"SQLColAttributes(SQL_COLUMN_TABLE_NAME)");
- if (name_len >= sizeof (name)) {
+ if (name_len >= (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
@@ -5815,11 +6049,11 @@
callsql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1),
SQL_COLUMN_LABEL, name,
sizeof (name), &name_len, NULL),
"SQLColAttributes(SQL_COLUMN_LABEL)");
- if (name_len >= sizeof (name)) {
+ if (name_len >= (SQLSMALLINT) sizeof (name)) {
name_len = sizeof (name) - 1;
}
if (name_len > 0) {
name[name_len / sizeof (name[0])] = 0;
}
@@ -5837,10 +6071,46 @@
p += strlen(p) + 1;
}
/* reserved space for later adjustments */
na[4 * q->ncols] = p;
q->colnames = na;
+ if (q->colvals == NULL) {
+ q->colvals = ALLOC_N(VALUE, 4 * q->ncols);
+ if (q->colvals != NULL) {
+ VALUE cname;
+
+ for (i = 0; i < 4 * q->ncols; i++) {
+ q->colvals[i] = Qnil;
+ }
+ res = rb_iv_get(q->self, "@_c");
+ if (res == Qnil) {
+ res = rb_hash_new();
+ rb_iv_set(q->self, "@_c", res);
+ }
+ for (i = 0; i < 4 * q->ncols; i++) {
+ cname = rb_tainted_str_new2(q->colnames[i]);
+#ifdef USE_RB_ENC
+ rb_enc_associate(cname, rb_enc);
+#endif
+ q->colvals[i] = cname;
+ if (rb_funcall(res, IDkeyp, 1, cname) == Qtrue) {
+ char *p;
+
+ cname = rb_tainted_str_new2(q->colnames[i]);
+#ifdef USE_RB_ENC
+ rb_enc_associate(cname, rb_enc);
+#endif
+ p = q->colnames[4 * q->ncols];
+ sprintf(p, "#%d", i);
+ cname = rb_str_cat2(cname, p);
+ q->colvals[i] = cname;
+ }
+ rb_obj_freeze(cname);
+ rb_hash_aset(res, cname, Qtrue);
+ }
+ }
+ }
}
/* FALL THRU */
case DOFETCH_HASHN:
if (mode & DOFETCH_BANG) {
res = rb_iv_get(q->self, "@_h");
@@ -5864,19 +6134,25 @@
} else {
res = rb_ary_new2(q->ncols);
}
}
offc = q->upc ? (2 * q->ncols) : 0;
+ switch (mode & DOFETCH_MODES) {
+ case DOFETCH_HASHK2:
+ case DOFETCH_HASH2:
+ offc += q->ncols;
+ break;
+ }
for (i = 0; i < q->ncols; i++) {
- SQLLEN curlen, totlen;
+ SQLLEN totlen;
+ SQLLEN curlen = q->coltypes[i].size;
SQLSMALLINT type = q->coltypes[i].type;
VALUE v, name;
char *valp, *freep = NULL;
- curlen = q->coltypes[i].size;
if (curlen == SQL_NO_TOTAL) {
- SQLLEN chunksize = SEGSIZE;
+ SQLLEN chunksize = SEGSIZE;
totlen = 0;
#ifdef UNICODE
valp = ALLOC_N(char, chunksize + sizeof (SQLWCHAR));
#else
@@ -5889,11 +6165,12 @@
rc = SQLGetData(q->hstmt, (SQLUSMALLINT) (i + 1),
type, (SQLPOINTER) (valp + totlen),
#ifdef UNICODE
((type == SQL_C_CHAR) || (type == SQL_C_WCHAR)) ?
- (chunksize + sizeof (SQLWCHAR)) : chunksize,
+ (chunksize + (int) sizeof (SQLWCHAR)) :
+ chunksize,
#else
(type == SQL_C_CHAR) ?
(chunksize + 1) : chunksize,
#endif
&curlen);
@@ -5928,11 +6205,11 @@
#endif
if (valp == NULL) {
if (freep != NULL) {
xfree(freep);
}
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
freep = valp;
}
if (totlen > 0) {
curlen = totlen;
@@ -5977,29 +6254,81 @@
#endif
case SQL_C_DATE:
{
DATE_STRUCT *date;
- v = Data_Make_Struct(Cdate, DATE_STRUCT, 0, xfree, date);
- *date = *(DATE_STRUCT *) valp;
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ const char *p;
+ char buffer[128];
+ VALUE d;
+
+ date = (DATE_STRUCT *) valp;
+ p = (q->dbcp->gmtime == Qtrue) ? "+00:00" : "";
+ sprintf(buffer, "%d-%d-%dT00:00:00%s",
+ date->year, date->month, date->day, p);
+ d = rb_str_new2(buffer);
+ v = rb_funcall(rb_cDate, IDparse, 1, d);
+ } else {
+ v = Data_Make_Struct(Cdate, DATE_STRUCT, 0, xfree,
+ date);
+ *date = *(DATE_STRUCT *) valp;
+ }
}
break;
case SQL_C_TIME:
{
TIME_STRUCT *time;
- v = Data_Make_Struct(Ctime, TIME_STRUCT, 0, xfree, time);
- *time = *(TIME_STRUCT *) valp;
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ VALUE now, frac;
+
+ time = (TIME_STRUCT *) valp;
+ frac = rb_float_new(0.0);
+ now = rb_funcall(rb_cTime, IDnow, 0, NULL);
+ v = rb_funcall(rb_cTime,
+ (q->dbcp->gmtime == Qtrue) ?
+ IDutc : IDlocal,
+ 7,
+ rb_funcall(now, IDyear, 0, NULL),
+ rb_funcall(now, IDmonth, 0, NULL),
+ rb_funcall(now, IDday, 0, NULL),
+ INT2NUM(time->hour),
+ INT2NUM(time->minute),
+ INT2NUM(time->second),
+ frac);
+ } else {
+ v = Data_Make_Struct(Ctime, TIME_STRUCT, 0, xfree,
+ time);
+ *time = *(TIME_STRUCT *) valp;
+ }
}
break;
case SQL_C_TIMESTAMP:
{
TIMESTAMP_STRUCT *ts;
- v = Data_Make_Struct(Ctimestamp, TIMESTAMP_STRUCT,
- 0, xfree, ts);
- *ts = *(TIMESTAMP_STRUCT *) valp;
+ if (q->dbcp != NULL && q->dbcp->rbtime == Qtrue) {
+ VALUE frac;
+
+ ts = (TIMESTAMP_STRUCT *) valp;
+ frac = rb_float_new((double) 1.0e-3 * ts->fraction);
+ v = rb_funcall(rb_cTime,
+ (q->dbcp->gmtime == Qtrue) ?
+ IDutc : IDlocal,
+ 7,
+ INT2NUM(ts->year),
+ INT2NUM(ts->month),
+ INT2NUM(ts->day),
+ INT2NUM(ts->hour),
+ INT2NUM(ts->minute),
+ INT2NUM(ts->second),
+ frac);
+ } else {
+ v = Data_Make_Struct(Ctimestamp, TIMESTAMP_STRUCT,
+ 0, xfree, ts);
+ *ts = *(TIMESTAMP_STRUCT *) valp;
+ }
}
break;
#ifdef UNICODE
case SQL_C_WCHAR:
v = uc_tainted_str_new((SQLWCHAR *) valp,
@@ -6014,38 +6343,50 @@
if (freep != NULL) {
xfree(freep);
}
switch (mode & DOFETCH_MODES) {
case DOFETCH_HASH:
- valp = q->colnames[i + offc];
- goto doaset;
case DOFETCH_HASH2:
- valp = q->colnames[i + offc + q->ncols];
- doaset:
- name = rb_tainted_str_new2(valp);
- if (rb_funcall(res, IDkeyp, 1, name) == Qtrue) {
- char *p;
+ valp = q->colnames[i + offc];
+ name = (q->colvals == NULL) ? Qnil : q->colvals[i + offc];
+ if (name == Qnil) {
+ name = rb_tainted_str_new2(valp);
+#ifdef USE_RB_ENC
+ rb_enc_associate(name, rb_enc);
+#endif
+ if (rb_funcall(res, IDkeyp, 1, name) == Qtrue) {
+ char *p;
- p = q->colnames[4 * q->ncols];
- sprintf(p, "#%d", i);
- name = rb_str_cat2(name, p);
+ name = rb_tainted_str_new2(valp);
+#ifdef USE_RB_ENC
+ rb_enc_associate(name, rb_enc);
+#endif
+ p = q->colnames[4 * q->ncols];
+ sprintf(p, "#%d", i);
+ name = rb_str_cat2(name, p);
+ }
}
rb_hash_aset(res, name, v);
break;
case DOFETCH_HASHK:
- valp = q->colnames[i + offc];
- goto dokset;
case DOFETCH_HASHK2:
- valp = q->colnames[i + offc + q->ncols];
- dokset:
+ valp = q->colnames[i + offc];
+#ifdef USE_RB_ENC
+ name = ID2SYM(rb_intern3(valp, strlen(valp), rb_enc));
+#else
name = ID2SYM(rb_intern(valp));
+#endif
if (rb_funcall(res, IDkeyp, 1, name) == Qtrue) {
char *p;
p = q->colnames[4 * q->ncols];
sprintf(p, "%s#%d", valp, i);
+#ifdef USE_RB_ENC
+ name = ID2SYM(rb_intern3(p, strlen(p), rb_enc));
+#else
name = ID2SYM(rb_intern(p));
+#endif
}
rb_hash_aset(res, name, v);
break;
case DOFETCH_HASHN:
name = INT2NUM(i);
@@ -6061,11 +6402,12 @@
static VALUE
stmt_fetch1(VALUE self, int bang)
{
STMT *q;
SQLRETURN ret;
- char *msg, *err;
+ const char *msg;
+ char *err;
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
#endif
@@ -6132,11 +6474,12 @@
static VALUE
stmt_fetch_first1(VALUE self, int bang, int nopos)
{
STMT *q;
SQLRETURN ret;
- char *msg, *err;
+ const char *msg;
+ char *err;
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
#endif
@@ -6302,11 +6645,12 @@
stmt_fetch_hash1(int argc, VALUE *argv, VALUE self, int bang)
{
STMT *q;
SQLRETURN ret;
int mode = stmt_hash_mode(argc, argv, self);
- char *msg, *err;
+ const char *msg;
+ char *err;
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
#endif
@@ -6374,11 +6718,12 @@
stmt_fetch_first_hash1(int argc, VALUE *argv, VALUE self, int bang, int nopos)
{
STMT *q;
SQLRETURN ret;
int mode = stmt_hash_mode(argc, argv, self);
- char *msg, *err;
+ const char *msg;
+ char *err;
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
#endif
@@ -6415,11 +6760,11 @@
}
static VALUE
stmt_each(VALUE self)
{
- VALUE row;
+ VALUE row, res = Qnil;
STMT *q;
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
#endif
@@ -6444,21 +6789,31 @@
row = stmt_fetch_first1(self, 0, 1);
break;
default:
row = stmt_fetch1(self, 0);
}
- while (row != Qnil) {
- rb_yield(row);
- row = stmt_fetch1(self, 0);
+ if (rb_block_given_p()) {
+ while (row != Qnil) {
+ rb_yield(row);
+ row = stmt_fetch1(self, 0);
+ }
+ return self;
}
- return self;
+ if (row != Qnil) {
+ res = rb_ary_new();
+ while (row != Qnil) {
+ rb_ary_push(res, row);
+ row = stmt_fetch1(self, 0);
+ }
+ }
+ return res;
}
static VALUE
stmt_each_hash(int argc, VALUE *argv, VALUE self)
{
- VALUE row, withtab[2];
+ VALUE row, res = Qnil, withtab[2];
STMT *q;
int mode = stmt_hash_mode(argc, argv, self);
#if (ODBCVER < 0x0300)
SQLUINTEGER nRows;
SQLUSMALLINT rowStat[1];
@@ -6493,15 +6848,25 @@
row = stmt_fetch_first_hash1(2, withtab, self, 0, 1);
break;
default:
row = stmt_fetch_hash1(2, withtab, self, 0);
}
- while (row != Qnil) {
- rb_yield(row);
- row = stmt_fetch_hash1(2, withtab, self, 0);
+ if (rb_block_given_p()) {
+ while (row != Qnil) {
+ rb_yield(row);
+ row = stmt_fetch_hash1(2, withtab, self, 0);
+ }
+ return self;
}
- return self;
+ if (row != Qnil) {
+ res = rb_ary_new();
+ while (row != Qnil) {
+ rb_ary_push(res, row);
+ row = stmt_fetch_hash1(2, withtab, self, 0);
+ }
+ }
+ return res;
}
static VALUE
stmt_more_results(VALUE self)
{
@@ -6569,14 +6934,17 @@
dbc = self;
}
rb_scan_args(argc, argv, "1", &sql);
Check_Type(sql, T_STRING);
#ifdef UNICODE
+#ifdef USE_RB_ENC
+ sql = rb_funcall(sql, IDencode, 1, rb_encv);
+#endif
csql = STR2CSTR(sql);
ssql = uc_from_utf((unsigned char *) csql, -1);
if (ssql == NULL) {
- rb_raise(Cerror, set_err("Out of memory", 0));
+ rb_raise(Cerror, "%s", set_err("Out of memory", 0));
}
#else
csql = STR2CSTR(sql);
ssql = (SQLCHAR *) csql;
#endif
@@ -6587,14 +6955,17 @@
(ret = SQLExecDirect(hstmt, ssql, SQL_NTS)),
&msg, "SQLExecDirect('%s')", csql)) {
goto sqlerr;
}
if (ret == SQL_NO_DATA) {
-#ifdef UNICODE
- uc_free(ssql);
-#endif
- return Qnil;
+ callsql(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
+ SQLFreeStmt(hstmt, SQL_CLOSE), "SQLFreeStmt(SQL_DROP)");
+ if (q != NULL) {
+ q->hstmt = SQL_NULL_HSTMT;
+ unlink_stmt(q);
+ }
+ hstmt = SQL_NULL_HSTMT;
}
} else if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
SQLPrepare(hstmt, ssql, SQL_NTS),
&msg, "SQLPrepare('%s')", csql)) {
sqlerr:
@@ -6624,50 +6995,89 @@
}
static int
bind_one_param(int pnum, VALUE arg, STMT *q, char **msgp, int *outpp)
{
- SQLPOINTER valp = (SQLPOINTER) &q->pinfo[pnum].buffer;
+ SQLPOINTER valp = (SQLPOINTER) &q->paraminfo[pnum].buffer;
SQLSMALLINT ctype, stype;
SQLINTEGER vlen, rlen;
SQLUINTEGER coldef;
+#ifdef NO_RB_STR2CSTR
+ VALUE val;
+#endif
long llen;
int retry = 1;
#ifdef UNICODE
SQLWCHAR *up;
- q->pinfo[pnum].tofree = NULL;
+ q->paraminfo[pnum].tofree = NULL;
#endif
switch (TYPE(arg)) {
case T_STRING:
#ifdef UNICODE
ctype = SQL_C_WCHAR;
+#ifdef USE_RB_ENC
+ arg = rb_funcall(arg, IDencode, 1, rb_encv);
+#endif
+#ifndef NO_RB_STR2CSTR
up = (SQLWCHAR *) rb_str2cstr(arg, &llen);
- if (llen != strlen((char *) up)) {
+ if (llen != (long) strlen((char *) up)) {
ctype = SQL_C_BINARY;
valp = (SQLPOINTER) up;
rlen = llen;
vlen = rlen + 1;
break;
}
+#else
+ val = rb_string_value(&arg);
+ up = (SQLWCHAR *) RSTRING_PTR(val);
+ llen = RSTRING_LEN(val);
+ if (up == NULL) {
+ goto oom;
+ }
+ if (memchr((char *) up, 0, llen)) {
+ ctype = SQL_C_BINARY;
+ valp = (SQLPOINTER) up;
+ rlen = llen;
+ vlen = rlen + 1;
+ break;
+ }
+ up = (SQLWCHAR *) rb_string_value_cstr(&arg);
+#endif
up = uc_from_utf((unsigned char *) up, llen);
if (up == NULL) {
goto oom;
}
*(SQLWCHAR **) valp = up;
rlen = uc_strlen(up) * sizeof (SQLWCHAR);
vlen = rlen + sizeof (SQLWCHAR);
- q->pinfo[pnum].tofree = up;
+ q->paraminfo[pnum].tofree = up;
#else
ctype = SQL_C_CHAR;
+#ifndef NO_RB_STR2CSTR
valp = (SQLPOINTER) rb_str2cstr(arg, &llen);
rlen = llen;
- if (rlen != strlen((char *) valp)) {
+ if (rlen != (SQLINTEGER) strlen((char *) valp)) {
ctype = SQL_C_BINARY;
}
vlen = rlen + 1;
+#else
+ val = rb_string_value(&arg);
+ valp = (SQLPOINTER) RSTRING_PTR(val);
+ llen = RSTRING_LEN(val);
+ if (valp == NULL) {
+ goto oom;
+ }
+ rlen = llen;
+ vlen = rlen + 1;
+ if (memchr((char *) valp, 0, llen)) {
+ ctype = SQL_C_BINARY;
+ break;
+ }
+ valp = (SQLPOINTER) rb_string_value_cstr(&arg);
#endif
+#endif
break;
case T_FIXNUM:
ctype = SQL_C_LONG;
*(SQLINTEGER *) valp = FIX2INT(arg);
rlen = 1;
@@ -6724,23 +7134,97 @@
valp = (SQLPOINTER) ts;
rlen = 1;
vlen = sizeof (TIMESTAMP_STRUCT);
break;
}
+ if (rb_obj_is_kind_of(arg, rb_cTime) == Qtrue) {
+ if (q->paraminfo[pnum].type == SQL_TIME) {
+ TIME_STRUCT *time;
+
+ ctype = SQL_C_TIME;
+ time = (TIME_STRUCT *) valp;
+ memset(time, 0, sizeof (TIME_STRUCT));
+ time->hour = rb_funcall(arg, IDhour, 0, NULL);
+ time->minute = rb_funcall(arg, IDmin, 0, NULL);
+ time->second = rb_funcall(arg, IDsec, 0, NULL);
+ rlen = 1;
+ vlen = sizeof (TIME_STRUCT);
+ } else if (q->paraminfo[pnum].type == SQL_DATE) {
+ DATE_STRUCT *date;
+
+ ctype = SQL_C_DATE;
+ date = (DATE_STRUCT *) valp;
+ memset(date, 0, sizeof (DATE_STRUCT));
+ date->year = rb_funcall(arg, IDyear, 0, NULL);
+ date->month = rb_funcall(arg, IDmonth, 0, NULL);
+ date->day = rb_funcall(arg, IDday, 0, NULL);
+ rlen = 1;
+ vlen = sizeof (TIMESTAMP_STRUCT);
+ } else {
+ TIMESTAMP_STRUCT *ts;
+
+ ctype = SQL_C_TIMESTAMP;
+ ts = (TIMESTAMP_STRUCT *) valp;
+ memset(ts, 0, sizeof (TIMESTAMP_STRUCT));
+ ts->year = rb_funcall(arg, IDyear, 0, NULL);
+ ts->month = rb_funcall(arg, IDmonth, 0, NULL);
+ ts->day = rb_funcall(arg, IDday, 0, NULL);
+ ts->hour = rb_funcall(arg, IDhour, 0, NULL);
+ ts->minute = rb_funcall(arg, IDmin, 0, NULL);
+ ts->second = rb_funcall(arg, IDsec, 0, NULL);
+#ifdef TIME_USE_USEC
+ ts->fraction = rb_funcall(arg, IDusec, 0, NULL) * 1000;
+#else
+ ts->fraction = rb_funcall(arg, IDnsec, 0, NULL);
+#endif
+ rlen = 1;
+ vlen = sizeof (TIMESTAMP_STRUCT);
+ }
+ break;
+ }
+ if (rb_obj_is_kind_of(arg, rb_cDate) == Qtrue) {
+ DATE_STRUCT *date;
+
+ ctype = SQL_C_DATE;
+ date = (DATE_STRUCT *) valp;
+ memset(date, 0, sizeof (DATE_STRUCT));
+ date->year = rb_funcall(arg, IDyear, 0, NULL);
+ date->month = rb_funcall(arg, IDmonth, 0, NULL);
+ date->day = rb_funcall(arg, IDmday, 0, NULL);
+ rlen = 1;
+ vlen = sizeof (DATE_STRUCT);
+ break;
+ }
ctype = SQL_C_CHAR;
+#ifndef NO_RB_STR2CSTR
valp = (SQLPOINTER *) rb_str2cstr(rb_str_to_str(arg), &llen);
rlen = llen;
- if (rlen != strlen((char *) valp)) {
+ if (rlen != (SQLINTEGER) strlen((char *) valp)) {
ctype = SQL_C_BINARY;
}
vlen = rlen + 1;
+#else
+ val = rb_string_value(&arg);
+ valp = (SQLPOINTER) RSTRING_PTR(val);
+ llen = RSTRING_LEN(val);
+ if (valp == NULL) {
+ goto oom;
+ }
+ rlen = llen;
+ vlen = rlen + 1;
+ if (memchr((char *) valp, 0, llen)) {
+ ctype = SQL_C_BINARY;
+ break;
+ }
+ valp = (SQLPOINTER) rb_string_value_cstr(&arg);
+#endif
break;
}
- stype = q->pinfo[pnum].type;
- coldef = q->pinfo[pnum].coldef;
- q->pinfo[pnum].rlen = rlen;
- q->pinfo[pnum].ctype = ctype;
+ stype = q->paraminfo[pnum].type;
+ coldef = q->paraminfo[pnum].coldef;
+ q->paraminfo[pnum].rlen = rlen;
+ q->paraminfo[pnum].ctype = ctype;
if (coldef == 0) {
switch (ctype) {
case SQL_C_LONG:
coldef = 10;
break;
@@ -6770,92 +7254,92 @@
* then 'paul', it would not re-prepare the query. The key seems
* to be allocating enough space for the largest parameter.
* TBD: the default for this should be a tunable parameter.
*/
if ((stype == SQL_VARCHAR) &&
- (q->pinfo[pnum].iotype != SQL_PARAM_INPUT_OUTPUT) &&
- (q->pinfo[pnum].iotype != SQL_PARAM_OUTPUT)) {
- if (q->pinfo[pnum].coldef_max == 0) {
- q->pinfo[pnum].coldef_max = (vlen > 128) ? vlen : 128;
+ (q->paraminfo[pnum].iotype != SQL_PARAM_INPUT_OUTPUT) &&
+ (q->paraminfo[pnum].iotype != SQL_PARAM_OUTPUT)) {
+ if (q->paraminfo[pnum].coldef_max == 0) {
+ q->paraminfo[pnum].coldef_max = (vlen > 128) ? vlen : 128;
} else {
/* bump up max, if needed */
- if (vlen > q->pinfo[pnum].coldef_max) {
- q->pinfo[pnum].coldef_max = vlen;
+ if (vlen > (SQLINTEGER) q->paraminfo[pnum].coldef_max) {
+ q->paraminfo[pnum].coldef_max = vlen;
}
}
- coldef = q->pinfo[pnum].coldef_max;
+ coldef = q->paraminfo[pnum].coldef_max;
} else {
coldef = vlen;
}
break;
}
}
- if ((q->pinfo[pnum].iotype == SQL_PARAM_INPUT_OUTPUT) ||
- (q->pinfo[pnum].iotype == SQL_PARAM_OUTPUT)) {
+ if ((q->paraminfo[pnum].iotype == SQL_PARAM_INPUT_OUTPUT) ||
+ (q->paraminfo[pnum].iotype == SQL_PARAM_OUTPUT)) {
if (valp == NULL) {
- if (q->pinfo[pnum].outsize > 0) {
- if (q->pinfo[pnum].outbuf != NULL) {
- xfree(q->pinfo[pnum].outbuf);
+ if (q->paraminfo[pnum].outsize > 0) {
+ if (q->paraminfo[pnum].outbuf != NULL) {
+ xfree(q->paraminfo[pnum].outbuf);
}
- q->pinfo[pnum].outbuf = xmalloc(q->pinfo[pnum].outsize);
- if (q->pinfo[pnum].outbuf == NULL) {
+ q->paraminfo[pnum].outbuf = xmalloc(q->paraminfo[pnum].outsize);
+ if (q->paraminfo[pnum].outbuf == NULL) {
goto oom;
}
- ctype = q->pinfo[pnum].ctype = q->pinfo[pnum].outtype;
+ ctype = q->paraminfo[pnum].ctype = q->paraminfo[pnum].outtype;
outpp[0]++;
- valp = q->pinfo[pnum].outbuf;
- vlen = q->pinfo[pnum].outsize;
+ valp = q->paraminfo[pnum].outbuf;
+ vlen = q->paraminfo[pnum].outsize;
}
} else {
- if (q->pinfo[pnum].outbuf != NULL) {
- xfree(q->pinfo[pnum].outbuf);
+ if (q->paraminfo[pnum].outbuf != NULL) {
+ xfree(q->paraminfo[pnum].outbuf);
}
- q->pinfo[pnum].outbuf = xmalloc(vlen);
- if (q->pinfo[pnum].outbuf == NULL) {
+ q->paraminfo[pnum].outbuf = xmalloc(vlen);
+ if (q->paraminfo[pnum].outbuf == NULL) {
oom:
#ifdef UNICODE
- if (q->pinfo[pnum].tofree != NULL) {
- uc_free(q->pinfo[pnum].tofree);
- q->pinfo[pnum].tofree = NULL;
+ if (q->paraminfo[pnum].tofree != NULL) {
+ uc_free(q->paraminfo[pnum].tofree);
+ q->paraminfo[pnum].tofree = NULL;
}
#endif
*msgp = set_err("Out of memory", 0);
return -1;
}
#ifdef UNICODE
if (ctype == SQL_C_WCHAR) {
- memcpy(q->pinfo[pnum].outbuf, *(SQLWCHAR **) valp, vlen);
+ memcpy(q->paraminfo[pnum].outbuf, *(SQLWCHAR **) valp, vlen);
} else
#endif
- memcpy(q->pinfo[pnum].outbuf, valp, vlen);
+ memcpy(q->paraminfo[pnum].outbuf, valp, vlen);
#ifdef UNICODE
if (ctype == SQL_C_WCHAR) {
- *(SQLWCHAR **) valp = (SQLWCHAR *) q->pinfo[pnum].outbuf;
+ *(SQLWCHAR **) valp = (SQLWCHAR *) q->paraminfo[pnum].outbuf;
} else
#endif
- valp = q->pinfo[pnum].outbuf;
+ valp = q->paraminfo[pnum].outbuf;
outpp[0]++;
}
}
retry:
#ifdef UNICODE
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLBindParameter(q->hstmt, (SQLUSMALLINT) (pnum + 1),
- q->pinfo[pnum].iotype,
+ q->paraminfo[pnum].iotype,
ctype, stype, coldef,
- q->pinfo[pnum].scale,
+ q->paraminfo[pnum].scale,
(ctype == SQL_C_WCHAR) ?
*(SQLWCHAR **) valp : valp,
- vlen, &q->pinfo[pnum].rlen),
+ vlen, &q->paraminfo[pnum].rlen),
msgp, "SQLBindParameter(%d)", pnum + 1))
#else
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLBindParameter(q->hstmt, (SQLUSMALLINT) (pnum + 1),
- q->pinfo[pnum].iotype,
+ q->paraminfo[pnum].iotype,
ctype, stype, coldef,
- q->pinfo[pnum].scale,
- valp, vlen, &q->pinfo[pnum].rlen),
+ q->paraminfo[pnum].scale,
+ valp, vlen, &q->paraminfo[pnum].rlen),
msgp, "SQLBindParameter(%d)", pnum + 1))
#endif
{
if (retry) {
retry = 0;
@@ -6883,15 +7367,15 @@
int i, argnum, has_out_parms = 0;
char *msg = NULL;
SQLRETURN ret;
Data_Get_Struct(self, STMT, q);
- if (argc > q->nump - (EXEC_PARMXOUT(mode) < 0 ? 0 : 1)) {
- rb_raise(Cerror, set_err("Too much parameters", 0));
+ if (argc > q->nump - ((EXEC_PARMXOUT(mode) < 0) ? 0 : 1)) {
+ rb_raise(Cerror, "%s", set_err("Too much parameters", 0));
}
if (q->hstmt == SQL_NULL_HSTMT) {
- rb_raise(Cerror, set_err("Stale ODBC::Statement", 0));
+ rb_raise(Cerror, "%s", set_err("Stale ODBC::Statement", 0));
}
if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLFreeStmt(q->hstmt, SQL_CLOSE),
&msg, "SQLFreeStmt(SQL_CLOSE)")) {
goto error;
@@ -6906,24 +7390,24 @@
if (bind_one_param(i, Qnil, q, &msg, &has_out_parms) < 0) {
goto error;
}
continue;
}
- arg = argnum < argc ? argv[argnum++] : Qnil;
+ arg = (argnum < argc) ? argv[argnum++] : Qnil;
if (bind_one_param(i, arg, q, &msg, &has_out_parms) < 0) {
goto error;
}
}
if (!succeeded_nodata(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
(ret = SQLExecute(q->hstmt)),
&msg, "SQLExecute")) {
error:
#ifdef UNICODE
for (i = 0; i < q->nump; i++) {
- if (q->pinfo[i].tofree != NULL) {
- uc_free(q->pinfo[i].tofree);
- q->pinfo[i].tofree = NULL;
+ if (q->paraminfo[i].tofree != NULL) {
+ uc_free(q->paraminfo[i].tofree);
+ q->paraminfo[i].tofree = NULL;
}
}
#endif
callsql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
SQLFreeStmt(q->hstmt, SQL_DROP), "SQLFreeStmt(SQL_DROP)");
@@ -6931,13 +7415,13 @@
unlink_stmt(q);
rb_raise(Cerror, "%s", msg);
}
#ifdef UNICODE
for (i = 0; i < q->nump; i++) {
- if (q->pinfo[i].tofree != NULL) {
- uc_free(q->pinfo[i].tofree);
- q->pinfo[i].tofree = NULL;
+ if (q->paraminfo[i].tofree != NULL) {
+ uc_free(q->paraminfo[i].tofree);
+ q->paraminfo[i].tofree = NULL;
}
}
#endif
if (!has_out_parms) {
callsql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
@@ -7521,10 +8005,12 @@
{ &IDatattrs, "@attrs" },
{ &IDday, "day" },
{ &IDmonth, "month" },
{ &IDyear, "year" },
{ &IDmday, "mday" },
+ { &IDnsec, "nsec" },
+ { &IDusec, "usec" },
{ &IDsec, "sec" },
{ &IDmin, "min" },
{ &IDhour, "hour" },
{ &IDusec, "usec" },
{ &IDkeyp, "key?" },
@@ -7551,11 +8037,17 @@
{ &IDdescr, "descr" },
{ &IDstatement, "statement" },
{ &IDreturn_output_param, "return_output_param" },
{ &IDattrs, "attrs" },
{ &IDNULL, "NULL" },
- { &IDdefault, "default" }
+ { &IDdefault, "default" },
+#ifdef USE_RB_ENC
+ { &IDencode, "encode" },
+#endif
+ { &IDparse, "parse" },
+ { &IDutc, "utc" },
+ { &IDlocal, "local" }
};
/*
*----------------------------------------------------------------------
*
@@ -7570,11 +8062,11 @@
#else
Init_odbc()
#endif
{
int i;
- char *modname = "ODBC";
+ const char *modname = "ODBC";
ID modid = rb_intern(modname);
VALUE v = Qnil;
rb_require("date");
rb_cDate = rb_eval_string("Date");
@@ -7591,11 +8083,11 @@
#else
modname = "ODBC_NONE";
#endif
}
- for (i = 0; i < sizeof (ids) / sizeof (ids[0]); i++) {
+ for (i = 0; i < (int) (sizeof (ids) / sizeof (ids[0])); i++) {
*(ids[i].idp) = rb_intern(ids[i].str);
}
Modbc = rb_define_module(modname);
Cobj = rb_define_class_under(Modbc, "Object", rb_cObject);
@@ -7726,10 +8218,14 @@
rb_define_method(Cdbc, "get_info", dbc_getinfo, -1);
rb_define_method(Cdbc, "prepare", stmt_prep, -1);
rb_define_method(Cdbc, "run", stmt_run, -1);
rb_define_method(Cdbc, "do", stmt_do, -1);
rb_define_method(Cdbc, "proc", stmt_proc, -1);
+ rb_define_method(Cdbc, "use_time", dbc_timefmt, -1);
+ rb_define_method(Cdbc, "use_time=", dbc_timefmt, -1);
+ rb_define_method(Cdbc, "use_utc", dbc_timeutc, -1);
+ rb_define_method(Cdbc, "use_utc=", dbc_timeutc, -1);
/* connection options */
rb_define_method(Cdbc, "get_option", dbc_getsetoption, -1);
rb_define_method(Cdbc, "set_option", dbc_getsetoption, -1);
rb_define_method(Cdbc, "autocommit", dbc_autocommit, -1);
@@ -7897,9 +8393,19 @@
}
for (i = 0; option_map[i].name != NULL; i++) {
rb_define_const(Modbc, option_map[i].name,
INT2NUM(option_map[i].option));
}
+
+#ifdef UNICODE
+ rb_define_const(Modbc, "UTF8", Qtrue);
+#ifdef USE_RB_ENC
+ rb_enc = rb_utf8_encoding();
+ rb_encv = rb_enc_from_encoding(rb_enc);
+#endif
+#else
+ rb_define_const(Modbc, "UTF8", Qfalse);
+#endif
#ifdef TRACING
if (ruby_verbose) {
tracing = -1;
}