#include "Sybase.h"
#if defined(op)
#undef op
#endif
#if !defined(PATCHLEVEL)
#include "patchlevel.h" /* this is the perl patchlevel.h */
#endif
#if PATCHLEVEL < 5 && SUBVERSION < 5
#define PL_na na
#define PL_sv_undef sv_undef
#define PL_dirty dirty
#endif
#ifndef PerlIO
# define PerlIO FILE
# define PerlIO_printf fprintf
# define PerlIO_stderr() stderr
# define PerlIO_close(f) fclose(f)
# define PerlIO_open(f,m) fopen(f,m)
# define PerlIO_flush(f) fflush(f)
# define PerlIO_puts(f,s) fputs(s,f)
#endif
#ifdef WIN32
# define strncasecmp _strnicmp
#endif
#if !defined(NO_CHAINED_TRAN)
#define NO_CHAINED_TRAN 0
#endif
#if !defined(FLUSH_FINISH)
#define FLUSH_FINISH 0
#endif
#if !defined(PROC_STATUS)
#define PROC_STATUS 0
#endif
#if !defined(ROLLBACK_ON_EXIT)
#define ROLLBACK_ON_EXIT 0
#endif
#if defined(CS_VERSION_110)
#if !defined BLK_VERSION_110
#define BLK_VERSION_110 BLK_VERSION_100
#endif
#endif
#if defined(CS_VERSION_120)
#if !defined BLK_VERSION_120
#define BLK_VERSION_120 BLK_VERSION_110
#endif
#endif
#if defined(CS_VERSION_125)
#if !defined BLK_VERSION_125
#define BLK_VERSION_125 BLK_VERSION_120
#endif
#endif
#if defined(CS_VERSION_150)
#if !defined BLK_VERSION_150
#define BLK_VERSION_150 BLK_VERSION_125
#endif
#endif
#if defined(CS_VERSION_155)
#if !defined BLK_VERSION_155
#define BLK_VERSION_155 BLK_VERSION_150
#endif
#endif
#if defined(CS_VERSION_157)
#if !defined BLK_VERSION_157
#define BLK_VERSION_157 BLK_VERSION_155
#endif
#endif
#if !defined(CS_LONGCHAR_TYPE)
#define CS_LONGCHAR_TYPE CS_CHAR_TYPE
#endif
DBISTATE_DECLARE;
static
void
cleanUp _((imp_dbh_t *, imp_sth_t *));
static
char
*GetAggOp _((CS_INT));
static
CS_INT get_cwidth _((CS_DATAFMT *));
static
CS_INT display_dlen _((CS_DATAFMT *));
static
CS_RETCODE display_header _((imp_dbh_t *, CS_INT, CS_DATAFMT*));
static
CS_RETCODE describe _((SV *sth, imp_sth_t *,
int
));
static
CS_RETCODE fetch_data _((imp_dbh_t *, CS_COMMAND*));
static
CS_RETCODE CS_PUBLIC clientmsg_cb _((CS_CONTEXT*, CS_CONNECTION*, CS_CLIENTMSG*));
static
CS_RETCODE CS_PUBLIC servermsg_cb _((CS_CONTEXT*, CS_CONNECTION*, CS_SERVERMSG*));
static
CS_RETCODE CS_PUBLIC cslibmsg_cb(CS_CONTEXT *context, CS_CLIENTMSG *errmsg);
static
CS_COMMAND *syb_alloc_cmd _((imp_dbh_t *, CS_CONNECTION*,
int
mode));
static
void
dealloc_dynamic _((imp_sth_t *));
static
int
map_syb_types _((
int
));
static
int
map_sql_types _((
int
));
static
CS_CONNECTION *syb_db_connect _((
struct
imp_dbh_st *));
static
int
syb_db_use _((imp_dbh_t *, CS_CONNECTION *));
static
int
syb_st_describe_proc _((SV *sth, imp_sth_t *,
char
*));
static
void
syb_set_error(imp_dbh_t *,
int
,
char
*);
static
char
*my_strdup _((
char
*));
static
void
fetchKerbTicket(imp_dbh_t *imp_dbh);
static
CS_RETCODE syb_blk_init(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth);
static
void
blkCleanUp(imp_sth_t *imp_sth, imp_dbh_t *imp_dbh);
static
int
getTableName(
char
*statement,
char
*table,
int
maxwidth);
static
int
toggle_autocommit(SV *dbh, imp_dbh_t *imp_dbh,
int
flag);
static
int
datetime2str(ColData *colData, CS_DATAFMT *srcfmt,
char
*buff, CS_INT len,
int
type, CS_LOCALE *locale);
#if defined(CS_DATE_TYPE)
static
int
date2str(CS_DATE *d, CS_DATAFMT *srcfmt,
char
*buff, CS_INT len,
int
type, CS_LOCALE *locale);
static
int
time2str(ColData *colData, CS_DATAFMT *srcfmt,
char
*buff, CS_INT len,
int
type, CS_LOCALE *locale);
#endif
static
int
syb_get_date_fmt(imp_dbh_t *imp_dbh,
char
*fmt);
static
int
cmd_execute(SV *sth, imp_sth_t *imp_sth);
#if defined(DBD_CAN_HANDLE_UTF8)
static
int
is_high_bit_set(
const
unsigned
char
*val, STRLEN size);
#endif
static
CS_BINARY *to_binary(
char
*str, STRLEN *outlen);
static
int
get_server_version(SV *dbh, imp_dbh_t *imp_dbh, CS_CONNECTION *con);
static
void
clear_cache(SV *sth, imp_sth_t *imp_sth);
static
int
_dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs,
int
maxlen);
static
CS_RETCODE get_cs_msg(CS_CONTEXT *context,
char
*msg, SV *sth, imp_sth_t *imp_sth);
static
CS_INT BLK_VERSION;
#if PERL_VERSION >= 8 && defined(_REENTRANT)
static
perl_mutex context_alloc_mutex[1];
#endif
static
CS_CONTEXT *context;
static
CS_LOCALE *glocale;
static
char
scriptName[255];
static
char
hostname[255];
static
char
*ocVersion;
#define LOCALE(s) ((s)->locale ? (s)->locale : glocale)
static
SV *cslib_cb;
static
int
syb_set_options(imp_dbh_t *imp_dbh, CS_INT action, CS_INT option, CS_VOID *value, CS_INT len,
CS_INT *outlen) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_set_options: optSupported = %d\n"
, imp_dbh->optSupported);
}
if
(!imp_dbh->optSupported) {
return
CS_FAIL;
}
return
ct_options(imp_dbh->connection, action, option, value, len, outlen);
}
static
void
syb_set_error(imp_dbh_t *imp_dbh,
int
err,
char
*errstr) {
dTHX;
sv_setiv(DBIc_ERR(imp_dbh), err);
if
(SvOK(DBIc_ERRSTR(imp_dbh))) {
sv_catpv(DBIc_ERRSTR(imp_dbh), errstr);
}
else
{
sv_setpv(DBIc_ERRSTR(imp_dbh), errstr);
}
}
static
CS_RETCODE CS_PUBLIC cslibmsg_cb(CS_CONTEXT *context, CS_CLIENTMSG *errmsg) {
dTHX;
#if 0
if
(DBIS->debug >= 4) {
PerlIO_printf(DBILOGFP,
" cslibmsg_cb -> %s\n"
, errmsg->msgstring);
if
(errmsg->osstringlen> 0) {
PerlIO_printf(DBILOGFP,
" cslibmsg_cb -> %s\n"
, errmsg->osstring);
}
}
#endif
if
(cslib_cb) {
dSP;
int
retval, count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(CS_LAYER(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_ORIGIN(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_SEVERITY(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_NUMBER(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSVpv(errmsg->msgstring, 0)));
if
(errmsg->osstringlen > 0) {
XPUSHs(sv_2mortal(newSVpv(errmsg->osstring, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
PUTBACK;
if
((count = perl_call_sv(cslib_cb, G_SCALAR)) != 1) {
croak(
"A cslib handler cannot return a LIST"
);
}
SPAGAIN;
retval = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return
retval;
}
PerlIO_printf(PerlIO_stderr(),
"\nCS Library Message:\n"
);
PerlIO_printf(PerlIO_stderr(),
"Message number: LAYER = (%d) ORIGIN = (%d) "
,
CS_LAYER(errmsg->msgnumber), CS_ORIGIN(errmsg->msgnumber));
PerlIO_printf(PerlIO_stderr(),
"SEVERITY = (%d) NUMBER = (%d)\n"
,
CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
PerlIO_printf(PerlIO_stderr(),
"Message String: %s\n"
, errmsg->msgstring);
if
(errmsg->osstringlen > 0) {
PerlIO_printf(PerlIO_stderr(),
"Operating System Error: %s\n"
,
errmsg->osstring);
}
return
CS_SUCCEED;
}
static
CS_RETCODE CS_PUBLIC
clientmsg_cb(CS_CONTEXT *context, CS_CONNECTION *connection, CS_CLIENTMSG *errmsg) {
dTHX;
imp_dbh_t *imp_dbh = NULL;
char
buff[255];
if
(connection) {
if
((ct_con_props(connection, CS_GET, CS_USERDATA, &imp_dbh,
CS_SIZEOF(imp_dbh), NULL)) != CS_SUCCEED) {
croak(
"Panic: clientmsg_cb: Can't find handle from connection"
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" clientmsg_cb -> %s\n"
,
errmsg->msgstring);
if
(errmsg->osstringlen> 0) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" clientmsg_cb -> %s\n"
,
errmsg->osstring);
}
}
if
(DBIc_is(imp_dbh, DBIcf_LongTruncOk) &&
CS_NUMBER(errmsg->msgnumber) == 132) {
return
CS_SUCCEED;
}
if
(imp_dbh->err_handler) {
dSP;
int
retval, count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(CS_NUMBER(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_SEVERITY(errmsg->msgnumber))));
XPUSHs(sv_2mortal(newSViv(0)));
XPUSHs(sv_2mortal(newSViv(0)));
XPUSHs(&PL_sv_undef);
XPUSHs(&PL_sv_undef);
XPUSHs(sv_2mortal(newSVpv(errmsg->msgstring, 0)));
if
(imp_dbh->sql) {
XPUSHs(sv_2mortal(newSVpv(imp_dbh->sql, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
XPUSHs(sv_2mortal(newSVpv(
"client"
, 0)));
PUTBACK;
if
((count = perl_call_sv(imp_dbh->err_handler, G_SCALAR | G_EVAL)) != 1) {
croak(
"An error handler can't return a LIST."
);
}
SPAGAIN;
if
(SvTRUE(ERRSV)) {
POPs;
retval = 1;
}
else
{
retval = POPi;
}
PUTBACK;
FREETMPS;
LEAVE;
if
(retval == 0) {
return
CS_SUCCEED;
}
}
sv_setiv(DBIc_ERR(imp_dbh), (IV)CS_NUMBER(errmsg->msgnumber));
if
(SvOK(DBIc_ERRSTR(imp_dbh))) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
"OpenClient message: "
);
}
else
{
sv_setpv(DBIc_ERRSTR(imp_dbh),
"OpenClient message: "
);
}
sprintf
(buff,
"LAYER = (%d) ORIGIN = (%d) "
,
CS_LAYER(errmsg->msgnumber), CS_ORIGIN(errmsg->msgnumber));
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
sprintf
(buff,
"SEVERITY = (%d) NUMBER = (%d)\n"
,
CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
sprintf
(buff,
"Server %s, database %s\n"
,
imp_dbh->server, imp_dbh->curr_db);
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
sv_catpv(DBIc_ERRSTR(imp_dbh),
"Message String: "
);
sv_catpv(DBIc_ERRSTR(imp_dbh), errmsg->msgstring);
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
if
(errmsg->osstringlen> 0) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
"Operating System Error: "
);
sv_catpv(DBIc_ERRSTR(imp_dbh), errmsg->osstring);
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
}
if
(CS_NUMBER(errmsg->msgnumber) == 6) {
imp_dbh->isDead = 1;
}
if
(CS_SEVERITY(errmsg->msgnumber) == CS_SV_RETRY_FAIL &&
CS_NUMBER(errmsg->msgnumber) == 63 &&
CS_ORIGIN(errmsg->msgnumber) == 2 &&
CS_LAYER(errmsg->msgnumber) == 1) {
CS_INT status;
status = 0;
if
(ct_con_props(connection, CS_GET, CS_LOGIN_STATUS,
(CS_VOID *)&status,
CS_UNUSED, NULL) != CS_SUCCEED) {
imp_dbh->isDead = 1;
return
CS_FAIL;
}
if
(!status) {
imp_dbh->isDead = 1;
return
CS_FAIL;
}
if
(ct_cancel(connection, NULL, CS_CANCEL_ATTN) == CS_FAIL) {
imp_dbh->isDead = 1;
return
CS_FAIL;
}
return
CS_SUCCEED;
}
}
else
{
PerlIO_printf(PerlIO_stderr(),
"OpenClient message: "
);
PerlIO_printf(PerlIO_stderr(),
"LAYER = (%d) ORIGIN = (%d) "
,
CS_LAYER(errmsg->msgnumber), CS_ORIGIN(errmsg->msgnumber));
PerlIO_printf(PerlIO_stderr(),
"SEVERITY = (%d) NUMBER = (%d)\n"
,
CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
PerlIO_printf(PerlIO_stderr(),
"Message String: %s\n"
, errmsg->msgstring);
if
(errmsg->osstringlen> 0) {
PerlIO_printf(PerlIO_stderr(),
"Operating System Error: %s\n"
,
errmsg->osstring);
}
}
return
CS_SUCCEED;
}
static
CS_RETCODE CS_PUBLIC
servermsg_cb(CS_CONTEXT *context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg) {
CS_COMMAND *cmd;
CS_RETCODE retcode;
imp_dbh_t *imp_dbh = NULL;
char
buff[1024];
dTHX;
if
(connection && (ct_con_props(connection, CS_GET, CS_USERDATA, &imp_dbh,
CS_SIZEOF(imp_dbh), NULL)) != CS_SUCCEED) {
croak(
"Panic: servermsg_cb: Can't find handle from connection"
);
}
if
(imp_dbh && DBIc_DBISTATE(imp_dbh)->debug >= 4) {
if
(srvmsg->msgnumber) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" servermsg_cb -> number=%d severity=%d "
,
srvmsg->msgnumber, srvmsg->severity);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"state=%d line=%d "
,
srvmsg->state, srvmsg->line);
if
(srvmsg->svrnlen> 0) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"server=%s "
, srvmsg->svrname);
}
if
(srvmsg->proclen> 0) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"procedure=%s "
, srvmsg->proc);
}
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"text=%s\n"
, srvmsg->text);
}
else
{
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" servermsg_cb -> %s\n"
, srvmsg->text);
}
}
if
(srvmsg->msgnumber == 5701 || srvmsg->msgnumber == 5703 || srvmsg->msgnumber == 5704) {
char
*c;
int
i;
if
(srvmsg->text != NULL && (c =
strchr
( srvmsg->text,
'\''
)) != NULL) {
i = 0;
for
( ++c; i <= 30 && *c !=
'\0'
&& *c !=
'\''
; ++c ) {
buff[i++] = *c;
}
buff[i] =
'\0'
;
if
(
strcmp
( buff,
"<NULL>"
) != 0) {
switch
(srvmsg->msgnumber) {
case
5701:
if
(imp_dbh && DBIc_ACTIVE(imp_dbh) &&
imp_dbh->connection == connection) {
strcpy
(imp_dbh->curr_db, buff);
}
break
;
case
5703:
break
;
case
5704:
break
;
default
:
break
;
}
}
}
return
CS_SUCCEED;
}
if
(imp_dbh && srvmsg->msgnumber == 17001) {
imp_dbh->optSupported = 0;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" servermsg_cb() -> ct_option is %ssupported\n"
, imp_dbh->optSupported == 1 ?
""
:
"not "
);
}
}
if
(imp_dbh && imp_dbh->err_handler) {
dSP;
int
retval, count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(srvmsg->msgnumber)));
XPUSHs(sv_2mortal(newSViv(srvmsg->severity)));
XPUSHs(sv_2mortal(newSViv(srvmsg->state)));
XPUSHs(sv_2mortal(newSViv(srvmsg->line)));
if
(srvmsg->svrnlen> 0) {
XPUSHs(sv_2mortal(newSVpv(srvmsg->svrname, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
if
(srvmsg->proclen> 0) {
XPUSHs(sv_2mortal(newSVpv(srvmsg->proc, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
XPUSHs(sv_2mortal(newSVpv(srvmsg->text, 0)));
if
(imp_dbh->sql) {
XPUSHs(sv_2mortal(newSVpv(imp_dbh->sql, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
XPUSHs(sv_2mortal(newSVpv(
"server"
, 0)));
PUTBACK;
if
((count = perl_call_sv(imp_dbh->err_handler, G_SCALAR | G_EVAL)) != 1) {
croak(
"An error handler can't return a LIST."
);
}
SPAGAIN;
if
(SvTRUE(ERRSV)) {
POPs;
retval = 1;
}
else
{
retval = POPi;
}
PUTBACK;
FREETMPS;
LEAVE;
if
(retval == 0) {
return
CS_SUCCEED;
}
}
if
(imp_dbh && srvmsg->msgnumber) {
if
(srvmsg->severity > 10 || srvmsg->msgnumber == 5702) {
sv_setiv(DBIc_ERR(imp_dbh), (IV)srvmsg->msgnumber);
imp_dbh->lasterr = srvmsg->msgnumber;
imp_dbh->lastsev = srvmsg->severity;
if
(srvmsg->msgnumber == 5702) {
ct_close(connection, CS_FORCE_CLOSE);
imp_dbh->isDead = 1;
}
}
if
(SvOK(DBIc_ERRSTR(imp_dbh))) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
"Server message "
);
}
else
{
sv_setpv(DBIc_ERRSTR(imp_dbh),
"Server message "
);
}
sprintf
(buff,
"number=%d severity=%d "
, srvmsg->msgnumber, srvmsg->severity);
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
sprintf
(buff,
"state=%d line=%d"
, srvmsg->state, srvmsg->line);
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
if
(srvmsg->svrnlen> 0) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
" server="
);
sv_catpv(DBIc_ERRSTR(imp_dbh), srvmsg->svrname);
}
if
(srvmsg->proclen> 0) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
" procedure="
);
sv_catpv(DBIc_ERRSTR(imp_dbh), srvmsg->proc);
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
" text="
);
sv_catpv(DBIc_ERRSTR(imp_dbh), srvmsg->text);
if
(imp_dbh->showSql) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
" Statement="
);
sv_catpv(DBIc_ERRSTR(imp_dbh), imp_dbh->sql);
}
if
(imp_dbh->showEed && srvmsg->status & CS_HASEED) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n[Start Extended Error]\n"
);
if
(ct_con_props(connection, CS_GET, CS_EED_CMD,
&cmd, CS_UNUSED, NULL) != CS_SUCCEED) {
warn(
"servermsg_cb: ct_con_props(CS_EED_CMD) failed"
);
return
CS_FAIL;
}
retcode = fetch_data(imp_dbh, cmd);
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n[End Extended Error]\n"
);
}
else
{
retcode = CS_SUCCEED;
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
" "
);
return
retcode;
}
else
{
if
(srvmsg->msgnumber) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"Server message: number=%d severity=%d "
,
srvmsg->msgnumber, srvmsg->severity);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"state=%d line=%d "
,
srvmsg->state, srvmsg->line);
if
(srvmsg->svrnlen> 0) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"server=%s "
, srvmsg->svrname);
}
if
(srvmsg->proclen> 0) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"procedure=%s "
, srvmsg->proc);
}
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"text=%s\n"
, srvmsg->text);
}
else
{
warn(
"%s\n"
, srvmsg->text);
}
PerlIO_flush(DBIc_LOGPIO(imp_dbh));
}
return
CS_SUCCEED;
}
static
CS_CHAR * GetAggOp(CS_INT op) {
CS_CHAR *name;
switch
((
int
) op) {
case
CS_OP_SUM:
name =
"sum"
;
break
;
case
CS_OP_AVG:
name =
"avg"
;
break
;
case
CS_OP_COUNT:
name =
"count"
;
break
;
case
CS_OP_MIN:
name =
"min"
;
break
;
case
CS_OP_MAX:
name =
"max"
;
break
;
default
:
name =
"unknown"
;
break
;
}
return
name;
}
static
CS_INT get_cwidth(CS_DATAFMT *column) {
CS_INT len;
switch
((
int
) column->datatype) {
case
CS_CHAR_TYPE:
case
CS_LONGCHAR_TYPE:
case
CS_VARCHAR_TYPE:
case
CS_TEXT_TYPE:
case
CS_IMAGE_TYPE:
len = column->maxlength;
break
;
case
CS_BINARY_TYPE:
case
CS_VARBINARY_TYPE:
case
CS_LONGBINARY_TYPE:
#if defined(CS_UNICHAR_TYPE)
case
CS_UNICHAR_TYPE:
#endif
#if defined(CS_UNITEXT_TYPE)
case
CS_UNITEXT_TYPE:
#endif
len = (2 * column->maxlength) + 2;
break
;
case
CS_BIT_TYPE:
case
CS_TINYINT_TYPE:
len = 3;
break
;
case
CS_SMALLINT_TYPE:
#if defined(CS_USMALLINT_TYPE)
case
CS_USMALLINT_TYPE:
#endif
len = 6;
break
;
case
CS_INT_TYPE:
#if defined(CS_UINT_TYPE)
case
CS_UINT_TYPE:
#endif
len = 11;
break
;
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
case
CS_UBIGINT_TYPE:
len = 22;
#endif
case
CS_REAL_TYPE:
case
CS_FLOAT_TYPE:
len = 20;
break
;
case
CS_MONEY_TYPE:
case
CS_MONEY4_TYPE:
len = 24;
break
;
case
CS_DATETIME_TYPE:
case
CS_DATETIME4_TYPE:
#if defined(CS_DATE_TYPE)
case
CS_DATE_TYPE:
case
CS_TIME_TYPE:
#endif
#if defined(CS_BIGDATETIME_TYPE)
case
CS_BIGDATETIME_TYPE:
case
CS_BIGTIME_TYPE:
#endif
len = 40;
break
;
#if 1
case
CS_NUMERIC_TYPE:
case
CS_DECIMAL_TYPE:
len = column->precision + column->scale + 2;
break
;
#endif
#ifdef CS_UNIQUE_TYPE
case
CS_UNIQUE_TYPE:
len = 40;
break
;
#endif
default
:
len = column->maxlength;
break
;
}
return
len;
}
static
CS_INT display_dlen(CS_DATAFMT *column) {
CS_INT len;
len = get_cwidth(column);
switch
((
int
) column->datatype) {
case
CS_CHAR_TYPE:
case
CS_LONGCHAR_TYPE:
case
CS_VARCHAR_TYPE:
case
CS_TEXT_TYPE:
case
CS_IMAGE_TYPE:
case
CS_BINARY_TYPE:
case
CS_VARBINARY_TYPE:
len = MIN(len, MAX_CHAR_BUF);
break
;
default
:
break
;
}
return
MAX(
strlen
(column->name) + 1, len);
}
static
CS_RETCODE display_header(imp_dbh_t *imp_dbh, CS_INT numcols,
CS_DATAFMT *columns) {
dTHX;
CS_INT i;
CS_INT l;
CS_INT j;
CS_INT disp_len;
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
for
(i = 0; i < numcols; i++) {
disp_len = display_dlen(&columns[i]);
sv_catpv(DBIc_ERRSTR(imp_dbh), columns[i].name);
l = disp_len -
strlen
(columns[i].name);
for
(j = 0; j < l; j++) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
" "
);
}
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
for
(i = 0; i < numcols; i++) {
disp_len = display_dlen(&columns[i]);
l = disp_len - 1;
for
(j = 0; j < l; j++) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
"-"
);
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
" "
);
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
return
CS_SUCCEED;
}
void
syb_init(dbistate_t *dbistate) {
dTHX;
SV *sv;
CS_INT netio_type = CS_SYNC_IO;
STRLEN lna;
CS_INT outlen;
CS_RETCODE retcode = CS_FAIL;
CS_INT cs_ver;
CS_INT boolean = CS_FALSE;
DBIS = dbistate;
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_INIT (context_alloc_mutex);
#endif
#if 0
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
#if defined(CS_CURRENT_VERSION)
if
(retcode != CS_SUCCEED) {
cs_ver = CS_CURRENT_VERSION;
retcode = cs_ctx_alloc(cs_ver, &context);
}
#endif
#if defined(CS_VERSION_150)
if
(retcode != CS_SUCCEED) {
cs_ver = CS_VERSION_150;
retcode = cs_ctx_alloc(cs_ver, &context);
}
#endif
#if defined(CS_VERSION_125)
if
(retcode != CS_SUCCEED) {
cs_ver = CS_VERSION_125;
retcode = cs_ctx_alloc(cs_ver, &context);
}
#endif
#if defined(CS_VERSION_120)
if
(retcode != CS_SUCCEED) {
cs_ver = CS_VERSION_120;
retcode = cs_ctx_alloc(cs_ver, &context);
}
#endif
#if defined(CS_VERSION_110)
if
(retcode != CS_SUCCEED) {
cs_ver = CS_VERSION_110;
retcode = cs_ctx_alloc(cs_ver, &context);
}
#endif
if
(retcode != CS_SUCCEED) {
cs_ver = CS_VERSION_100;
retcode = cs_ctx_alloc(cs_ver, &context);
}
if
(retcode != CS_SUCCEED) {
croak(
"DBD::Sybase initialize: cs_ctx_alloc(%d) failed"
, cs_ver);
}
#if defined(CS_CURRENT_VERSION)
if
(cs_ver = CS_CURRENT_VERSION) {
BLK_VERSION = CS_CURRENT_VERSION;
}
#endif
#if defined(CS_VERSION_150)
if
(cs_ver == CS_VERSION_150) {
BLK_VERSION = BLK_VERSION_150;
}
#endif
#if defined(CS_VERSION_125)
if
(cs_ver == CS_VERSION_125) {
BLK_VERSION = BLK_VERSION_125;
}
#endif
#if defined(CS_VERSION_120)
if
(cs_ver == CS_VERSION_120) {
BLK_VERSION = BLK_VERSION_120;
}
#endif
#if defined(CS_VERSION_110)
if
(cs_ver == CS_VERSION_110) {
BLK_VERSION = BLK_VERSION_110;
}
#endif
if
(cs_ver == CS_VERSION_100) {
BLK_VERSION = BLK_VERSION_100;
}
#if USE_CSLIB_CB
if
(cs_config(context, CS_SET, CS_MESSAGE_CB,
(CS_VOID *)cslibmsg_cb, CS_UNUSED, NULL) != CS_SUCCEED) {
(
void
)cs_ctx_drop(context);
croak(
"DBD::Sybase initialize: cs_config(CS_MESSAGE_CB) failed"
);
}
#else
if
(cs_diag(context, CS_INIT, CS_UNUSED, CS_UNUSED, NULL) != CS_SUCCEED) {
warn(
"cs_diag(CS_INIT) failed"
);
}
#endif
#if defined(CS_EXTERNAL_CONFIG)
if
(cs_config(context, CS_SET, CS_EXTERNAL_CONFIG, &boolean, CS_UNUSED,
NULL) != CS_SUCCEED) {
}
#endif
if
((retcode = ct_init(context, cs_ver)) != CS_SUCCEED) {
#if 1
cs_ctx_drop(context);
#endif
context = NULL;
croak(
"DBD::Sybase initialize: ct_init(%d) failed"
, cs_ver);
}
if
((retcode = ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *) clientmsg_cb)) != CS_SUCCEED) {
croak(
"DBD::Sybase initialize: ct_callback(clientmsg) failed"
);
}
if
((retcode = ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB,
(CS_VOID *) servermsg_cb)) != CS_SUCCEED) {
croak(
"DBD::Sybase initialize: ct_callback(servermsg) failed"
);
}
if
((retcode = ct_config(context, CS_SET, CS_NETIO, &netio_type, CS_UNUSED,
NULL)) != CS_SUCCEED) {
croak(
"DBD::Sybase initialize: ct_config(netio) failed"
);
}
#if defined(MAX_CONNECT)
netio_type = MAX_CONNECT;
if
((retcode = ct_config(context, CS_SET, CS_MAX_CONNECT, &netio_type,
CS_UNUSED, NULL)) != CS_SUCCEED) {
croak(
"DBD::Sybase initialize: ct_config(max_connect) failed"
);
}
#endif
{
char
out[1024], *p;
retcode = ct_config(context, CS_GET, CS_VER_STRING, (CS_VOID*) out,
1024, &outlen);
if
((p =
strchr
(out,
'\n'
)))
*p = 0;
ocVersion = my_strdup(out);
}
if
((sv = perl_get_sv(
"0"
, FALSE))) {
char
*p;
strcpy
(scriptName, SvPV(sv, lna));
if
((p =
strrchr
(scriptName,
'/'
))) {
char
tmp[255];
++p;
strncpy
(tmp, p, 250);
strcpy
(scriptName, tmp);
}
if
(!
strcmp
(scriptName,
"-e"
)) {
strcpy
(scriptName,
"perl -e"
);
}
}
if
((sv = perl_get_sv(
"DBD::Sybase::hostname"
, FALSE))) {
strcpy
(hostname, SvPV(sv, lna));
}
if
(dbistate->debug >= 3) {
char
*p =
""
;
if
((sv = perl_get_sv(
"DBD::Sybase::VERSION"
, FALSE))) {
p = SvPV(sv, lna);
}
PerlIO_printf(dbistate->logfp,
" syb_init() -> DBD::Sybase %s initialized\n"
, p);
PerlIO_printf(dbistate->logfp,
" OpenClient version: %s\n"
,
ocVersion);
}
if
((retcode = cs_loc_alloc(context, &glocale)) != CS_SUCCEED) {
warn(
"cs_loc_alloc failed"
);
}
if
(retcode == CS_SUCCEED) {
if
((retcode = cs_locale(context, CS_SET, glocale, CS_LC_ALL,
(CS_CHAR*) NULL, CS_UNUSED, (CS_INT*) NULL)) != CS_SUCCEED) {
warn(
"cs_locale(CS_LC_ALL) failed"
);
}
}
if
(retcode == CS_SUCCEED) {
CS_INT type = CS_DATES_SHORT;
if
((retcode = cs_dt_info(context, CS_SET, glocale, CS_DT_CONVFMT,
CS_UNUSED, (CS_VOID*) &type, CS_SIZEOF(CS_INT), NULL))
!= CS_SUCCEED) {
warn(
"cs_dt_info() failed"
);
}
}
if
(retcode == CS_SUCCEED) {
if
((retcode = cs_config(context, CS_SET, CS_LOC_PROP, glocale,
CS_UNUSED, NULL)) != CS_SUCCEED) {
}
}
}
int
syb_thread_enabled(
void
) {
int
retcode = 0;
#if PERL_VERSION >= 8 && defined(_REENTRANT) && !defined(NO_THREADS)
retcode = 1;
#endif
return
retcode;
}
int
syb_set_timeout(
int
timeout) {
dTHX;
CS_RETCODE retcode;
if
(timeout <= 0) {
timeout = CS_NO_LIMIT;
}
if
(DBIS->debug >= 3) {
PerlIO_printf(DBILOGFP,
" syb_set_timeout() -> ct_config(CS_TIMEOUT,%d)\n"
, timeout);
}
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_LOCK (context_alloc_mutex);
#endif
if
((retcode = ct_config(context, CS_SET, CS_TIMEOUT, &timeout, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_TIMEOUT) failed"
);
}
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_UNLOCK (context_alloc_mutex);
#endif
return
retcode;
}
static
int
extractFromDsn(
char
*tag,
char
*source,
char
*dest,
int
size) {
char
*p =
strstr
(source, tag);
char
*q = dest;
if
(!p) {
return
0;
}
p +=
strlen
(tag);
while
(p && *p && *p !=
';'
&& --size) {
*q++ = *p++;
}
*q = 0;
return
1;
}
static
int
fetchAttrib(SV *attribs,
char
*key) {
dTHX;
if
(attribs) {
SV **svp;
if
((svp = hv_fetch((HV*) SvRV(attribs), key,
strlen
(key), 0)) != NULL) {
return
SvIV(*svp);
}
}
return
0;
}
static
SV * fetchSvAttrib(SV *attribs,
char
*key) {
dTHX;
if
(attribs) {
SV **svp;
if
((svp = hv_fetch((HV*) SvRV(attribs), key,
strlen
(key), 0)) != NULL) {
return
newSVsv(*svp);
}
}
return
NULL;
}
static
void
getBcpAttribs(imp_sth_t *imp_sth, SV *attribs) {
dTHX;
SV **svp;
#define BCP_ATTRIB "syb_bcp_attribs"
if
(!attribs || !SvOK(attribs)) {
return
;
}
if
((svp = hv_fetch((HV*) SvRV(attribs), BCP_ATTRIB,
strlen
(BCP_ATTRIB), 0)) != NULL) {
imp_sth->bcpFlag = 1;
imp_sth->bcpIdentityFlag = fetchAttrib(*svp,
"identity_flag"
);
imp_sth->bcpIdentityCol = fetchAttrib(*svp,
"identity_column"
);
}
}
int
syb_db_login(SV *dbh, imp_dbh_t *imp_dbh,
char
*dsn,
char
*uid,
char
*pwd, SV *attribs) {
dTHX;
int
retval;
imp_dbh->server[0] = 0;
imp_dbh->charset[0] = 0;
imp_dbh->packetSize[0] = 0;
imp_dbh->language[0] = 0;
imp_dbh->ifile[0] = 0;
imp_dbh->loginTimeout[0] = 0;
imp_dbh->timeout[0] = 0;
imp_dbh->hostname[0] = 0;
imp_dbh->scriptName[0] = 0;
imp_dbh->database[0] = 0;
imp_dbh->curr_db[0] = 0;
imp_dbh->encryptPassword[0] = 0;
imp_dbh->showSql = 0;
imp_dbh->showEed = 0;
imp_dbh->flushFinish = FLUSH_FINISH;
imp_dbh->doRealTran = NO_CHAINED_TRAN;
imp_dbh->chainedSupported = 1;
imp_dbh->quotedIdentifier = 0;
imp_dbh->rowcount = 0;
imp_dbh->doProcStatus = PROC_STATUS;
imp_dbh->useBin0x = 0;
imp_dbh->binaryImage = 0;
imp_dbh->deadlockRetry = 0;
imp_dbh->deadlockSleep = 0;
imp_dbh->deadlockVerbose = 0;
imp_dbh->nsqlNoStatus = 0;
imp_dbh->noChildCon = 0;
imp_dbh->failedDbUseFatal = fetchAttrib(attribs,
"syb_failed_db_fatal"
);
imp_dbh->bindEmptyStringNull = fetchAttrib(attribs,
"syb_bind_empty_string_as_null"
);
imp_dbh->err_handler = fetchSvAttrib(attribs,
"syb_err_handler"
);
imp_dbh->alwaysForceFailure = 1;
imp_dbh->kerberosPrincipal[0] = 0;
imp_dbh->kerbGetTicket = fetchSvAttrib(attribs,
"syb_kerberos_serverprincipal"
);
imp_dbh->disconnectInChild = fetchAttrib(attribs,
"syb_disconnect_in_child"
);
imp_dbh->host[0] = 0;
imp_dbh->port[0] = 0;
imp_dbh->enable_utf8 = fetchAttrib(attribs,
"syb_enable_utf8"
);
#if !defined(DBD_CAN_HANDLE_UTF8)
if
(imp_dbh->enable_utf8) {
warn(
"The current version of OpenClient can't handle utf8 data."
);
}
imp_dbh->enable_utf8 = 0;
#endif
imp_dbh->blkLogin[0] = 0;
imp_dbh->dateFmt = 0;
imp_dbh->inUse = 0;
imp_dbh->init_done = 0;
if
(
strchr
(dsn,
'='
)) {
extractFromDsn(
"server="
, dsn, imp_dbh->server, 64);
extractFromDsn(
"charset="
, dsn, imp_dbh->charset, 64);
extractFromDsn(
"database="
, dsn, imp_dbh->database, 260);
extractFromDsn(
"packetSize="
, dsn, imp_dbh->packetSize, 64);
extractFromDsn(
"language="
, dsn, imp_dbh->language, 64);
extractFromDsn(
"interfaces="
, dsn, imp_dbh->ifile, 255);
extractFromDsn(
"loginTimeout="
, dsn, imp_dbh->loginTimeout, 64);
extractFromDsn(
"timeout="
, dsn, imp_dbh->timeout, 64);
extractFromDsn(
"scriptName="
, dsn, imp_dbh->scriptName, 255);
extractFromDsn(
"hostname="
, dsn, imp_dbh->hostname, 255);
extractFromDsn(
"tdsLevel="
, dsn, imp_dbh->tdsLevel, 30);
extractFromDsn(
"encryptPassword="
, dsn, imp_dbh->encryptPassword, 10);
extractFromDsn(
"kerberos="
, dsn, imp_dbh->kerberosPrincipal, 255);
extractFromDsn(
"host="
, dsn, imp_dbh->host, 64);
extractFromDsn(
"port="
, dsn, imp_dbh->port, 20);
extractFromDsn(
"maxConnect="
, dsn, imp_dbh->maxConnect, 25);
extractFromDsn(
"sslCAFile="
, dsn, imp_dbh->sslCAFile, 255);
extractFromDsn(
"bulkLogin="
, dsn, imp_dbh->blkLogin, 10);
extractFromDsn(
"tds_keepalive="
, dsn, imp_dbh->tds_keepalive, 10);
extractFromDsn(
"serverType="
, dsn, imp_dbh->serverType, 30);
}
else
{
strncpy
(imp_dbh->server, dsn, 64);
imp_dbh->server[63] = 0;
}
strncpy
(imp_dbh->uid, uid, UID_PWD_SIZE);
imp_dbh->uid[UID_PWD_SIZE - 1] = 0;
strncpy
(imp_dbh->pwd, pwd, UID_PWD_SIZE);
imp_dbh->pwd[UID_PWD_SIZE - 1] = 0;
sv_setpv(DBIc_ERRSTR(imp_dbh),
""
);
if
(imp_dbh->kerbGetTicket) {
fetchKerbTicket(imp_dbh);
}
imp_dbh->pid = getpid();
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_LOCK(context_alloc_mutex);
#endif
if
((imp_dbh->connection = syb_db_connect(imp_dbh)) == NULL) {
retval = 0;
}
else
{
retval = 1;
}
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_UNLOCK(context_alloc_mutex);
#endif
if
(!retval) {
return
retval;
}
if
(!imp_dbh->serverType[0] || !strncasecmp(imp_dbh->serverType,
"ase"
, 3)) {
get_server_version(dbh, imp_dbh, imp_dbh->connection);
}
DBIc_IMPSET_on(imp_dbh);
DBIc_ACTIVE_on(imp_dbh);
DBIc_LongReadLen(imp_dbh) = 32768;
return
1;
}
static
CS_CONNECTION *syb_db_connect(imp_dbh_t *imp_dbh) {
dTHR;
CS_RETCODE retcode;
CS_CONNECTION *connection = NULL;
char
ofile[255];
int
len;
if
(imp_dbh->maxConnect[0]) {
const
char
*
const
s = imp_dbh->maxConnect;
int
i;
i =
atoi
(s);
if
(i < 1) {
warn(
"maxConnect must be positive, not '%s'"
, s);
return
0;
}
#if defined(CS_MAX_CONNECT)
if
((retcode = ct_config(context, CS_SET, CS_MAX_CONNECT, (CS_VOID*) &i, CS_UNUSED, NULL)) != CS_SUCCEED) {
croak(
"ct_config(max_connect) failed"
);
}
#else
warn(
"ct_config(max_connect) not supported"
);
#endif
}
if
(imp_dbh->ifile[0]) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_config(CS_IFILE,%s)\n"
,
imp_dbh->ifile);
}
if
((retcode = ct_config(context, CS_GET, CS_IFILE, ofile, 255, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_GET, CS_IFILE) failed"
);
}
if
(retcode == CS_SUCCEED) {
if
((retcode = ct_config(context, CS_SET, CS_IFILE, imp_dbh->ifile, CS_NULLTERM, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_IFILE, %s) failed"
, imp_dbh->ifile);
return
NULL;
}
}
}
if
(imp_dbh->loginTimeout[0]) {
int
timeout =
atoi
(imp_dbh->loginTimeout);
if
(timeout <= 0) {
timeout = 60;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_config(CS_LOGIN_TIMEOUT,%d)\n"
,
timeout);
}
if
((retcode = ct_config(context, CS_SET, CS_LOGIN_TIMEOUT, &timeout, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_LOGIN_TIMEOUT) failed"
);
}
}
if
(imp_dbh->timeout[0]) {
int
timeout =
atoi
(imp_dbh->timeout);
if
(timeout <= 0) {
timeout = CS_NO_LIMIT;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_config(CS_TIMEOUT,%d)\n"
, timeout);
}
if
((retcode = ct_config(context, CS_SET, CS_TIMEOUT, &timeout, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_TIMEOUT) failed"
);
}
}
if
(imp_dbh->language[0] == 0 && imp_dbh->charset[0] == 0) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> using global CS_LOCALE data\n"
);
}
}
else
{
CS_INT type = CS_DATES_SHORT;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> using private CS_LOCALE data\n"
);
}
if
((retcode = cs_loc_alloc(context, &imp_dbh->locale) != CS_SUCCEED)) {
warn(
"cs_loc_alloc failed"
);
return
0;
}
if
(cs_locale(context, CS_SET, imp_dbh->locale, CS_LC_ALL, (CS_CHAR*) NULL, CS_UNUSED, (CS_INT*) NULL)
!= CS_SUCCEED) {
warn(
"cs_locale(CS_LC_ALL) failed"
);
return
0;
}
if
(imp_dbh->language[0] != 0) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> cs_locale(CS_SYB_LANG,%s)\n"
,
imp_dbh->language);
}
if
(cs_locale(context, CS_SET, imp_dbh->locale, CS_SYB_LANG,
(CS_CHAR*) imp_dbh->language, CS_NULLTERM, (CS_INT*) NULL)
!= CS_SUCCEED) {
warn(
"cs_locale(CS_SYB_LANG, %s) failed"
, imp_dbh->language);
return
0;
}
}
if
(imp_dbh->charset[0] != 0) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> cs_locale(CS_SYB_CHARSET,%s)\n"
,
imp_dbh->charset);
}
if
(cs_locale(context, CS_SET, imp_dbh->locale, CS_SYB_CHARSET,
(CS_CHAR*) imp_dbh->charset, CS_NULLTERM, (CS_INT*) NULL)
!= CS_SUCCEED) {
warn(
"cs_locale(CS_SYB_CHARSET, %s) failed"
, imp_dbh->charset);
return
0;
}
}
if
(cs_dt_info(context, CS_SET, imp_dbh->locale, CS_DT_CONVFMT,
CS_UNUSED, (CS_VOID*) &type, CS_SIZEOF(CS_INT), NULL)
!= CS_SUCCEED) {
warn(
"cs_dt_info() failed"
);
}
}
#if defined(CS_CON_KEEPALIVE)
if
(imp_dbh->tds_keepalive[0]) {
int
tds_keepalive =
atoi
(imp_dbh->tds_keepalive);
if
(tds_keepalive != 1) {
tds_keepalive = 0;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"syb_db_login() -> ct_config(CS_CON_KEEPALIVE,%d)\n"
, tds_keepalive);
}
if
((retcode = ct_config(context, CS_SET, CS_CON_KEEPALIVE, &tds_keepalive, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_CON_KEEPALIVE) failed"
);
}
}
#endif
if
((retcode = ct_con_alloc(context, &connection)) != CS_SUCCEED) {
warn(
"ct_con_alloc failed"
);
return
0;
}
if
(imp_dbh->locale) {
if
(ct_con_props(connection, CS_SET, CS_LOC_PROP,
(CS_VOID*)imp_dbh->locale, CS_UNUSED, (CS_INT*)NULL)
!= CS_SUCCEED) {
warn(
"ct_con_props(CS_LOC_PROP) failed"
);
return
0;
}
}
if
((retcode = ct_con_props(connection, CS_SET, CS_USERDATA, &imp_dbh,
CS_SIZEOF(imp_dbh), NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_USERDATA) failed"
);
return
0;
}
if
(imp_dbh->tdsLevel[0] != 0) {
CS_INT value = 0;
if
(strEQ(imp_dbh->tdsLevel,
"CS_TDS_40"
)) {
value = CS_TDS_40;
}
else
if
(strEQ(imp_dbh->tdsLevel,
"CS_TDS_42"
)) {
value = CS_TDS_42;
}
else
if
(strEQ(imp_dbh->tdsLevel,
"CS_TDS_46"
)) {
value = CS_TDS_46;
}
else
if
(strEQ(imp_dbh->tdsLevel,
"CS_TDS_495"
)) {
value = CS_TDS_495;
}
else
if
(strEQ(imp_dbh->tdsLevel,
"CS_TDS_50"
)) {
value = CS_TDS_50;
}
if
(value) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_con_props(CS_TDS_VERSION,%s)\n"
,
imp_dbh->tdsLevel);
}
if
(ct_con_props(connection, CS_SET, CS_TDS_VERSION,
(CS_VOID*)&value, CS_UNUSED, (CS_INT*)NULL) != CS_SUCCEED) {
warn(
"ct_con_props(CS_TDS_VERSION, %s) failed"
, imp_dbh->tdsLevel);
}
}
else
{
warn(
"Unkown tdsLevel value %s found"
, imp_dbh->tdsLevel);
}
}
if
(imp_dbh->packetSize[0] != 0) {
int
i =
atoi
(imp_dbh->packetSize);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_con_props(CS_PACKETSIZE,%d)\n"
, i);
}
if
(ct_con_props(connection, CS_SET, CS_PACKETSIZE, (CS_VOID*)&i,
CS_UNUSED, (CS_INT*)NULL) != CS_SUCCEED) {
warn(
"ct_con_props(CS_PACKETSIZE, %d) failed"
, i);
return
0;
}
}
#if defined(CS_SEC_NETWORKAUTH)
if
(imp_dbh->kerberosPrincipal[0] == 0) {
#endif
if
(retcode == CS_SUCCEED && *imp_dbh->uid) {
if
((retcode = ct_con_props(connection, CS_SET, CS_USERNAME,
imp_dbh->uid, CS_NULLTERM, NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_USERNAME) failed"
);
return
0;
}
}
if
(retcode == CS_SUCCEED && *imp_dbh->pwd) {
if
((retcode = ct_con_props(connection, CS_SET, CS_PASSWORD,
imp_dbh->pwd, CS_NULLTERM, NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_PASSWORD) failed"
);
return
0;
}
}
#if defined(CS_SEC_NETWORKAUTH)
}
else
{
CS_INT i = CS_TRUE;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_con_props(CS_SERVERPRINCIPAL,%s)\n"
,
imp_dbh->kerberosPrincipal);
}
if
((retcode = ct_con_props(connection, CS_SET, CS_SEC_NETWORKAUTH,
(CS_VOID *) &i, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SEC_NETWORKAUTH) failed"
);
return
0;
}
if
((retcode = ct_con_props(connection, CS_SET, CS_SEC_SERVERPRINCIPAL,
imp_dbh->kerberosPrincipal, CS_NULLTERM, NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SEC_SERVERPRINCIPAL) failed"
);
return
0;
}
}
#endif
if
(retcode == CS_SUCCEED) {
if
((retcode = ct_con_props(connection, CS_SET, CS_APPNAME,
*imp_dbh->scriptName ? imp_dbh->scriptName : scriptName,
CS_NULLTERM, NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_APPNAME, %s) failed"
, imp_dbh->scriptName);
return
0;
}
if
((retcode = ct_con_props(connection, CS_SET, CS_HOSTNAME,
*imp_dbh->hostname ? imp_dbh->hostname : hostname, CS_NULLTERM,
NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_HOSTNAME, %s) failed"
, imp_dbh->hostname);
return
0;
}
}
if
(retcode == CS_SUCCEED) {
if
(imp_dbh->encryptPassword[0] != 0) {
int
level =
atoi
(imp_dbh->encryptPassword);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> encryptPassword = %d\n"
,level);
}
int
i = CS_TRUE;
if
(level != 0) {
if
((retcode = ct_con_props(connection, CS_SET, CS_SEC_ENCRYPTION,
(CS_VOID*)&i, CS_UNUSED, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SEC_ENCRYPTION, true) failed"
);
return
0;
}
}
#if defined(CS_SEC_EXTENDED_ENCRYPTION)
if
(level > 1) {
CS_INT extendedEncryption = CS_TRUE;
CS_INT nonEncryptionRetry = CS_FALSE;
if
((retcode = ct_con_props(connection, CS_SET,
CS_SEC_EXTENDED_ENCRYPTION,
&extendedEncryption, CS_UNUSED, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SEC_EXTENDED_ENCRYPTION, true) failed"
);
return
0;
}
if
((retcode = ct_con_props(connection, CS_SET,
CS_SEC_NON_ENCRYPTION_RETRY,
&nonEncryptionRetry, CS_UNUSED, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SEC_NON_ENCRYPTION_RETRY, false) failed"
);
return
0;
}
}
#endif
}
}
#if defined(CS_PROP_SSL_CA)
if
(retcode == CS_SUCCEED) {
if
(imp_dbh->sslCAFile[0] != 0) {
if
((retcode = ct_con_props(connection, CS_SET, CS_PROP_SSL_CA,
imp_dbh->sslCAFile,
CS_NULLTERM, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_PROP_SSL_CA, %s) failed"
, imp_dbh->sslCAFile);
return
0;
}
}
}
#endif
if
(retcode == CS_SUCCEED && imp_dbh->host[0] && imp_dbh->port[0]) {
#if defined(CS_SERVERADDR)
char
buff[255];
sprintf
(buff,
"%.64s %.20s"
, imp_dbh->host, imp_dbh->port);
if
((retcode = ct_con_props(connection, CS_SET, CS_SERVERADDR,
(CS_VOID*)buff,
CS_NULLTERM, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_SERVERADDR) failed"
);
return
0;
}
#else
croak(
"This version of OpenClient doesn't support CS_SERVERADDR"
);
#endif
}
if
(retcode == CS_SUCCEED && imp_dbh->blkLogin[0] != 0) {
CS_INT flag = CS_TRUE;
if
((retcode = ct_con_props(connection, CS_SET, CS_BULK_LOGIN,
(CS_VOID*)&flag, CS_UNUSED, (CS_INT*)NULL)) != CS_SUCCEED) {
warn(
"ct_con_props(CS_BULK_LOGIN) failed"
);
return
0;
}
}
if
(retcode == CS_SUCCEED) {
len = *imp_dbh->server == 0 ? 0 : CS_NULLTERM;
if
((retcode = ct_connect(connection, imp_dbh->server, len)) != CS_SUCCEED) {
if
(glocale != NULL) {
cs_loc_drop(context, glocale);
}
ct_con_drop(connection);
return
0;
}
}
if
(imp_dbh->ifile[0]) {
if
((retcode = ct_config(context, CS_SET, CS_IFILE, ofile, CS_NULLTERM,
NULL)) != CS_SUCCEED) {
warn(
"ct_config(CS_SET, CS_IFILE, %s) failed"
, ofile);
}
}
if
(imp_dbh->database[0] || imp_dbh->curr_db[0]) {
int
ret = syb_db_use(imp_dbh, connection);
if
(imp_dbh->failedDbUseFatal && ret < 0) {
ct_close(connection, CS_FORCE_CLOSE);
if
(glocale != NULL) {
cs_loc_drop(context, glocale);
}
ct_con_drop(connection);
return
0;
}
}
if
(imp_dbh->chainedSupported) {
CS_BOOL value = CS_FALSE;
imp_dbh->optSupported = 1;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> checking for chained transactions\n"
);
}
retcode = ct_options(connection, CS_SET, CS_OPT_CHAINXACTS, &value,
CS_UNUSED, NULL);
if
(retcode == CS_FAIL) {
imp_dbh->doRealTran = 1;
imp_dbh->chainedSupported = 0;
}
#if 0
if
(imp_dbh->lasterr == 17001) {
imp_dbh->optSupported = 0;
}
else
{
imp_dbh->optSupported = 1;
}
#endif
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> ct_option is %ssupported\n"
,
imp_dbh->optSupported == 1 ?
""
:
"not "
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_login() -> chained transactions are %s supported\n"
,
retcode == CS_FAIL ?
"not"
:
""
);
}
}
#if 0
if
(!imp_dbh->optSupported) {
imp_dbh->chainedSupported = 0;
imp_dbh->doRealTran = 1;
}
#endif
if
(imp_dbh->connection) {
if
(imp_dbh->quotedIdentifier && imp_dbh->optSupported) {
CS_INT value = 1;
retcode = ct_options(connection, CS_SET, CS_OPT_QUOTED_IDENT,
&value, CS_UNUSED, NULL);
if
(retcode != CS_SUCCEED) {
warn(
"Setting of CS_OPT_QUOTED_IDENT failed."
);
}
}
#if defined(CS_OPT_ROWCOUNT)
if
(imp_dbh->rowcount && imp_dbh->optSupported) {
CS_INT value = imp_dbh->rowcount;
retcode = ct_options(connection, CS_SET, CS_OPT_ROWCOUNT,
&value, CS_UNUSED, NULL);
if
(retcode != CS_SUCCEED) {
warn(
"Setting of CS_OPT_ROWCOUNT failed."
);
}
}
#endif
}
return
connection;
}
static
int
syb_db_use(imp_dbh_t *imp_dbh, CS_CONNECTION *connection) {
CS_COMMAND *cmd = syb_alloc_cmd(imp_dbh, connection, 1);
CS_RETCODE ret;
CS_INT restype;
char
statement[255];
int
retval = 0;
char
*db;
if
(!cmd) {
return
-1;
}
if
(DBIc_ACTIVE(imp_dbh) && imp_dbh->curr_db[0]) {
db = imp_dbh->curr_db;
}
else
{
db = imp_dbh->database;
}
sprintf
(statement,
"use [%s]"
, db);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_use() -> ct_command(%s)\n"
, statement);
}
ret = ct_command(cmd, CS_LANG_CMD, statement, CS_NULLTERM, CS_UNUSED);
if
(ret != CS_SUCCEED) {
warn(
"ct_command failed for '%s'"
, statement);
return
-1;
}
ret = ct_send(cmd);
if
(ret != CS_SUCCEED) {
warn(
"ct_send failed for '%s'"
, statement);
return
-1;
}
while
((ret = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_use() -> ct_results(%d)\n"
, restype);
}
if
(restype == CS_CMD_FAIL) {
warn(
"DBD::Sybase - can't change context to database %s\n"
, imp_dbh->database);
retval = -1;
}
}
ct_cmd_drop(cmd);
return
retval;
}
static
int
extract_version(
char
*buff,
char
*ver) {
if
(!
strncmp
(buff,
"Adaptive"
, 8) || !
strncmp
(buff,
"SQL Server"
, 10)) {
char
*p, *s;
if
((p =
strchr
(buff,
'/'
))) {
++p;
if
((s =
strchr
(p,
'/'
))) {
int
len = s - p;
if
(len >= VERSION_SIZE) {
len = VERSION_SIZE;
}
strncpy
(ver, p, len);
}
else
{
strncpy
(ver, p, 10);
}
}
}
else
if
(!
strncmp
(buff,
"Microsoft SQL Server"
, 20)) {
strcpy
(ver,
"MS-SQL"
);
}
else
{
strcpy
(ver,
"Unknown"
);
}
return
0;
}
static
int
get_server_version(SV *dbh, imp_dbh_t *imp_dbh, CS_CONNECTION *con) {
CS_COMMAND *cmd = syb_alloc_cmd(imp_dbh, con, 1);
CS_RETCODE ret;
CS_INT restype;
char
statement[60];
char
buff[255];
char
version[
sizeof
(imp_dbh->serverVersion)];
int
retval = 0;
char
*db;
if
(!cmd) {
return
-1;
}
memset
(version, 0,
sizeof
(imp_dbh->serverVersion));
sprintf
(statement,
"select @@version"
);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" get_server_version() -> ct_command(%s)\n"
, statement);
}
ret = ct_command(cmd, CS_LANG_CMD, statement, CS_NULLTERM, CS_UNUSED);
if
(ret != CS_SUCCEED) {
warn(
"ct_command failed for '%s'"
, statement);
return
-1;
}
ret = ct_send(cmd);
if
(ret != CS_SUCCEED) {
warn(
"ct_send failed for '%s'"
, statement);
return
-1;
}
while
((ret = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" get_server_version() -> ct_results(%d)\n"
, restype);
}
if
(restype == CS_CMD_FAIL) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" get_server_version() -> Can't get version value\n"
);
}
retval = -1;
}
if
(restype == CS_ROW_RESULT) {
CS_DATAFMT datafmt;
CS_INT len;
CS_SMALLINT indicator;
CS_INT retcode;
CS_INT rows;
ct_describe(cmd, 1, &datafmt);
datafmt.format = CS_FMT_NULLTERM;
datafmt.maxlength =
sizeof
(buff);
ct_bind(cmd, 1, &datafmt, buff, &len, &indicator);
while
((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &rows)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" get_server_version() -> version = %s\n"
, buff);
}
strncpy
(imp_dbh->serverVersionString, buff,
sizeof
(imp_dbh->serverVersionString));
extract_version(buff, version);
strncpy
(imp_dbh->serverVersion, version,
sizeof
(imp_dbh->serverVersion));
if
(!
strncmp
(
"MS-SQL"
, version, 6)) {
imp_dbh->isMSSql = 1;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" get_server_version() -> version = %s\n"
,
imp_dbh->serverVersion);
}
}
}
}
ct_cmd_drop(cmd);
return
retval;
}
int
syb_ping(SV *dbh, imp_dbh_t *imp_dbh) {
dTHX;
CS_COMMAND *cmd;
CS_RETCODE ret;
CS_INT restype;
char
*statement =
"/* ping */"
;
if
(DBIc_ACTIVE_KIDS(imp_dbh)) {
DBIh_SET_ERR_CHAR(dbh, (imp_xxh_t *)imp_dbh, NULL, -1,
"Can't call ping() with active statement handles"
,
NULL, NULL);
return
-1;
}
DBIh_CLEAR_ERROR(imp_dbh);
cmd = syb_alloc_cmd(imp_dbh, imp_dbh->connection, 0
);
if
(!cmd) {
return
0;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_ping() -> ct_command(%s)\n"
, statement);
}
ret = ct_command(cmd, CS_LANG_CMD, statement, CS_NULLTERM, CS_UNUSED);
if
(ret != CS_SUCCEED) {
ct_cmd_drop(cmd);
return
0;
}
ret = ct_send(cmd);
if
(ret != CS_SUCCEED) {
ct_cmd_drop(cmd);
return
0;
}
while
((ret = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_ping() -> ct_results(%d)\n"
, restype);
}
if
(imp_dbh->isDead) {
ct_cmd_drop(cmd);
return
0;
}
}
DBIh_CLEAR_ERROR(imp_dbh);
ct_cmd_drop(cmd);
return
1;
}
int
syb_db_date_fmt(SV *dbh, imp_dbh_t *imp_dbh,
char
*fmt) {
CS_INT type;
if
(!
strncmp
(fmt,
"ISO_strict"
, 10)) {
imp_dbh->dateFmt = 2;
return
1;
}
if
(!
strcmp
(fmt,
"ISO"
)) {
imp_dbh->dateFmt = 1;
return
1;
}
imp_dbh->dateFmt = 0;
if
(!
strcmp
(fmt,
"LONG"
)) {
type = CS_DATES_LONG;
}
else
if
(!
strcmp
(fmt,
"SHORT"
)) {
type = CS_DATES_SHORT;
}
else
if
(!
strcmp
(fmt,
"DMY4_YYYY"
)) {
type = CS_DATES_DMY4_YYYY;
}
else
if
(!
strcmp
(fmt,
"MDY1_YYYY"
)) {
type = CS_DATES_MDY1_YYYY;
}
else
if
(!
strcmp
(fmt,
"DMY1_YYYY"
)) {
type = CS_DATES_DMY1_YYYY;
}
else
if
(!
strcmp
(fmt,
"DMY2_YYYY"
)) {
type = CS_DATES_DMY2_YYYY;
}
else
if
(!
strcmp
(fmt,
"YMD3_YYYY"
)) {
type = CS_DATES_YMD3_YYYY;
}
else
if
(!
strcmp
(fmt,
"HMS"
)) {
type = CS_DATES_HMS;
}
else
if
(!
strcmp
(fmt,
"LONGMS"
)) {
#if defined(CS_DATES_LONGUSA_YYYY)
type = CS_DATES_LONGUSA_YYYY;
#else
type = CS_DATES_LONG;
#endif
}
else
{
warn(
"Invalid format %s in _date_fmt"
, fmt);
return
0;
}
if
(cs_dt_info(context, CS_SET, LOCALE(imp_dbh), CS_DT_CONVFMT, CS_UNUSED,
(CS_VOID*) &type, CS_SIZEOF(CS_INT), NULL) != CS_SUCCEED) {
warn(
"cs_dt_info() failed"
);
return
0;
}
return
1;
}
static
int
syb_get_date_fmt(imp_dbh_t *imp_dbh,
char
*fmt) {
CS_INT type;
char
*p;
if
(imp_dbh->dateFmt == 2) {
strcpy
(fmt,
"ISO_strict"
);
return
1;
}
if
(imp_dbh->dateFmt == 1) {
strcpy
(fmt,
"ISO"
);
return
1;
}
if
(cs_dt_info(context, CS_GET, LOCALE(imp_dbh), CS_DT_CONVFMT, CS_UNUSED,
(CS_VOID*) &type, CS_SIZEOF(CS_INT), NULL) != CS_SUCCEED) {
warn(
"cs_dt_info() failed"
);
return
0;
}
switch
(type) {
case
CS_DATES_LONG:
p =
"LONG"
;
break
;
case
CS_DATES_SHORT:
p =
"SHORT"
;
break
;
case
CS_DATES_DMY4_YYYY:
p =
"DMY4_YYYY"
;
break
;
case
CS_DATES_MDY1_YYYY:
p =
"MDY1_YYYY"
;
break
;
case
CS_DATES_DMY1_YYYY:
p =
"DMY1_YYYY"
;
break
;
case
CS_DATES_DMY2_YYYY:
p =
"DMY2_YYYY"
;
break
;
case
CS_DATES_YMD3_YYYY:
p =
"YMD3_YYYY"
;
break
;
case
CS_DATES_HMS:
p =
"HMS"
;
break
;
default
:
p =
"Unknown"
;
break
;
}
strcpy
(fmt, p);
return
1;
}
int
syb_discon_all(SV *drh, imp_drh_t *imp_drh) {
return
1;
}
#if defined(NO_BLK)
static
int
syb_blk_done(imp_sth_t *imp_sth, CS_INT type)
{
return
1;
}
#else
static
int
syb_blk_done(imp_sth_t *imp_sth, CS_INT type) {
CS_RETCODE ret;
if
(type == CS_BLK_BATCH && !imp_sth->bcpRows) {
return
1;
}
ret = blk_done(imp_sth->bcp_desc, type, &imp_sth->numRows);
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" syb_blk_done -> blk_done(%d, %d) = %d\n"
,
type, imp_sth->numRows, ret);
}
if
(ret == CS_SUCCEED) {
if
(type == CS_BLK_CANCEL) {
imp_sth->bcpRows = -1;
}
else
{
imp_sth->bcpRows = 0;
}
}
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" syb_blk_done(%d) -> ret = %d, rows = %d\n"
, type, ret,
imp_sth->numRows);
}
return
ret == CS_SUCCEED;
}
#endif
int
syb_db_commit(SV *dbh, imp_dbh_t *imp_dbh) {
CS_COMMAND *cmd;
char
buff[128];
CS_INT restype;
CS_RETCODE retcode;
int
failFlag = 0;
if
(imp_dbh->imp_sth && imp_dbh->imp_sth->bcpFlag) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_commit() -> bcp op, calling syb_blk_done()\n"
);
}
return
syb_blk_done(imp_dbh->imp_sth, CS_BLK_BATCH);
}
if
(imp_dbh->doRealTran && !imp_dbh->inTransaction) {
return
1;
}
if
(DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
warn(
"commit ineffective with AutoCommit"
);
return
1;
}
cmd = syb_alloc_cmd(imp_dbh, imp_dbh->connection, 1);
if
(imp_dbh->doRealTran) {
sprintf
(buff,
"\nCOMMIT TRAN %s\n"
, imp_dbh->tranName);
}
else
{
strcpy
(buff,
"\nCOMMIT TRAN\n"
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_commit() -> ct_command(%s)\n"
, buff);
}
retcode = ct_command(cmd, CS_LANG_CMD, buff, CS_NULLTERM, CS_UNUSED);
if
(retcode != CS_SUCCEED) {
return
0;
}
if
(ct_send(cmd) != CS_SUCCEED) {
return
0;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_commit() -> ct_send() OK\n"
);
}
while
((retcode = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_commit() -> ct_results(%d) == %d\n"
, restype,
retcode);
}
if
(restype == CS_CMD_FAIL) {
failFlag = 1;
}
}
ct_cmd_drop(cmd);
imp_dbh->inTransaction = 0;
return
!failFlag;
}
int
syb_db_rollback(SV *dbh, imp_dbh_t *imp_dbh) {
CS_COMMAND *cmd;
char
buff[128];
CS_INT restype;
CS_RETCODE retcode;
int
failFlag = 0;
if
(imp_dbh->imp_sth && imp_dbh->imp_sth->bcpFlag) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_rollback() -> bcp op, calling syb_blk_done()\n"
);
}
return
syb_blk_done(imp_dbh->imp_sth, CS_BLK_CANCEL);
}
if
(imp_dbh->doRealTran && !imp_dbh->inTransaction) {
return
1;
}
if
(DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
warn(
"rollback ineffective with AutoCommit"
);
return
1;
}
cmd = syb_alloc_cmd(imp_dbh, imp_dbh->connection, 1);
if
(imp_dbh->doRealTran) {
sprintf
(buff,
"\nROLLBACK TRAN %s\n"
, imp_dbh->tranName);
}
else
{
strcpy
(buff,
"\nROLLBACK TRAN\n"
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_rollback() -> ct_command(%s)\n"
, buff);
}
retcode = ct_command(cmd, CS_LANG_CMD, buff, CS_NULLTERM, CS_UNUSED);
if
(retcode != CS_SUCCEED) {
return
0;
}
if
(ct_send(cmd) != CS_SUCCEED) {
return
0;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_rollback() -> ct_send() OK\n"
);
}
while
((retcode = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_rollback() -> ct_results(%d) == %d\n"
, restype,
retcode);
}
if
(restype == CS_CMD_FAIL) {
failFlag = 1;
}
}
ct_cmd_drop(cmd);
imp_dbh->inTransaction = 0;
return
!failFlag;
}
static
int
syb_db_opentran(SV *dbh, imp_dbh_t *imp_dbh) {
CS_COMMAND *cmd;
char
buff[128];
CS_INT restype;
CS_RETCODE retcode;
int
failFlag = 0;
if
(DBIc_is(imp_dbh, DBIcf_AutoCommit) || imp_dbh->inTransaction) {
return
1;
}
cmd = syb_alloc_cmd(imp_dbh, imp_dbh->connection, 1);
sprintf
(imp_dbh->tranName,
"DBI%x"
, (
void
*)imp_dbh);
sprintf
(buff,
"\nBEGIN TRAN %s\n"
, imp_dbh->tranName);
retcode = ct_command(cmd, CS_LANG_CMD, buff, CS_NULLTERM, CS_UNUSED);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_opentran() -> ct_command(%s) = %d\n"
, buff, retcode);
}
if
(retcode != CS_SUCCEED) {
return
0;
}
retcode = ct_send(cmd);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_opentran() -> ct_send() = %d\n"
, retcode);
}
if
(retcode != CS_SUCCEED) {
return
0;
}
while
((retcode = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_opentran() -> ct_results(%d) == %d\n"
, restype,
retcode);
}
if
(restype == CS_CMD_FAIL) {
failFlag = 1;
}
}
ct_cmd_drop(cmd);
if
(!failFlag) {
imp_dbh->inTransaction = 1;
}
return
!failFlag;
}
int
syb_db_disconnect(SV *dbh, imp_dbh_t *imp_dbh) {
dTHX;
CS_RETCODE retcode;
if
(imp_dbh->disconnectInChild == 0 && imp_dbh->pid != getpid()) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" syb_db_disconnect() -> imp_dbh->pid (%d) != pid (%d) - not closing connection\n"
,
imp_dbh->pid, getpid());
}
return
0;
}
#if ROLLBACK_ON_EXIT
if
(imp_dbh->isDead == 0) {
if
(!DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
syb_db_rollback(dbh, imp_dbh);
}
}
#endif
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_disconnect() -> ct_close()\n"
);
}
if
((retcode = ct_close(imp_dbh->connection, CS_FORCE_CLOSE)) != CS_SUCCEED) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_disconnect(): ct_close() failed\n"
);
}
if
(imp_dbh->locale && (retcode = cs_loc_drop(context, imp_dbh->locale)) != CS_SUCCEED) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_disconnect(): cs_loc_drop() failed\n"
);
}
if
((retcode = ct_con_drop(imp_dbh->connection)) != CS_SUCCEED) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_disconnect(): ct_con_drop() failed\n"
);
}
DBIc_ACTIVE_off(imp_dbh);
return
1;
}
void
syb_db_destroy(SV *dbh, imp_dbh_t *imp_dbh) {
if
(DBIc_ACTIVE(imp_dbh)) {
syb_db_disconnect(dbh, imp_dbh);
}
DBIc_IMPSET_off(imp_dbh);
}
int
syb_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) {
dTHX;
STRLEN kl;
int
on;
char
*key = SvPV(keysv, kl);
if
(kl == 15 && strEQ(key,
"syb_chained_txn"
)) {
on = SvTRUE(valuesv);
if
(imp_dbh->chainedSupported) {
int
autocommit = DBIc_is(imp_dbh, DBIcf_AutoCommit);
if
(!autocommit && !imp_dbh->isMSSql) {
syb_db_commit(dbh, imp_dbh);
}
if
(on) {
imp_dbh->doRealTran = 0;
}
else
{
imp_dbh->doRealTran = 1;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_STORE() -> syb_chained_txn => %d\n"
, on);
}
if
(!autocommit && imp_dbh->optSupported) {
CS_BOOL value = on ? CS_TRUE : CS_FALSE;
CS_RETCODE ret;
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_CHAINXACTS,
&value, CS_UNUSED, NULL);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" syb_db_STORE() -> syb_chained_txn AutoCommit off CS_OPT_CHAINXACTS(%d) => %d\n"
,
value, ret);
}
}
}
else
{
}
return
TRUE;
}
if
(kl == 10 && strEQ(key,
"AutoCommit"
)) {
int
crnt = (DBIc_has(imp_dbh, DBIcf_AutoCommit) > 0);
int
ret;
if
(imp_dbh->imp_sth && imp_dbh->imp_sth->bcpFlag) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_db_STORE(): AutoCommit value changes inhibitted during BCP ops\n"
);
}
return
TRUE;
}
on = SvTRUE(valuesv);
if
(DBIc_ACTIVE_KIDS(imp_dbh) && ((on && !crnt) || (!on && crnt))) {
croak(
"panic: can't change AutoCommit (from %d to %d) with active statement handles"
,
on, crnt);
}
ret = toggle_autocommit(dbh, imp_dbh, on);
DBIc_set(imp_dbh, DBIcf_AutoCommit, on);
return
TRUE;
}
if
(kl == 11 && strEQ(key,
"LongTruncOK"
)) {
DBIc_set(imp_dbh, DBIcf_LongTruncOk, SvTRUE(valuesv));
return
TRUE;
}
if
(kl == 11 && strEQ(key,
"LongReadLen"
)) {
CS_INT value = SvIV(valuesv);
CS_RETCODE ret;
if
(imp_dbh->inUse) {
warn(
"Can't set LongReadLen because the database handle is in use."
);
return
FALSE;
}
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_TEXTSIZE, &value,
CS_UNUSED, NULL);
if
(ret != CS_SUCCEED) {
warn(
"Setting of CS_OPT_TEXTSIZE failed."
);
return
FALSE;
}
DBIc_LongReadLen(imp_dbh) = value;
return
TRUE;
}
if
(kl == 21 && strEQ(key,
"syb_quoted_identifier"
)) {
CS_INT value = SvIV(valuesv);
CS_RETCODE ret;
if
(imp_dbh->inUse) {
warn(
"Can't set syb_quoted_identifier because the database handle is in use."
);
return
FALSE;
}
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_QUOTED_IDENT, &value,
CS_UNUSED, NULL);
if
(ret != CS_SUCCEED) {
warn(
"Setting of CS_OPT_QUOTED_IDENT failed."
);
return
FALSE;
}
imp_dbh->quotedIdentifier = value;
return
TRUE;
}
if
(kl == 12 && strEQ(key,
"syb_show_sql"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->showSql = 1;
}
else
{
imp_dbh->showSql = 0;
}
return
TRUE;
}
if
(kl == 12 && strEQ(key,
"syb_show_eed"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->showEed = 1;
}
else
{
imp_dbh->showEed = 0;
}
return
TRUE;
}
if
(kl == 15 && strEQ(key,
"syb_err_handler"
)) {
if
(!SvOK(valuesv)) {
imp_dbh->err_handler = NULL;
}
else
if
(imp_dbh->err_handler == (SV*) NULL) {
imp_dbh->err_handler = newSVsv(valuesv);
}
else
{
sv_setsv(imp_dbh->err_handler, valuesv);
}
return
TRUE;
}
if
(kl == 15 && strEQ(key,
"syb_enable_utf8"
)) {
#if !defined(DBD_CAN_HANDLE_UTF8)
warn(
"The current version of OpenClient can't handle utf8 data."
);
return
FALSE;
#else
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->enable_utf8 = 1;
}
else
{
imp_dbh->enable_utf8 = 0;
}
return
TRUE;
#endif
}
if
(kl == 16 && strEQ(key,
"syb_row_callback"
)) {
if
(!SvOK(valuesv)) {
imp_dbh->row_cb = NULL;
}
else
if
(imp_dbh->row_cb == (SV*) NULL) {
imp_dbh->row_cb = newSVsv(valuesv);
}
else
{
sv_setsv(imp_dbh->row_cb, valuesv);
}
return
TRUE;
}
if
(kl == 16 && strEQ(key,
"syb_flush_finish"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->flushFinish = 1;
}
else
{
imp_dbh->flushFinish = 0;
}
return
TRUE;
}
if
(kl == 12 && strEQ(key,
"syb_rowcount"
)) {
#if defined(CS_OPT_ROWCOUNT)
CS_INT value = SvIV(valuesv);
CS_RETCODE ret;
if
(imp_dbh->inUse) {
warn(
"Can't set syb_rowcount because the database handle is in use."
);
return
FALSE;
}
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_ROWCOUNT, &value,
CS_UNUSED, NULL);
if
(ret != CS_SUCCEED) {
warn(
"Setting of CS_OPT_ROWCOUNT failed."
);
return
FALSE;
}
imp_dbh->rowcount = value;
return
TRUE;
#else
return
FALSE;
#endif
}
if
(kl == 21 && strEQ(key,
"syb_dynamic_supported"
)) {
warn(
"'syb_dynamic_supported' is a read-only attribute"
);
return
TRUE;
}
if
(kl == 18 && strEQ(key,
"syb_do_proc_status"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->doProcStatus = 1;
}
else
{
imp_dbh->doProcStatus = 0;
}
return
TRUE;
}
if
(kl == 14 && strEQ(key,
"syb_use_bin_0x"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->useBin0x = 1;
}
else
{
imp_dbh->useBin0x = 0;
}
return
TRUE;
}
if
(kl == 17 && strEQ(key,
"syb_binary_images"
)) {
on = SvTRUE(valuesv);
if
(on) {
imp_dbh->binaryImage = 1;
}
else
{
imp_dbh->binaryImage = 0;
}
return
TRUE;
}
if
(kl == 18 && strEQ(key,
"syb_deadlock_retry"
)) {
int
value = SvIV(valuesv);
imp_dbh->deadlockRetry = value;
return
TRUE;
}
if
(kl == 18 && strEQ(key,
"syb_deadlock_sleep"
)) {
int
value = SvIV(valuesv);
imp_dbh->deadlockSleep = value;
return
TRUE;
}
if
(kl == 20 && strEQ(key,
"syb_deadlock_verbose"
)) {
int
value = SvIV(valuesv);
imp_dbh->deadlockVerbose = value;
return
TRUE;
}
if
(kl == 17 && strEQ(key,
"syb_nsql_nostatus"
)) {
int
value = SvIV(valuesv);
imp_dbh->nsqlNoStatus = value;
return
TRUE;
}
if
(kl == 16 && strEQ(key,
"syb_no_child_con"
)) {
imp_dbh->noChildCon = SvIV(valuesv);
return
TRUE;
}
if
(kl == 19 && strEQ(key,
"syb_failed_db_fatal"
)) {
imp_dbh->failedDbUseFatal = SvIV(valuesv);
return
TRUE;
}
if
(kl == 29 && strEQ(key,
"syb_bind_empty_string_as_null"
)) {
imp_dbh->bindEmptyStringNull = SvIV(valuesv);
return
TRUE;
}
if
(kl == 27 && strEQ(key,
"syb_cancel_request_on_error"
)) {
imp_dbh->alwaysForceFailure = SvIV(valuesv);
return
TRUE;
}
if
(kl == 23 && strEQ(key,
"syb_disconnect_in_child"
)) {
imp_dbh->disconnectInChild = SvIV(valuesv);
return
TRUE;
}
if
(kl == 18 && strEQ(key,
"syb_server_version"
)) {
strncpy
(imp_dbh->serverVersion, SvPV(valuesv, PL_na), 15);
return
TRUE;
}
if
(kl == 12 && strEQ(key,
"syb_date_fmt"
)) {
syb_db_date_fmt(dbh, imp_dbh, SvPV(valuesv, PL_na));
return
TRUE;
}
return
FALSE;
}
SV *syb_db_FETCH_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv) {
dTHX;
STRLEN kl;
char
*key = SvPV(keysv, kl);
SV *retsv = NULL;
if
(kl == 10 && strEQ(key,
"AutoCommit"
)) {
if
(DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 11 && strEQ(key,
"LongTruncOK"
)) {
if
(DBIc_is(imp_dbh, DBIcf_LongTruncOk)) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 11 && strEQ(key,
"LongReadLen"
)) {
retsv = newSViv(DBIc_LongReadLen(imp_dbh));
}
if
(kl == 12 && strEQ(key,
"syb_show_sql"
)) {
if
(imp_dbh->showSql) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 12 && strEQ(key,
"syb_show_eed"
)) {
if
(imp_dbh->showEed) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 8 && strEQ(key,
"syb_dead"
)) {
if
(imp_dbh->isDead) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 15 && strEQ(key,
"syb_err_handler"
)) {
if
(imp_dbh->err_handler) {
retsv = newSVsv(imp_dbh->err_handler);
}
else
{
retsv = &PL_sv_undef;
}
}
if
(kl == 15 && strEQ(key,
"syb_enable_utf8"
)) {
if
(imp_dbh->enable_utf8) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 16 && strEQ(key,
"syb_row_callback"
)) {
if
(imp_dbh->row_cb) {
retsv = newSVsv(imp_dbh->row_cb);
}
else
{
retsv = &PL_sv_undef;
}
}
if
(kl == 15 && strEQ(key,
"syb_chained_txn"
)) {
if
(imp_dbh->doRealTran) {
retsv = newSViv(0);
}
else
{
retsv = newSViv(1);
}
}
if
(kl == 18 && strEQ(key,
"syb_check_tranmode"
)) {
CS_INT value;
CS_RETCODE ret;
ret = syb_set_options(imp_dbh, CS_GET, CS_OPT_CHAINXACTS, &value,
CS_UNUSED, NULL);
if
(ret != CS_SUCCEED) {
value = 0;
}
retsv = newSViv(value);
}
if
(kl == 16 && strEQ(key,
"syb_flush_finish"
)) {
if
(imp_dbh->flushFinish) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 21 && strEQ(key,
"syb_dynamic_supported"
)) {
CS_BOOL val;
CS_RETCODE ret = ct_capability(imp_dbh->connection, CS_GET,
CS_CAP_REQUEST, CS_REQ_DYN, (CS_VOID*) &val);
if
(ret != CS_SUCCEED || val == CS_FALSE) {
retsv = newSViv(0);
}
else
{
retsv = newSViv(1);
}
}
if
(kl == 21 && strEQ(key,
"syb_quoted_identifier"
)) {
if
(imp_dbh->quotedIdentifier) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 12 && strEQ(key,
"syb_rowcount"
)) {
retsv = newSViv(imp_dbh->rowcount);
}
if
(kl == 14 && strEQ(key,
"syb_oc_version"
)) {
retsv = newSVpv(ocVersion,
strlen
(ocVersion));
}
if
(kl == 18 && strEQ(key,
"syb_do_proc_status"
)) {
retsv = newSViv(imp_dbh->doProcStatus);
}
if
(kl == 14 && strEQ(key,
"syb_use_bin_0x"
)) {
if
(imp_dbh->useBin0x) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 17 && strEQ(key,
"syb_binary_images"
)) {
if
(imp_dbh->binaryImage) {
retsv = newSViv(1);
}
else
{
retsv = newSViv(0);
}
}
if
(kl == 18 && strEQ(key,
"syb_deadlock_retry"
)) {
retsv = newSViv(imp_dbh->deadlockRetry);
}
if
(kl == 18 && strEQ(key,
"syb_deadlock_sleep"
)) {
retsv = newSViv(imp_dbh->deadlockSleep);
}
if
(kl == 20 && strEQ(key,
"syb_deadlock_verbose"
)) {
retsv = newSViv(imp_dbh->deadlockVerbose);
}
if
(kl == 17 && strEQ(key,
"syb_nsql_nostatus"
)) {
retsv = newSViv(imp_dbh->nsqlNoStatus);
}
if
(kl == 16 && strEQ(key,
"syb_no_child_con"
)) {
retsv = newSViv(imp_dbh->noChildCon);
}
if
(kl == 19 && strEQ(key,
"syb_failed_db_fatal"
)) {
retsv = newSViv(imp_dbh->failedDbUseFatal);
}
if
(kl == 29 && strEQ(key,
"syb_bind_empty_string_as_null"
)) {
retsv = newSViv(imp_dbh->bindEmptyStringNull);
}
if
(kl == 27 && strEQ(key,
"syb_cancel_request_on_error"
)) {
retsv = newSViv(imp_dbh->alwaysForceFailure);
}
if
(kl == 23 && strEQ(key,
"syb_disconnect_in_child"
)) {
retsv = newSViv(imp_dbh->disconnectInChild);
}
if
(kl == 18 && strEQ(key,
"syb_server_version"
)) {
retsv = newSVpv(imp_dbh->serverVersion, 0);
}
if
(kl == 25 && strEQ(key,
"syb_server_version_string"
)) {
retsv = newSVpv(imp_dbh->serverVersionString, 0);
}
if
(kl == 12 && strEQ(key,
"syb_date_fmt"
)) {
char
buff[50];
syb_get_date_fmt(imp_dbh, buff);
retsv = newSVpv(buff, 0);
}
if
(kl == 11 && strEQ(key,
"syb_has_blk"
)) {
#if defined(NO_BLK)
retsv = &PL_sv_no;
#else
retsv = &PL_sv_yes;
#endif
}
if
(retsv == &PL_sv_yes || retsv == &PL_sv_no || retsv == &PL_sv_undef) {
return
retsv;
}
return
sv_2mortal(retsv);
}
static
CS_COMMAND * syb_alloc_cmd(imp_dbh_t *imp_dbh, CS_CONNECTION *connection,
int
mode) {
CS_COMMAND *cmd;
CS_RETCODE retcode;
if
((retcode = ct_cmd_alloc(connection, &cmd)) != CS_SUCCEED) {
if
(mode != 0) {
syb_set_error(imp_dbh, -1,
"ct_cmd_alloc failed"
);
}
return
NULL;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_alloc_cmd() -> CS_COMMAND %x for CS_CONNECTION %x\n"
,
cmd, connection);
}
return
cmd;
}
static
void
dbd_preparse(imp_sth_t *imp_sth,
char
*statement) {
dTHX;
enum
{
DEFAULT, LITERAL, COMMENT, LINE_COMMENT, VARIABLE
} STATES;
int
state = DEFAULT;
int
next_state;
char
last_literal = 0;
char
*src;
phs_t phs_tpl;
SV *phs_sv;
int
idx = 0;
STRLEN namelen;
char
name[64];
#define VARNAME_LEN 255
char
varname[VARNAME_LEN + 1];
int
pos;
imp_sth->statement = my_strdup(statement);
memset
(&phs_tpl, 0,
sizeof
(phs_tpl));
phs_tpl.ftype = CS_VARCHAR_TYPE;
varname[0] = 0;
src = statement;
while
(
isspace
(*src) && *src) {
++src;
}
if
(!strncasecmp(src,
"exec"
, 4)) {
imp_sth->type = 1;
}
else
if
(imp_sth->bcpFlag) {
imp_sth->type = 2;
}
else
{
imp_sth->type = 0;
}
src = statement;
while
(*src) {
next_state = state;
switch
(state) {
case
DEFAULT:
if
(*src ==
'\''
|| *src ==
'"'
) {
last_literal = *src;
next_state = LITERAL;
}
else
if
(*src ==
'/'
&& *(src + 1) ==
'*'
) {
next_state = COMMENT;
}
else
if
(*src ==
'-'
&& *(src + 1) ==
'-'
) {
next_state = LINE_COMMENT;
}
else
if
(*src ==
'@'
) {
varname[0] =
'@'
;
pos = 1;
next_state = VARIABLE;
}
break
;
case
LITERAL:
if
(*src == last_literal) {
next_state = DEFAULT;
}
break
;
case
COMMENT:
if
(*(src - 1) ==
'*'
&& *src ==
'/'
) {
next_state = DEFAULT;
}
break
;
case
LINE_COMMENT:
if
(*src ==
'\n'
) {
next_state = DEFAULT;
}
break
;
case
VARIABLE:
if
(!
isalnum
(*src) && *src !=
'_'
) {
varname[pos] = 0;
next_state = DEFAULT;
}
else
if
(pos < VARNAME_LEN) {
varname[pos++] = *src;
}
}
if
(state != DEFAULT || *src !=
'?'
) {
++src;
state = next_state;
continue
;
}
state = next_state;
if
(*src !=
'?'
) {
continue
;
}
++src;
sprintf
(name,
":p%d"
, ++idx);
namelen =
strlen
(name);
if
(imp_sth->all_params_hv == NULL) {
imp_sth->all_params_hv = newHV();
}
phs_tpl.sv = &PL_sv_undef;
phs_sv = newSVpv((
char
*) &phs_tpl,
sizeof
(phs_tpl) + namelen + 1);
hv_store(imp_sth->all_params_hv, name, namelen, phs_sv, 0);
strcpy
(((phs_t*) (
void
*) SvPVX(phs_sv))->name, name);
strcpy
(((phs_t*) (
void
*) SvPVX(phs_sv))->varname, varname);
if
(imp_sth->type == 1) {
char
*p = src;
do
{
if
(*p ==
','
) {
break
;
}
if
(
isspace
(*p)) {
continue
;
}
if
(
isalpha
(*p)) {
if
(!strncasecmp(p,
"out"
, 3)) {
((phs_t*) (
void
*) SvPVX(phs_sv))->is_inout = 1;
}
else
{
break
;
}
}
}
while
(*(++p));
}
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" dbd_preparse parameter %s (%s)\n"
,
((phs_t*) (
void
*) SvPVX(phs_sv))->name,
((phs_t*) (
void
*) SvPVX(phs_sv))->varname);
}
}
if
(imp_sth->all_params_hv) {
DBIc_NUM_PARAMS(imp_sth) = (
int
) HvKEYS(imp_sth->all_params_hv);
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" dbd_preparse scanned %d distinct placeholders\n"
,
(
int
) DBIc_NUM_PARAMS(imp_sth));
}
}
}
static
CS_RETCODE dyn_prepare(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth,
char
* statement) {
dTHX;
CS_INT restype;
static
int
tt = 1;
int
failed = 0;
CS_BOOL val;
CS_RETCODE ret;
ret = ct_capability(imp_dbh->connection, CS_GET, CS_CAP_REQUEST,
CS_REQ_DYN, (CS_VOID*) &val);
if
(ret != CS_SUCCEED || val == CS_FALSE) {
croak(
"Panic: dynamic SQL (? placeholders) are not supported by the server you are connecting to"
);
}
sprintf
(imp_sth->dyn_id,
"DBD%d"
, (
int
) tt++);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" dyn_prepare: ct_dynamic(CS_PREPARE) for %s\n"
,
imp_sth->dyn_id);
}
imp_sth->dyn_execed = 0;
imp_sth->cmd = syb_alloc_cmd(imp_dbh,
imp_sth->connection ? imp_sth->connection : imp_dbh->connection, 1);
ret = ct_dynamic(imp_sth->cmd, CS_PREPARE, imp_sth->dyn_id, CS_NULLTERM,
statement, CS_NULLTERM);
if
(ret != CS_SUCCEED) {
warn(
"ct_dynamic(CS_PREPARE) returned %d"
, ret);
return
ret;
}
ret = ct_send(imp_sth->cmd);
if
(ret != CS_SUCCEED) {
warn(
"ct_send(ct_dynamic(CS_PREPARE)) returned %d"
, ret);
return
ret;
}
while
((ret = ct_results(imp_sth->cmd, &restype)) == CS_SUCCEED) {
if
(restype == CS_CMD_FAIL) {
failed = 1;
}
}
if
(ret == CS_FAIL || failed) {
warn(
"ct_result(ct_dynamic(CS_PREPARE)) returned %d"
, ret);
return
ret;
}
ret = ct_dynamic(imp_sth->cmd, CS_DESCRIBE_INPUT, imp_sth->dyn_id,
CS_NULLTERM, NULL, CS_UNUSED);
if
(ret != CS_SUCCEED) {
warn(
"ct_dynamic(CS_DESCRIBE_INPUT) returned %d"
, ret);
}
ret = ct_send(imp_sth->cmd);
if
(ret != CS_SUCCEED) {
warn(
"ct_send(CS_DESCRIBE_INPUT) returned %d"
, ret);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" dyn_prepare: ct_dynamic(CS_DESCRIBE_INPUT) for %s\n"
,
imp_sth->dyn_id);
}
while
((ret = ct_results(imp_sth->cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" dyn_prepare: ct_results(CS_DESCRIBE_INPUT) for %s - restype %d\n"
,
imp_sth->dyn_id, restype);
}
if
(restype == CS_DESCRIBE_RESULT) {
CS_INT num_param, outlen;
int
i;
char
name[50];
SV **svp;
phs_t *phs;
int
ret;
ret = ct_res_info(imp_sth->cmd, CS_NUMDATA, &num_param, CS_UNUSED,
&outlen);
if
(ret != CS_SUCCEED) {
warn(
"ct_res_info(CS_DESCRIBE_INPUT) returned %d"
, ret);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" dyn_prepare: ct_res_info(CS_DESCRIBE_INPUT) statement has %d parameters\n"
,
num_param);
}
for
(i = 1; i <= num_param; ++i) {
sprintf
(name,
":p%d"
, i);
svp = hv_fetch(imp_sth->all_params_hv, name,
strlen
(name), 0);
phs = ((phs_t*) (
void
*) SvPVX(*svp));
ct_describe(imp_sth->cmd, i, &phs->datafmt);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" dyn_prepare: ct_describe(CS_DESCRIBE_INPUT) col %d, type %d, name %s, status %d, length %d\n"
,
i, phs->datafmt.datatype, phs->datafmt.name,
phs->datafmt.status, phs->datafmt.maxlength);
}
}
}
}
if
(ct_dynamic(imp_sth->cmd, CS_EXECUTE, imp_sth->dyn_id, CS_NULLTERM,
NULL, CS_UNUSED) != CS_SUCCEED) {
ret = CS_FAIL;
}
else
{
ret = CS_SUCCEED;
imp_sth->dyn_execed = 1;
}
return
ret;
}
int
syb_st_prepare(SV *sth, imp_sth_t *imp_sth,
char
*statement, SV *attribs) {
dTHX;
D_imp_dbh_from_sth;
CS_RETCODE ret;
sv_setpv(DBIc_ERRSTR(imp_dbh),
""
);
if
(!DBIc_ACTIVE(imp_dbh)) {
syb_set_error(imp_dbh, -1,
"Database disconnected"
);
return
0;
}
getBcpAttribs(imp_sth, attribs);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_prepare() -> inUse = %d\n"
, imp_dbh->inUse);
}
if
(DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_sth)) || imp_dbh->inUse) {
int
retval = 1;
if
(imp_dbh->noChildCon) {
syb_set_error(imp_dbh, -1,
"DBD::Sybase error: Can't create child connections when syb_no_chld_con is set"
);
return
0;
}
if
(!DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
croak(
"Panic: Can't have multiple statement handles on a single database handle when AutoCommit is OFF"
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_prepare() parent has active kids - opening new connection\n"
);
}
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_LOCK(context_alloc_mutex);
#endif
if
((imp_sth->connection = syb_db_connect(imp_dbh)) == NULL) {
retval = 0;
}
#if PERL_VERSION >= 8 && defined(_REENTRANT)
MUTEX_UNLOCK(context_alloc_mutex);
#endif
if
(!retval) {
return
retval;
}
}
if
(imp_sth->statement != NULL) {
Safefree(imp_sth->statement);
}
imp_sth->statement = NULL;
dbd_preparse(imp_sth, statement);
imp_dbh->sql = imp_sth->statement;
if
(!DBIc_is(imp_dbh, DBIcf_AutoCommit) && imp_dbh->doRealTran) {
if
(syb_db_opentran(NULL, imp_dbh) == 0) {
return
-2;
}
}
if
((
int
) DBIc_NUM_PARAMS(imp_sth)) {
if
(imp_sth->type == 0) {
ret = dyn_prepare(imp_dbh, imp_sth, statement);
if
(ret != CS_SUCCEED) {
return
0;
}
}
else
if
(imp_sth->type == 1) {
if
(!syb_st_describe_proc(sth, imp_sth, statement)) {
croak(
"DBD::Sybase: describe_proc failed!\n"
);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" describe_proc: procname = %s\n"
, imp_sth->proc);
}
imp_sth->cmd = syb_alloc_cmd(imp_dbh,
imp_sth->connection ? imp_sth->connection
: imp_dbh->connection, 1);
ret = CS_SUCCEED;
imp_sth->dyn_execed = 0;
}
else
{
ret = syb_blk_init(imp_dbh, imp_sth);
}
}
else
{
if
(imp_sth->type == 2) {
syb_set_error(imp_dbh, -1,
"The syb_bcp_attribs attribute is set, but no placeholders found in the query"
);
return
0;
}
imp_sth->cmd = NULL;
#if 0
if
(cmd_execute(sth, imp_sth) != 0) {
return
0;
}
#endif
ret = CS_SUCCEED;
}
if
(ret != CS_SUCCEED) {
return
0;
}
imp_sth->doProcStatus = imp_dbh->doProcStatus;
DBIc_on(imp_sth, DBIcf_IMPSET);
if
(!imp_sth->connection) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_prepare() -> set inUse\n"
);
}
imp_dbh->inUse = 1;
}
DBIc_ACTIVE_on(imp_sth);
return
1;
}
static
int
syb_st_describe_proc(SV *sth, imp_sth_t *imp_sth,
char
*statement) {
D_imp_dbh_from_sth;
enum
{DEFAULT, QUOTED} STATES;
int
state = DEFAULT;
int
next_state;
char
quote_char;
char
*buff = my_strdup(statement);
char
*src = buff;
char
*start;
while
(
isspace
(*src) && *src) {
++src;
}
if
(strncasecmp(src,
"exec"
, 4)) {
return
0;
}
while
(!
isspace
(*src) && *src) {
++src;
}
while
(
isspace
(*src) && *src) {
++src;
}
start = src;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_describe_proc parsing: |%s|\n"
, start);
}
while
(*src) {
next_state = state;
switch
(state) {
case
DEFAULT:
if
(*src ==
'['
|| *src ==
'"'
) {
quote_char = (*src ==
'*'
? *src :
']'
);
next_state = QUOTED;
}
break
;
case
QUOTED:
if
(*src == quote_char) {
next_state = DEFAULT;
}
break
;
}
if
(state == DEFAULT &&
isspace
(*src)) {
*src =
'\0'
;
break
;
}
++src;
state = next_state;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_describe_proc after parsing: %s\n"
, start);
}
if
(state == QUOTED) {
warn(
"DBD::Sybase - error parsing the proc name in the EXEC statement\n"
);
Safefree(buff);
return
0;
}
strcpy
(imp_sth->proc, start);
Safefree(buff);
return
1;
}
int
syb_st_rows(SV *sth, imp_sth_t *imp_sth) {
return
imp_sth->numRows;
}
static
void
cleanUp(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth) {
int
i;
int
numCols = DBIc_NUM_FIELDS(imp_sth);
for
(i = 0; i < numCols && imp_sth->coldata != NULL; ++i) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cleanUp() -> processing column %d\n"
, i);
}
if
(imp_sth->coldata[i].type == CS_CHAR_TYPE
|| imp_sth->coldata[i].type == CS_LONGCHAR_TYPE
|| imp_sth->coldata[i].type == CS_TEXT_TYPE
|| imp_sth->coldata[i].type == CS_IMAGE_TYPE) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cleanUp() -> Safefree for %d, type %d\n"
, i, imp_sth->coldata[i].type);
}
Safefree(imp_sth->coldata[i].value.c);
}
}
if
(imp_sth->datafmt) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cleanUp() -> Safefree(datafmt)\n"
);
}
Safefree(imp_sth->datafmt);
}
if
(imp_sth->coldata) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cleanUp() -> Safefree(coldata)\n"
);
}
Safefree(imp_sth->coldata);
}
imp_sth->numCols = 0;
imp_sth->coldata = NULL;
imp_sth->datafmt = NULL;
}
static
CS_RETCODE describe(SV* sth, imp_sth_t* imp_sth,
int
restype) {
dTHX;
D_imp_dbh_from_sth;
CS_RETCODE retcode;
int
i;
int
numCols;
AV* av;
if
((retcode = ct_res_info(imp_sth->cmd, CS_NUMDATA, &numCols, CS_UNUSED, NULL)) != CS_SUCCEED) {
warn(
"ct_res_info() failed"
);
goto
GoodBye;
}
if
(numCols <= 0) {
warn(
"ct_res_info() returned 0 columns"
);
DBIc_NUM_FIELDS(imp_sth) = numCols;
imp_sth->numCols = 0;
goto
GoodBye;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_res_info() returns %d columns\n"
, numCols);
}
DBIc_NUM_FIELDS(imp_sth) = 0;
DBIc_DBISTATE(imp_sth)->set_attr_k(sth, sv_2mortal(newSVpvn(
"NUM_OF_FIELDS"
, 13)), 0, sv_2mortal(newSViv(numCols)));
#if 1 /* for DBI <= 1.53 (and 1.54 which doesn't shrink properly) */
av = DBIc_FIELDS_AV(imp_sth);
if
(av && av_len(av) + 1 != numCols) {
SvREADONLY_off(av);
av_clear(av);
i = numCols;
while
(i--) {
av_store(av, i, newSV(0));
}
SvREADONLY_on(av);
}
#endif
imp_sth->numCols = numCols;
Newz(902, imp_sth->coldata, numCols, ColData);
Newz(902, imp_sth->datafmt, numCols, CS_DATAFMT);
if
(restype == CS_COMPUTE_RESULT) {
CS_INT comp_id, outlen;
if
((retcode = ct_compute_info(imp_sth->cmd, CS_COMP_ID, CS_UNUSED, &comp_id, CS_UNUSED, &outlen)) != CS_SUCCEED) {
warn(
"ct_compute_info failed"
);
goto
GoodBye;
}
}
for
(i = 0; i < numCols; ++i) {
if
((retcode = ct_describe(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i])) != CS_SUCCEED) {
warn(
"ct_describe() failed"
);
cleanUp(imp_dbh, imp_sth);
goto
GoodBye;
}
if
(imp_sth->datafmt[i].namelen == 0) {
sprintf
(imp_sth->datafmt[i].name,
"COL(%d)"
, i + 1);
}
if
(restype == CS_COMPUTE_RESULT) {
CS_INT agg_op, outlen;
CS_CHAR* agg_op_name;
if
((retcode = ct_compute_info(imp_sth->cmd, CS_COMP_OP, (i + 1), &agg_op, CS_UNUSED, &outlen)) != CS_SUCCEED) {
warn(
"ct_compute_info failed"
);
goto
GoodBye;
}
agg_op_name = GetAggOp(agg_op);
if
((retcode = ct_compute_info(imp_sth->cmd, CS_COMP_COLID, (i + 1), &agg_op, CS_UNUSED, &outlen)) != CS_SUCCEED) {
warn(
"ct_compute_info failed"
);
goto
GoodBye;
}
sprintf
(imp_sth->datafmt[i].name,
"%s(%d)"
, agg_op_name, agg_op);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_describe(%d): type = %d, maxlen = %d\n"
, i,
imp_sth->datafmt[i].datatype, imp_sth->datafmt[i].maxlength);
}
imp_sth->coldata[i].realType = imp_sth->datafmt[i].datatype;
imp_sth->coldata[i].realLength = imp_sth->datafmt[i].maxlength;
imp_sth->datafmt[i].locale = LOCALE(imp_dbh);
switch
(imp_sth->datafmt[i].datatype) {
case
CS_BIT_TYPE:
case
CS_TINYINT_TYPE:
case
CS_SMALLINT_TYPE:
case
CS_INT_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_INT);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_INT_TYPE;
imp_sth->datafmt[i].datatype = CS_INT_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.i,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#if defined(SYB_NATIVE_NUM) && defined(CS_UINT_TYPE)
case
CS_USMALLINT_TYPE:
case
CS_UINT_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_INT);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_UINT_TYPE;
imp_sth->datafmt[i].datatype = CS_UINT_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.ui,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#endif
#if defined(SYB_NATIVE_NUM)
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_BIGINT);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_BIGINT_TYPE;
imp_sth->datafmt[i].datatype = CS_BIGINT_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.bi,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#endif
#if defined(CS_UBIGINT_TYPE)
case
CS_UBIGINT_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_UBIGINT);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_UBIGINT_TYPE;
imp_sth->datafmt[i].datatype = CS_UBIGINT_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.ubi,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#endif
#endif
#if defined(SYB_NATIVE_NUM)
case
CS_MONEY_TYPE:
case
CS_MONEY4_TYPE:
#endif
case
CS_REAL_TYPE:
case
CS_FLOAT_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_FLOAT);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_FLOAT_TYPE;
imp_sth->datafmt[i].datatype = CS_FLOAT_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.f,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
case
CS_TEXT_TYPE:
case
CS_IMAGE_TYPE:
#if defined(CS_UNITEXT_TYPE)
case
CS_UNITEXT_TYPE:
#endif
New(902, imp_sth->coldata[i].value.c, imp_sth->datafmt[i].maxlength,
char
);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
if
(imp_dbh->binaryImage) {
imp_sth->coldata[i].type = imp_sth->datafmt[i].datatype;
}
else
{
imp_sth->coldata[i].type = CS_TEXT_TYPE;
imp_sth->datafmt[i].datatype = CS_TEXT_TYPE;
}
if
(!imp_sth->noBindBlob) {
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], imp_sth->coldata[i].value.c,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
}
break
;
case
CS_DATETIME_TYPE:
case
CS_DATETIME4_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_DATETIME);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_DATETIME_TYPE;
imp_sth->datafmt[i].datatype = CS_DATETIME_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.dt,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#if defined(CS_DATE_TYPE)
case
CS_DATE_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_DATE);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_DATE_TYPE;
imp_sth->datafmt[i].datatype = CS_DATE_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.d,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
case
CS_TIME_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_TIME);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_TIME_TYPE;
imp_sth->datafmt[i].datatype = CS_TIME_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], &imp_sth->coldata[i].value.t,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
break
;
#endif
#if defined(CS_BIGDATETIME_TYPE)
case
CS_BIGDATETIME_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_BIGDATETIME);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_BIGDATETIME_TYPE;
imp_sth->datafmt[i].datatype = CS_BIGDATETIME_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i],
&imp_sth->coldata[i].value.bdt,
&imp_sth->coldata[i].valuelen,
&imp_sth->coldata[i].indicator);
break
;
case
CS_BIGTIME_TYPE:
imp_sth->datafmt[i].maxlength =
sizeof
(CS_BIGTIME);
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
imp_sth->coldata[i].type = CS_BIGTIME_TYPE;
imp_sth->datafmt[i].datatype = CS_BIGTIME_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i],
&imp_sth->coldata[i].value.bt,
&imp_sth->coldata[i].valuelen,
&imp_sth->coldata[i].indicator);
break
;
#endif
case
CS_CHAR_TYPE:
case
CS_LONGCHAR_TYPE:
case
CS_VARCHAR_TYPE:
case
CS_BINARY_TYPE:
case
CS_VARBINARY_TYPE:
case
CS_NUMERIC_TYPE:
case
CS_DECIMAL_TYPE:
default
:
imp_sth->datafmt[i].maxlength = get_cwidth(&imp_sth->datafmt[i]) + 1;
if
(imp_sth->datafmt[i].maxlength < 0) {
imp_sth->datafmt[i].maxlength = INT_MAX;
}
imp_sth->datafmt[i].format = CS_FMT_UNUSED;
New(902, imp_sth->coldata[i].value.c, imp_sth->datafmt[i].maxlength,
char
);
imp_sth->coldata[i].type = CS_CHAR_TYPE;
imp_sth->datafmt[i].datatype = CS_CHAR_TYPE;
retcode = ct_bind(imp_sth->cmd, (i + 1), &imp_sth->datafmt[i], imp_sth->coldata[i].value.c,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
if
(imp_sth->coldata[i].realType == CS_BINARY_TYPE || imp_sth->coldata[i].realType == CS_VARBINARY_TYPE) {
imp_sth->coldata[i].type = imp_sth->datafmt[i].datatype = imp_sth->coldata[i].realType;
}
break
;
}
if
(retcode != CS_SUCCEED) {
warn(
"ct_bind() failed"
);
cleanUp(imp_dbh, imp_sth);
break
;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" describe() -> col %d, type %d, realtype %d\n"
, i,
imp_sth->coldata[i].type, imp_sth->coldata[i].realType);
}
}
GoodBye:;
if
(retcode == CS_SUCCEED) {
imp_sth->done_desc = 1;
}
else
{
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" describe() retcode is NOT CS_SUCCEED - canceling the request.\n"
);
}
int
flushFinish = imp_dbh->flushFinish;
imp_dbh->flushFinish = 0;
syb_st_finish(sth, imp_sth);
imp_dbh->flushFinish = flushFinish;
}
return
retcode == CS_SUCCEED;
}
static
void
clear_sth_flags(SV *sth, imp_sth_t *imp_sth) {
D_imp_dbh_from_sth;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" clear_sth_flags() -> resetting ACTIVE, moreResults, dyn_execed, exec_done\n"
);
}
imp_sth->moreResults = 0;
imp_sth->dyn_execed = 0;
imp_sth->exec_done = 0;
if
(!imp_sth->connection) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" clear_sth_flags() -> reset inUse flag\n"
);
}
imp_dbh->inUse = 0;
}
}
static
int
st_next_result(SV *sth, imp_sth_t *imp_sth) {
dTHX;
D_imp_dbh_from_sth;
CS_COMMAND *cmd = imp_sth->cmd;
CS_INT restype;
CS_RETCODE retcode;
int
failFlag = 0;
imp_sth->numRows = -1;
while
((retcode = ct_results(cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" st_next_result() -> ct_results(%d) == %d\n"
, restype,
retcode);
}
if
(restype == CS_CMD_FAIL) {
failFlag = 1;
}
if
((restype == CS_CMD_DONE || restype == CS_CMD_SUCCEED) && !failFlag) {
ct_res_info(cmd, CS_ROW_COUNT, &imp_sth->numRows, CS_UNUSED, NULL);
}
switch
(restype) {
case
CS_ROW_RESULT:
case
CS_PARAM_RESULT:
case
CS_STATUS_RESULT:
case
CS_CURSOR_RESULT:
case
CS_COMPUTE_RESULT:
if
(imp_sth->done_desc) {
cleanUp(imp_dbh, imp_sth);
clear_cache(sth, imp_sth);
}
retcode = describe(sth, imp_sth, restype);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"describe() retcode = %d\n"
, retcode);
}
if
(restype == CS_STATUS_RESULT && (imp_sth->doProcStatus
|| (imp_sth->dyn_execed && imp_sth->type == 0))) {
CS_INT rows_read;
retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&rows_read);
if
(retcode == CS_SUCCEED) {
imp_sth->lastProcStatus = imp_sth->coldata[0].value.i;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"describe() proc status code = %d\n"
,
imp_sth->lastProcStatus);
}
if
(imp_sth->lastProcStatus != 0) {
failFlag = 2;
}
}
else
{
croak(
"ct_fetch() for proc status failed!"
);
}
while
((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED,
CS_UNUSED, &rows_read))) {
if
(retcode == CS_END_DATA || retcode == CS_FAIL) {
break
;
}
}
}
else
{
goto
Done;
}
}
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"ct_results(%d) final retcode = %d\n"
, restype, retcode);
}
Done:
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" st_next_result() -> lasterr = %d, lastsev = %d\n"
,
imp_dbh->lasterr, imp_dbh->lastsev);
}
if
(!failFlag && imp_dbh->lasterr != 0 && imp_dbh->lastsev > 10) {
if
(imp_dbh->alwaysForceFailure || (restype != CS_STATUS_RESULT
&& restype != CS_ROW_RESULT && restype != CS_PARAM_RESULT
&& restype != CS_CURSOR_RESULT && restype != CS_COMPUTE_RESULT)) {
failFlag = 3;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" st_next_result() -> restype is not data result or syb_cancel_request_on_error is TRUE, force failFlag\n"
);
}
}
else
{
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" st_next_result() -> restype is data result, do NOT force failFlag\n"
);
}
}
}
if
(failFlag && (restype != CS_CMD_DONE && restype != CS_CMD_FAIL)
&& retcode != CS_FAIL) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" st_next_result() -> failFlag set - clear request\n"
);
}
syb_st_finish(sth, imp_sth);
}
if
(retcode == CS_END_RESULTS) {
restype = CS_CMD_DONE;
}
if
(failFlag || retcode == CS_FAIL || retcode == CS_CANCELED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" st_next_result() -> force CS_CMD_FAIL return\n"
);
}
restype = CS_CMD_FAIL;
}
imp_sth->lastResType = restype;
if
(restype == CS_CMD_DONE || restype == CS_CMD_FAIL) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" st_next_result() -> got %s: resetting ACTIVE, moreResults, dyn_execed, exec_done\n"
,
restype == CS_CMD_DONE ?
"CS_CMD_DONE"
:
"CS_CMD_FAIL"
);
}
clear_sth_flags(sth, imp_sth);
DBIc_ACTIVE_off(imp_sth);
}
else
{
DBIc_ACTIVE_on(imp_sth);
}
return
restype;
}
static
int
_convert(
void
*ptr,
char
*str, CS_LOCALE *locale,
CS_DATAFMT *datafmt, CS_INT *len) {
dTHX;
CS_DATAFMT srcfmt;
CS_INT retcode;
CS_INT reslen;
memset
(&srcfmt, 0,
sizeof
(srcfmt));
srcfmt.datatype = CS_CHAR_TYPE;
srcfmt.maxlength =
strlen
(str);
srcfmt.format = CS_FMT_NULLTERM;
srcfmt.locale = locale;
retcode = cs_convert(context, &srcfmt, str, datafmt, ptr, &reslen);
if
(DBIS->debug >= 3 && retcode != CS_SUCCEED || reslen == CS_UNUSED) {
PerlIO_printf(DBILOGFP,
"cs_convert failed (_convert(%s, %d))"
, str,
datafmt->datatype);
}
if
(len) {
*len = reslen;
}
return
retcode;
}
static
CS_RETCODE get_cs_msg(CS_CONTEXT *context,
char
*msg, SV *sth, imp_sth_t *imp_sth) {
dTHX;
CS_CLIENTMSG errmsg;
CS_INT lastmsg = 0;
CS_RETCODE ret;
memset
((
void
*) &errmsg, 0,
sizeof
(CS_CLIENTMSG));
ret = cs_diag(context, CS_STATUS, CS_CLIENTMSG_TYPE, CS_UNUSED, &lastmsg);
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
"get_cs_msg -> cs_diag(CS_STATUS): lastmsg = %d (ret = %d)\n"
,
lastmsg, ret);
}
if
(ret != CS_SUCCEED) {
warn(
"cs_diag(CS_STATUS) failed"
);
return
ret;
}
ret = cs_diag(context, CS_GET, CS_CLIENTMSG_TYPE, lastmsg, &errmsg);
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
"get_cs_msg -> cs_diag(CS_GET) ret = %d, errmsg=%s\n"
, ret, errmsg.msgstring);
}
if
(ret != CS_SUCCEED) {
warn(
"cs_diag(CS_GET) failed"
);
return
ret;
}
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t *)imp_sth, NULL, CS_NUMBER(errmsg.msgnumber),
errmsg.msgstring, NULL, NULL);
if
(cslib_cb) {
dSP;
int
retval, count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSViv(CS_LAYER(errmsg.msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_ORIGIN(errmsg.msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_SEVERITY(errmsg.msgnumber))));
XPUSHs(sv_2mortal(newSViv(CS_NUMBER(errmsg.msgnumber))));
XPUSHs(sv_2mortal(newSVpv(errmsg.msgstring, 0)));
if
(errmsg.osstringlen > 0) {
XPUSHs(sv_2mortal(newSVpv(errmsg.osstring, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
if
(msg) {
XPUSHs(sv_2mortal(newSVpv(msg, 0)));
}
else
{
XPUSHs(&PL_sv_undef);
}
PUTBACK;
if
((count = perl_call_sv(cslib_cb, G_SCALAR)) != 1) {
croak(
"A cslib handler cannot return a LIST"
);
}
SPAGAIN;
retval = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return
retval == 1 ? CS_SUCCEED : CS_FAIL;
}
#if 0
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"\nCS Library Message:\n"
);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"Message number: LAYER = (%ld) ORIGIN = (%ld) "
,
CS_LAYER(errmsg.msgnumber), CS_ORIGIN(errmsg.msgnumber));
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"SEVERITY = (%ld) NUMBER = (%ld)\n"
,
CS_SEVERITY(errmsg.msgnumber), CS_NUMBER(errmsg.msgnumber));
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"Message String: %s\n"
, errmsg.msgstring);
if
(msg)
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"User Message: %s\n"
, msg);
#endif
return
CS_FAIL;
}
static
void
* alloc_datatype(CS_INT datatype,
int
*len) {
void
*ptr;
int
bytes;
switch
(datatype) {
case
CS_TINYINT_TYPE:
bytes =
sizeof
(CS_TINYINT);
break
;
case
CS_SMALLINT_TYPE:
bytes =
sizeof
(CS_SMALLINT);
break
;
case
CS_INT_TYPE:
bytes =
sizeof
(CS_INT);
break
;
case
CS_REAL_TYPE:
bytes =
sizeof
(CS_REAL);
break
;
case
CS_FLOAT_TYPE:
bytes =
sizeof
(CS_FLOAT);
break
;
case
CS_BIT_TYPE:
bytes =
sizeof
(CS_BIT);
break
;
case
CS_DATETIME_TYPE:
bytes =
sizeof
(CS_DATETIME);
break
;
case
CS_DATETIME4_TYPE:
bytes =
sizeof
(CS_DATETIME4);
break
;
case
CS_MONEY_TYPE:
bytes =
sizeof
(CS_MONEY);
break
;
case
CS_MONEY4_TYPE:
bytes =
sizeof
(CS_MONEY4);
break
;
case
CS_NUMERIC_TYPE:
bytes =
sizeof
(CS_NUMERIC);
break
;
case
CS_DECIMAL_TYPE:
bytes =
sizeof
(CS_DECIMAL);
break
;
case
CS_LONG_TYPE:
bytes =
sizeof
(CS_LONG);
break
;
#if 0
case
CS_SENSITIVITY_TYPE: bytes =
sizeof
(CS_SENSITIVITY);
break
;
case
CS_BOUNDARY_TYPE: bytes =
sizeof
(CS_BOUNDARY);
break
;
#endif
case
CS_USHORT_TYPE:
bytes =
sizeof
(CS_USHORT);
break
;
#if defined(CS_DATE_TYPE)
case
CS_DATE_TYPE:
bytes =
sizeof
(CS_DATE);
break
;
case
CS_TIME_TYPE:
bytes =
sizeof
(CS_TIME);
break
;
#endif
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
bytes =
sizeof
(CS_BIGINT);
break
;
case
CS_USMALLINT_TYPE:
bytes =
sizeof
(CS_USMALLINT);
break
;
case
CS_UINT_TYPE:
bytes =
sizeof
(CS_UINT);
break
;
case
CS_UBIGINT_TYPE:
bytes =
sizeof
(CS_UBIGINT);
break
;
#endif
#if defined(CS_BIGDATETIME_TYPE)
case
CS_BIGDATETIME_TYPE:
bytes =
sizeof
(CS_BIGDATETIME);
break
;
case
CS_BIGTIME_TYPE:
bytes =
sizeof
(CS_BIGTIME);
break
;
#endif
default
:
warn(
"alloc_datatype: unkown type: %d"
, datatype);
return
NULL;
}
Newz(902, ptr, bytes,
char
);
*len = bytes;
return
ptr;
}
#if defined(NO_BLK)
static
int
syb_blk_execute(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth, SV *sth)
{
return
-1;
}
#else
static
int
syb_blk_execute(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth, SV *sth) {
dTHX;
int
i;
char
name[32];
void
*ptr;
CS_CONNECTION *con = imp_sth->connection ? imp_sth->connection
: imp_dbh->connection;
STRLEN slen;
CS_INT vlen;
SV **svp;
phs_t *phs;
CS_RETCODE ret;
#if !defined(USE_CSLIB_CB)
if
(cs_diag(context, CS_CLEAR, CS_CLIENTMSG_TYPE, CS_UNUSED, NULL)
!= CS_SUCCEED) {
warn(
"cs_diag(CS_CLEAR) failed"
);
}
#endif
for
(i = 0; i < imp_sth->numCols; ++i) {
sprintf
(name,
":p%d"
, i + 1);
svp = hv_fetch(imp_sth->all_params_hv, name,
strlen
(name), 0);
phs = ((phs_t*) (
void
*) SvPVX(*svp));
phs->datafmt.format = CS_FMT_UNUSED;
phs->datafmt.count = 1;
if
(!phs->sv || !SvOK(phs->sv) || phs->sv == &PL_sv_undef) {
imp_sth->coldata[i].indicator = 0;
ptr =
""
;
imp_sth->coldata[i].valuelen = 0;
if
(!imp_sth->bcpIdentityFlag && imp_sth->bcpIdentityCol == i + 1) {
continue
;
}
}
else
{
imp_sth->coldata[i].ptr = SvPV(phs->sv, slen);
imp_sth->coldata[i].indicator = 0;
switch
(phs->datafmt.datatype) {
#if 0
case
CS_NUMERIC_TYPE:
case
CS_DECIMAL_TYPE:
if
(_convert(&imp_sth->coldata[i].value.num,
imp_sth->coldata[i].ptr, LOCALE(imp_dbh),
&phs->datafmt, &vlen) != CS_SUCCEED) {
#if !defined(USE_CSLIB_CB)
if
(get_cs_msg(context, con) != CS_SUCCEED)
goto
FAIL;
#else
warn(
"BLK _convert(CS_NUMERIC, %s) failed - see cslib error."
, imp_sth->coldata[i].ptr);
#endif
}
imp_sth->coldata[i].valuelen = (vlen != CS_UNUSED ? vlen :
sizeof
(imp_sth->coldata[i].value.num));
ptr = &imp_sth->coldata[i].value.num;
break
;
#endif
case
CS_BINARY_TYPE:
case
CS_LONGBINARY_TYPE:
case
CS_LONGCHAR_TYPE:
case
CS_TEXT_TYPE:
case
CS_IMAGE_TYPE:
case
CS_CHAR_TYPE:
ptr = imp_sth->coldata[i].ptr;
imp_sth->coldata[i].valuelen = slen;
break
;
#if defined(CS_UNICHAR_TYPE)
case
CS_UNICHAR_TYPE:
ptr = imp_sth->coldata[i].ptr;
imp_sth->coldata[i].valuelen = slen * 2;
break
;
#endif
default
:
if
(!imp_sth->coldata[i].v_alloc) {
imp_sth->coldata[i].value.p
= alloc_datatype(phs->datafmt.datatype,
&imp_sth->coldata[i].v_alloc);
}
if
(_convert(imp_sth->coldata[i].value.p,
imp_sth->coldata[i].ptr, LOCALE(imp_dbh),
&phs->datafmt, &vlen) != CS_SUCCEED) {
char
msg[255];
#if !defined(USE_CSLIB_CB)
sprintf
(msg,
"cs_convert failed: column %d: (_convert(%s, %d))"
,
i + 1, (
char
*) imp_sth->coldata[i].ptr,
phs->datafmt.datatype);
ret = get_cs_msg(context, msg, sth, imp_sth);
if
(ret == CS_FAIL) {
goto
FAIL;
}
#else
warn(
"cs_convert failed: column %d: (_convert(%s, %d))"
,
i + 1, imp_sth->coldata[i].ptr, phs->datafmt.datatype);
ret = CS_FAIL;
goto
FAIL;
#endif
}
imp_sth->coldata[i].valuelen = (vlen != CS_UNUSED ? vlen
: imp_sth->coldata[i].v_alloc);
ptr = imp_sth->coldata[i].value.p;
break
;
}
}
ret = blk_bind(imp_sth->bcp_desc, i + 1, &phs->datafmt, ptr,
&imp_sth->coldata[i].valuelen, &imp_sth->coldata[i].indicator);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"blk_bind %d -> '%s' (ret = %d)\n"
, i + 1,
(
char
*)imp_sth->coldata[i].ptr, ret);
}
if
(ret != CS_SUCCEED) {
goto
FAIL;
}
}
ret = blk_rowxfer(imp_sth->bcp_desc);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"blk_rowxfer() -> %d\n"
, ret);
}
if
(ret == CS_SUCCEED) {
imp_sth->bcpRows++;
}
FAIL: ;
return
(ret == CS_SUCCEED ? -1 : -2);
}
#endif
static
int
cmd_execute(SV *sth, imp_sth_t *imp_sth) {
D_imp_dbh_from_sth;
if
(imp_sth->statement == NULL) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> can't execute a command with a NULL statement string.\n"
);
}
syb_set_error(imp_dbh, -1,
"execute() called with an invalid SQL string."
);
return
-2;
}
if
(!imp_sth->dyn_execed) {
if
(!imp_sth->cmd) {
imp_sth->cmd = syb_alloc_cmd(imp_dbh,
imp_sth->connection ? imp_sth->connection
: imp_dbh->connection, 1);
}
if
(ct_command(imp_sth->cmd, CS_LANG_CMD, imp_sth->statement,
CS_NULLTERM, CS_UNUSED) != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> ct_command() failed (cmd=%x, statement=%s, imp_sth=%x)\n"
,
imp_sth->cmd, imp_sth->statement, imp_sth);
}
return
-2;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> ct_command() OK\n"
);
}
}
if
(ct_send(imp_sth->cmd) != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> ct_send() failed\n"
);
}
return
-2;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> ct_send() OK\n"
);
}
imp_sth->exec_done = 1;
if
(!imp_sth->connection) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cmd_execute() -> set inUse flag\n"
);
}
imp_dbh->inUse = 1;
}
return
0;
}
int
syb_st_execute(SV *sth, imp_sth_t *imp_sth) {
dTHX;
D_imp_dbh_from_sth;
int
restype;
#if 0
if
(DBIc_ACTIVE_KIDS(DBIc_PARENT_COM(imp_sth))) {
}
#endif
imp_dbh->lasterr = 0;
imp_dbh->lastsev = 0;
if
(imp_sth->type == 2) {
return
syb_blk_execute(imp_dbh, imp_sth, sth);
}
if
(!imp_sth->exec_done) {
CS_INT rows;
int
i;
SV **phs_svp;
char
namebuf[30];
int
namelen;
phs_t *phs;
int
num_params = (
int
) DBIc_NUM_PARAMS(imp_sth);
int
foundOutput = 0;
boundparams_t *params = 0;
params =
malloc
(
sizeof
(boundparams_t) * num_params );
for
(i = 1; i <= num_params; ++i) {
sprintf
(namebuf,
":p%d"
, i);
namelen =
strlen
(namebuf);
phs_svp = hv_fetch(imp_sth->all_params_hv, namebuf, namelen, 0);
if
(phs_svp == NULL) {
croak(
"Can't bind unknown placeholder '%s'"
, namebuf);
}
phs = (phs_t*) SvPVX(*phs_svp);
if
( phs->is_inout && phs->is_boundinout ) {
params[foundOutput].phs = phs;
foundOutput++;
}
if
(!_dbd_rebind_ph(sth, imp_sth, phs, 0)) {
free
(params);
return
-2;
}
}
if
(cmd_execute(sth, imp_sth) != 0) {
free
(params);
return
-2;
}
if
( foundOutput > 0 ) {
while
(ct_results(imp_sth->cmd, &restype) == CS_SUCCEED && restype != CS_CMD_DONE) {
if
(restype == CS_CMD_FAIL) {
free
(params);
return
-2;
}
if
(restype == CS_PARAM_RESULT) {
for
(i = 0; i < foundOutput; i++) {
CS_DATAFMT datafmt;
phs = params[i].phs;
if
( ct_describe(imp_sth->cmd, i+1, &datafmt) != CS_SUCCEED) {
croak(
"ct_describe() failed"
);
}
phs->datafmt.maxlength = datafmt.maxlength;
SvPOK_only(phs->sv);
SvGROW(phs->sv, phs->datafmt.maxlength );
if
( ct_bind(imp_sth->cmd, i+1, &phs->datafmt, SvPVX(phs->sv), ¶ms[i].len, 0) != CS_SUCCEED )
syb_set_error(imp_dbh, -1,
"ct_bind() for output param failed!"
);
}
}
while
((ct_fetch(imp_sth->cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, &rows)) == CS_SUCCEED) {
}
}
for
(i = 0; i < foundOutput; i++) {
SvCUR_set(params[i].phs->sv, params[i].len);
}
}
free
(params);
}
restype = st_next_result(sth, imp_sth);
if
(restype == CS_CMD_FAIL) {
return
-2;
}
return
imp_sth->numRows;
}
int
syb_st_cancel(SV *sth, imp_sth_t *imp_sth) {
D_imp_dbh_from_sth;
CS_CONNECTION *connection = imp_sth->connection ? imp_sth->connection
: imp_dbh->connection;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_cancel() -> ct_cancel(CS_CANCEL_ATTN)\n"
);
}
if
(ct_cancel(connection, NULL, CS_CANCEL_ATTN) == CS_FAIL) {
ct_close(connection, CS_FORCE_CLOSE);
imp_dbh->isDead = 1;
}
return
1;
}
static
int
fix_fbav(imp_sth_t *imp_sth,
int
num_fields, AV *av) {
#if 0
int
clear_cache = 0;
int
i;
D_imp_dbh_from_sth;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3)
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" fix_fbav() -> num_fields = %d, numCols = %d\n"
, num_fields, imp_sth->numCols);
if
(num_fields < imp_sth->numCols) {
int
isReadonly = SvREADONLY(av);
++clear_cache;
if
(isReadonly)
SvREADONLY_off(av);
i = imp_sth->numCols - 1;
while
(i >= num_fields)
av_store(av, i--, newSV(0));
num_fields = AvFILL(av)+1;
if
(isReadonly)
SvREADONLY_on(av);
}
else
if
(num_fields> imp_sth->numCols) {
int
isReadonly = SvREADONLY(av);
if
(isReadonly)
SvREADONLY_off(av);
av_fill(av, imp_sth->numCols - 1);
num_fields = AvFILL(av)+1;
if
(isReadonly)
SvREADONLY_on(av);
++clear_cache;
}
return
clear_cache;
#else
return
1;
#endif
}
static
void
clear_cache(SV *sth, imp_sth_t *imp_sth) {
dTHX;
hv_delete((HV*) SvRV(sth),
"NAME"
, 4, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NAME_lc"
, 7, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NAME_uc"
, 7, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NAME_hash"
, 9, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NAME_hash_lc"
, 12, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NAME_hash_uc"
, 12, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NULLABLE"
, 8, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"NUM_OF_FIELDS"
, 13, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"PRECISION"
, 9, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"SCALE"
, 5, G_DISCARD);
hv_delete((HV*) SvRV(sth),
"TYPE"
, 4, G_DISCARD);
}
AV * syb_st_fetch(SV *sth, imp_sth_t *imp_sth) {
dTHX;
D_imp_dbh_from_sth;
CS_COMMAND *cmd = imp_sth->cmd;
CS_INT num_fields;
int
ChopBlanks;
int
i;
AV *av;
CS_RETCODE retcode;
CS_INT rows_read, restype;
int
len;
if
(!DBIc_is(imp_sth, DBIcf_ACTIVE) || !imp_sth->exec_done) {
return
Nullav;
}
retcode = ct_res_info(cmd, CS_NUMDATA, &num_fields, CS_UNUSED, NULL);
if
(retcode != CS_SUCCEED) {
croak(
" syb_st_fetch(): ct_res_info() failed"
);
}
ChopBlanks = DBIc_has(imp_sth, DBIcf_ChopBlanks);
TryAgain: retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&rows_read);
av = DBIc_DBISTATE(imp_dbh)->get_fbav(imp_sth);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_fetch() -> ct_fetch() = %d (%d rows, %d cols)\n"
,
retcode, rows_read, num_fields);
}
switch
(retcode) {
case
CS_ROW_FAIL:
if
(!DBIc_is(imp_sth, DBIcf_LongTruncOk))
goto
TryAgain;
case
CS_SUCCEED:
for
(i = 0; i < num_fields; ++i) {
SV *sv = AvARRAY(av)[i];
len = 0;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_fetch() -> %d/%d/%d\n"
, i,
imp_sth->coldata[i].valuelen, imp_sth->coldata[i].type);
}
if
(i >= imp_sth->numCols || imp_sth->coldata[i].indicator
== CS_NULLDATA || (imp_sth->noBindBlob
&& (imp_sth->datafmt[i].datatype == CS_TEXT_TYPE
|| imp_sth->datafmt[i].datatype == CS_IMAGE_TYPE))) {
(
void
) SvOK_off(sv);
}
else
{
#define DATE_BUFF_LEN 50
char
buff[DATE_BUFF_LEN];
switch
(imp_sth->coldata[i].type) {
case
CS_IMAGE_TYPE:
case
CS_TEXT_TYPE:
case
CS_CHAR_TYPE:
case
CS_LONGCHAR_TYPE:
len = imp_sth->coldata[i].valuelen;
sv_setpvn(sv, imp_sth->coldata[i].value.c, len);
if
((imp_sth->coldata[i].realType == CS_CHAR_TYPE
|| imp_sth->coldata[i].realType == CS_LONGCHAR_TYPE)
&& ChopBlanks) {
char
*p = SvEND(sv);
int
len = SvCUR(sv);
while
(len && *--p ==
' '
) {
--len;
}
if
(len != SvCUR(sv)) {
SvCUR_set(sv, len);
*SvEND(sv) =
'\0'
;
}
}
#if defined(DBD_CAN_HANDLE_UTF8)
if
(imp_dbh->enable_utf8
&& (imp_sth->coldata[i].realType == CS_UNICHAR_TYPE
#if defined(CS_UNITEXT_TYPE)
|| imp_sth->coldata[i].realType == CS_UNITEXT_TYPE
#endif
)) {
U8 *value = SvPV_nolen(sv);
STRLEN len = SvCUR(sv);
SvUTF8_off(sv);
if
(is_high_bit_set(value, len) && is_utf8_string(value, len)) {
SvUTF8_on(sv);
}
}
#endif
break
;
case
CS_FLOAT_TYPE:
sv_setnv(sv, imp_sth->coldata[i].value.f);
break
;
case
CS_INT_TYPE:
sv_setiv(sv, imp_sth->coldata[i].value.i);
break
;
#if defined(CS_UINT_TYPE)
case
CS_UINT_TYPE:
sv_setnv(sv, imp_sth->coldata[i].value.ui);
break
;
#endif
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
sv_setnv(sv, imp_sth->coldata[i].value.bi);
break
;
#endif
#if defined(CS_UBIGINT_TYPE)
case
CS_UBIGINT_TYPE:
sv_setnv(sv, imp_sth->coldata[i].value.ubi);
break
;
#endif
case
CS_BINARY_TYPE:
case
CS_VARBINARY_TYPE:
if
(imp_dbh->useBin0x) {
sv_setpv(sv,
"0x"
);
}
else
{
sv_setpv(sv,
""
);
}
len = imp_sth->coldata[i].valuelen;
sv_catpvn(sv, imp_sth->coldata[i].value.c, len);
break
;
case
CS_DATETIME_TYPE:
#if defined(CS_BIGDATETIME_TYPE)
case
CS_BIGDATETIME_TYPE:
#endif
len = datetime2str(&imp_sth->coldata[i],
&imp_sth->datafmt[i], buff, DATE_BUFF_LEN,
imp_dbh->dateFmt, LOCALE(imp_dbh));
sv_setpvn(sv, buff, len);
break
;
#if defined(CS_DATE_TYPE)
case
CS_DATE_TYPE:
len = date2str(&imp_sth->coldata[i].value.d,
&imp_sth->datafmt[i], buff, DATE_BUFF_LEN,
imp_dbh->dateFmt, LOCALE(imp_dbh));
sv_setpvn(sv, buff, len);
break
;
case
CS_TIME_TYPE:
#if defined(CS_BIGTIME_TYPE)
case
CS_BIGTIME_TYPE:
#endif
len = time2str(&imp_sth->coldata[i],
&imp_sth->datafmt[i], buff, DATE_BUFF_LEN,
imp_dbh->dateFmt, LOCALE(imp_dbh));
sv_setpvn(sv, buff, len);
break
;
#endif
default
:
croak(
"syb_st_fetch: unknown datatype: %d, column %d"
,
imp_sth->datafmt[i].datatype, i + 1);
}
}
}
break
;
case
CS_FAIL:
if
(ct_cancel(imp_dbh->connection, NULL, CS_CANCEL_ALL) == CS_FAIL) {
ct_close(imp_dbh->connection, CS_FORCE_CLOSE);
imp_dbh->isDead = 1;
}
return
Nullav;
break
;
case
CS_END_DATA:
restype = st_next_result(sth, imp_sth);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_fetch() -> st_next_results() == %d\n"
, restype);
}
if
(restype == CS_CMD_DONE || restype == CS_CMD_FAIL) {
return
Nullav;
}
else
{
if
(restype == CS_COMPUTE_RESULT) {
num_fields = imp_sth->numCols;
goto
TryAgain;
}
imp_sth->moreResults = 1;
}
return
Nullav;
break
;
case
-4:
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, retcode,
"TDS_INVALID_PARAMETER from ct_fetch"
, Nullch, Nullch);
return
Nullav;
case
-6:
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, retcode,
"TDS_WRONG_STATE from ct_fetch"
, Nullch, Nullch);
return
Nullav;
case
CS_CANCELED:
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, retcode,
"Canceled"
, Nullch, Nullch);
return
Nullav;
default
:
warn(
"ct_fetch() returned an unexpected retcode %ld"
, (
long
) retcode);
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, retcode,
"Unexpected retcode from ct_fetch"
, Nullch, Nullch);
return
Nullav;
}
if
(imp_dbh->row_cb) {
dSP;
int
retval, count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newRV((SV*) av)));
PUTBACK;
if
((count = perl_call_sv(imp_dbh->row_cb, G_SCALAR)) != 1) {
croak(
"An error handler can't return a LIST."
);
}
SPAGAIN;
retval = POPi;
PUTBACK;
FREETMPS;
LEAVE;
if
(retval == 0) {
goto
TryAgain;
}
}
return
av;
}
#if defined(DBD_CAN_HANDLE_UTF8)
static
int
is_high_bit_set(
const
unsigned
char
*val, STRLEN size)
{
while
(*val && size--) {
if
(*val++ & 0x80)
return
1;
}
return
0;
}
#endif
#if defined(NO_BLK)
static
int
sth_blk_finish(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth, SV *sth)
{
return
1;
}
#else
static
int
sth_blk_finish(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth, SV *sth) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" sth_blk_finish() -> Checking for pending rows\n"
);
}
if
(imp_sth->bcpRows > 0) {
if
(DBIc_WARN(imp_dbh)) {
warn(
"finish: %d uncommited rows will be rolled back"
,
imp_sth->bcpRows);
}
syb_blk_done(imp_sth, CS_BLK_CANCEL);
}
else
if
(imp_sth->bcpRows == 0) {
syb_blk_done(imp_sth, CS_BLK_ALL);
}
blkCleanUp(imp_sth, imp_dbh);
DBIc_set(imp_dbh, DBIcf_AutoCommit, imp_sth->bcpAutoCommit);
toggle_autocommit(NULL, imp_dbh, imp_sth->bcpAutoCommit);
clear_sth_flags(sth, imp_sth);
imp_dbh->imp_sth = NULL;
return
1;
}
#endif
int
syb_st_finish(SV *sth, imp_sth_t *imp_sth) {
dTHX;
D_imp_dbh_from_sth;
CS_CONNECTION *connection;
if
(imp_sth->bcp_desc) {
return
sth_blk_finish(imp_dbh, imp_sth, sth);
}
connection = imp_sth->connection ? imp_sth->connection
: imp_dbh->connection;
if
(imp_dbh->flushFinish) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_finish() -> flushing\n"
);
}
while
(DBIc_ACTIVE(imp_sth) && !imp_dbh->isDead && imp_sth->exec_done
) {
AV *retval;
do
{
retval = syb_st_fetch(sth, imp_sth);
}
while
(retval && retval != Nullav);
}
}
else
{
if
(DBIc_ACTIVE(imp_sth)) {
#if defined(ROGUE)
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_finish() -> ct_cancel(CS_CANCEL_CURRENT)\n"
);
}
if
(ct_cancel(NULL, imp_sth->cmd, CS_CANCEL_CURRENT) == CS_FAIL) {
ct_close(connection, CS_FORCE_CLOSE);
imp_dbh->isDead = 1;
}
#else
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_finish() -> ct_cancel(CS_CANCEL_ALL)\n"
);
}
if
(ct_cancel(connection, NULL, CS_CANCEL_ALL) == CS_FAIL) {
ct_close(connection, CS_FORCE_CLOSE);
imp_dbh->isDead = 1;
}
#endif
}
}
clear_sth_flags(sth, imp_sth);
DBIc_ACTIVE_off(imp_sth);
return
1;
}
static
void
dealloc_dynamic(imp_sth_t *imp_sth) {
dTHX;
CS_RETCODE ret;
CS_INT restype;
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" dealloc_dynamic: ct_dynamic(CS_DEALLOC) for %s\n"
,
imp_sth->dyn_id);
}
ret = ct_dynamic(imp_sth->cmd, CS_DEALLOC, imp_sth->dyn_id, CS_NULLTERM,
NULL, CS_UNUSED);
if
(ret != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(
DBIc_LOGPIO(imp_sth),
" dealloc_dynamic: ct_dynamic(CS_DEALLOC) for %s FAILED\n"
,
imp_sth->dyn_id);
}
return
;
}
ret = ct_send(imp_sth->cmd);
if
(ret != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" dealloc_dynamic: ct_send(CS_DEALLOC) for %s FAILED\n"
,
imp_sth->dyn_id);
}
return
;
}
while
(ct_results(imp_sth->cmd, &restype) == CS_SUCCEED) {
;
}
if
(imp_sth->all_params_hv) {
HV *hv = imp_sth->all_params_hv;
SV *sv;
char
*key;
I32 retlen;
hv_iterinit(hv);
while
((sv = hv_iternextsv(hv, &key, &retlen)) != NULL) {
if
(sv != &PL_sv_undef) {
phs_t *phs_tpl = (phs_t*) (
void
*) SvPVX(sv);
sv_free(phs_tpl->sv);
}
}
sv_free((SV*) imp_sth->all_params_hv);
}
if
(imp_sth->out_params_av) {
sv_free((SV*) imp_sth->out_params_av);
}
imp_sth->all_params_hv = NULL;
imp_sth->out_params_av = NULL;
}
void
syb_st_destroy(SV *sth, imp_sth_t *imp_sth) {
D_imp_dbh_from_sth;
CS_RETCODE ret;
dTHX;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy: called on %x...\n"
, imp_sth);
}
if
(PL_dirty) {
DBIc_IMPSET_off(imp_sth);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy: dirty set, skipping\n"
);
}
return
;
}
if
(DBIc_ACTIVE(imp_dbh)) {
if
(!
strncmp
(imp_sth->dyn_id,
"DBD"
, 3)) {
dealloc_dynamic(imp_sth);
}
}
if
(imp_sth->statement != NULL) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy(): freeing imp_sth->statement\n"
);
}
Safefree(imp_sth->statement);
imp_sth->statement = NULL;
imp_dbh->sql = NULL;
}
cleanUp(imp_dbh, imp_sth);
if
(imp_sth->cmd) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_cmd_drop() -> CS_COMMAND %x\n"
, imp_sth->cmd);
}
ret = ct_cmd_drop(imp_sth->cmd);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy(): cmd dropped: %d\n"
, ret);
}
}
if
(imp_sth->bcp_desc) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy(): blkCleanUp()\n"
);
}
sth_blk_finish(imp_dbh, imp_sth, sth);
}
if
(imp_sth->connection) {
ret = ct_close(imp_sth->connection, CS_FORCE_CLOSE);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy(): connection closed: %d\n"
, ret);
}
ct_con_drop(imp_sth->connection);
}
else
{
if
(DBIc_ACTIVE(imp_sth)) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_st_destroy(): reset inUse flag\n"
);
}
imp_dbh->inUse = 0;
}
}
DBIc_ACTIVE_off(imp_sth);
DBIc_IMPSET_off(imp_sth);
}
int
syb_st_blob_read(SV *sth, imp_sth_t *imp_sth,
int
field,
long
offset,
long
len, SV *destrv,
long
destoffset) {
return
1;
}
int
syb_ct_get_data(SV *sth, imp_sth_t *imp_sth,
int
column, SV *bufrv,
int
buflen) {
dTHX;
CS_COMMAND *cmd = imp_sth->cmd;
CS_VOID *buffer;
CS_INT outlen;
CS_RETCODE ret;
SV *bufsv;
if
(buflen == 0) {
buflen = imp_sth->datafmt[column - 1].maxlength;
}
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" ct_get_data(%d): buflen = %d\n"
, column, buflen);
}
if
(!SvROK(bufrv)) {
warn(
"ct_get_data: buffer parameter is not a reference!"
);
return
0;
}
bufsv = SvRV(bufrv);
Newz(902, buffer, buflen,
char
);
ret = ct_get_data(cmd, column, (CS_VOID*) buffer, buflen, &outlen);
if
(outlen) {
sv_setpvn(bufsv, buffer, outlen);
}
else
{
sv_setsv(bufsv, &PL_sv_undef);
}
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" ct_get_data(%d): got %d bytes (ret = %d)\n"
, column,
outlen, ret);
}
Safefree(buffer);
return
outlen;
}
int
syb_ct_prepare_send(SV *sth, imp_sth_t *imp_sth) {
return
ct_command(imp_sth->cmd, CS_SEND_DATA_CMD, NULL, CS_UNUSED,
CS_COLUMN_DATA) == CS_SUCCEED;
}
int
syb_ct_finish_send(SV *sth, imp_sth_t *imp_sth) {
CS_RETCODE retcode;
CS_INT restype;
D_imp_dbh_from_sth;
retcode = ct_send(imp_sth->cmd);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_send() = %d\n"
, retcode);
}
if
(retcode != CS_SUCCEED) {
return
0;
}
while
((retcode = ct_results(imp_sth->cmd, &restype)) == CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_results(%d) = %d\n"
, restype,
retcode);
}
if
(restype == CS_PARAM_RESULT) {
CS_DATAFMT datafmt;
CS_INT count;
retcode = ct_describe(imp_sth->cmd, 1, &datafmt);
if
(retcode != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_describe() failed\n"
);
}
return
0;
}
datafmt.maxlength =
sizeof
(imp_dbh->iodesc.timestamp);
datafmt.format = CS_FMT_UNUSED;
if
((retcode = ct_bind(imp_sth->cmd, 1, &datafmt,
(CS_VOID *) imp_dbh->iodesc.timestamp,
&imp_dbh->iodesc.timestamplen, NULL)) != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_bind() failed\n"
);
}
return
0;
}
retcode = ct_fetch(imp_sth->cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&count);
if
(retcode != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_fetch() failed\n"
);
}
return
0;
}
retcode = ct_cancel(NULL, imp_sth->cmd, CS_CANCEL_CURRENT);
if
(retcode != CS_SUCCEED) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_finish_send(): ct_fetch() failed\n"
);
}
return
0;
}
}
}
return
1;
}
int
syb_ct_send_data(SV *sth, imp_sth_t *imp_sth,
char
*buffer,
int
size) {
dTHX;
D_imp_dbh_from_sth;
if
(DBIc_DBISTATE(imp_sth)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" ct_send_data(): sending buffer size %d bytes\n"
, size);
}
return
ct_send_data(imp_sth->cmd, buffer, size) == CS_SUCCEED;
}
int
syb_ct_data_info(SV *sth, imp_sth_t *imp_sth,
int
action,
int
column,
SV *attr) {
dTHX;
D_imp_dbh_from_sth;
CS_COMMAND *cmd = imp_sth->cmd;
CS_RETCODE ret;
if
(action == CS_SET) {
if
(attr && attr != &PL_sv_undef && SvROK(attr)) {
SV **svp;
svp = hv_fetch((HV*) SvRV(attr),
"total_txtlen"
, 12, 0);
if
(svp && SvGMAGICAL(*svp)) {
mg_get(*svp);
}
if
(svp && SvIOK(*svp)) {
imp_dbh->iodesc.total_txtlen = SvIV(*svp);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): set total_txtlen to %d\n"
,
imp_dbh->iodesc.total_txtlen);
}
svp = hv_fetch((HV*) SvRV(attr),
"log_on_update"
, 13, 0);
if
(svp && SvGMAGICAL(*svp)) {
mg_get(*svp);
}
if
(svp && SvIOK(*svp)) {
imp_dbh->iodesc.log_on_update = SvIV(*svp);
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): set log_on_update to %d\n"
,
imp_dbh->iodesc.log_on_update);
}
}
}
if
(action == CS_SET) {
column = CS_UNUSED;
}
else
{
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): get IODESC for column %d\n"
, column);
}
}
ret = ct_data_info(cmd, action, column, &imp_dbh->iodesc);
if
(action == CS_GET) {
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): ret = %d, total_txtlen = %d, textptr=%x, timestamp=%x, datatype=%d\n"
, ret, imp_dbh->iodesc.total_txtlen,
imp_dbh->iodesc.textptr, imp_dbh->iodesc.timestamp, imp_dbh->iodesc.datatype);
}
if
(imp_dbh->iodesc.textptrlen == 0) {
DBIh_SET_ERR_CHAR(sth, (imp_xxh_t*)imp_sth, Nullch, 0,
"ct_data_info(): text pointer is not set or is undefined. The text/image column may be uninitialized in the database for this row."
, Nullch, Nullch);
return
0;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): ret = %d, total_txtlen = %d\n"
, ret,
imp_dbh->iodesc.total_txtlen);
}
}
else
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" ct_data_info(): ret = %d\n"
,
ret);
}
return
ret == CS_SUCCEED;
}
typedef
struct
{
const
char
*str;
unsigned len :8;
unsigned array :1;
unsigned filler :23;
} T_st_params;
#define s_A(str) { str, sizeof(str)-1 }
static
T_st_params S_st_fetch_params[] = { s_A(
"NUM_OF_PARAMS"
),
s_A(
"NUM_OF_FIELDS"
),
s_A(
"NAME"
),
s_A(
"NULLABLE"
),
s_A(
"TYPE"
),
s_A(
"PRECISION"
),
s_A(
"SCALE"
),
s_A(
"syb_more_results"
),
s_A(
"LENGTH"
),
s_A(
"syb_types"
),
s_A(
"syb_result_type"
),
s_A(
"LongReadLen"
),
s_A(
"syb_proc_status"
),
s_A(
"syb_do_proc_status"
),
s_A(
"syb_no_bind_blob"
),
s_A(
"CursorName"
),
s_A(
""
),
};
static
T_st_params S_st_store_params[] = { s_A(
"syb_do_proc_status"
),
s_A(
"syb_no_bind_blob"
),
s_A(
""
),
};
#undef s_A
SV * syb_st_FETCH_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv) {
dTHX;
STRLEN kl;
char
*key = SvPV(keysv, kl);
int
i;
SV *retsv = NULL;
T_st_params *par;
for
(par = S_st_fetch_params; par->len > 0; par++) {
if
(par->len == kl && strEQ(key, par->str)) {
break
;
}
}
if
(par->len <= 0) {
return
Nullsv;
}
if
(par - S_st_fetch_params == 0) {
return
Nullsv;
}
if
(!imp_sth->done_desc && (par - S_st_fetch_params) < 10) {
return
Nullsv;
}
i = DBIc_NUM_FIELDS(imp_sth);
AV *av;
switch
(par - S_st_fetch_params) {
case
0:
return
Nullsv;
case
1:
retsv = newSViv(i);
break
;
case
2:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i, newSVpv(imp_sth->datafmt[i].name, 0));
}
break
;
case
3:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i,
(imp_sth->datafmt[i].status & CS_CANBENULL) ? newSViv(1)
: newSViv(0));
}
break
;
case
4:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i, newSViv(map_syb_types(imp_sth->coldata[i].realType)));
}
break
;
case
5:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i, newSViv(
imp_sth->datafmt[i].precision ? imp_sth->datafmt[i].precision
: imp_sth->coldata[i].realLength));
}
break
;
case
6:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
switch
(imp_sth->coldata[i].realType) {
case
CS_NUMERIC_TYPE:
case
CS_DECIMAL_TYPE:
av_store(av, i, newSViv(imp_sth->datafmt[i].scale));
break
;
default
:
av_store(av, i, newSVsv(&PL_sv_undef));
}
}
break
;
case
7:
retsv = newSViv(imp_sth->moreResults);
break
;
case
8:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i, newSViv(imp_sth->coldata[i].realLength));
}
break
;
case
9:
av = newAV();
retsv = newRV(sv_2mortal((SV*) av));
while
(--i >= 0) {
av_store(av, i, newSViv(imp_sth->coldata[i].realType));
}
break
;
case
10:
retsv = newSViv(imp_sth->lastResType);
break
;
case
11:
retsv = newSViv(DBIc_LongReadLen(imp_sth));
break
;
case
12:
retsv = newSViv(imp_sth->lastProcStatus);
break
;
case
13:
retsv = newSViv(imp_sth->doProcStatus);
break
;
case
14:
retsv = newSViv(imp_sth->noBindBlob);
break
;
case
15:
retsv = &PL_sv_undef;
break
;
default
:
return
Nullsv;
}
if
(retsv == &PL_sv_no || retsv == &PL_sv_yes || retsv == &PL_sv_undef) {
return
retsv;
}
return
sv_2mortal(retsv);
}
int
syb_st_STORE_attrib(SV *sth, imp_sth_t *imp_sth, SV *keysv, SV *valuesv) {
dTHX;
STRLEN kl;
char
*key = SvPV(keysv, kl);
T_st_params *par;
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" syb_st_STORE(): key = %s\n"
,
key);
}
for
(par = S_st_store_params; par->len > 0; par++) {
if
(par->len == kl && strEQ(key, par->str)) {
break
;
}
}
if
(par->len <= 0) {
return
FALSE;
}
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" syb_st_STORE(): storing %d for key = %s\n"
,
SvTRUE(valuesv), key);
}
switch
(par - S_st_store_params) {
case
0:
if
(SvTRUE(valuesv)) {
imp_sth->doProcStatus = 1;
}
else
{
imp_sth->doProcStatus = 0;
}
return
TRUE;
case
1:
if
(SvTRUE(valuesv)) {
imp_sth->noBindBlob = 1;
}
else
{
imp_sth->noBindBlob = 0;
}
return
TRUE;
}
return
FALSE;
}
static
int
datetime2str(ColData *colData, CS_DATAFMT *srcfmt,
char
*buff,
CS_INT len,
int
type, CS_LOCALE *locale) {
if
(type == 0) {
CS_DATAFMT dstfmt;
memset
(&dstfmt, 0,
sizeof
(dstfmt));
dstfmt.datatype = CS_CHAR_TYPE;
dstfmt.maxlength = len;
dstfmt.format = CS_FMT_NULLTERM;
dstfmt.locale = locale;
cs_convert(context, srcfmt, &colData->value.dt, &dstfmt, buff, &len);
return
len - 1;
}
else
{
CS_DATEREC rec;
int
datatype;
void
*value;
#if defined(CS_BIGDATETIME_TYPE)
if
(srcfmt->datatype == CS_BIGDATETIME_TYPE) {
datatype = CS_BIGDATETIME_TYPE;
value = &colData->value.bdt;
}
else
#endif
{
datatype = CS_DATETIME_TYPE;
value = &colData->value.dt;
}
cs_dt_crack(context, datatype, value, &rec);
#if defined(CS_BIGDATETIME_TYPE)
if
(srcfmt->datatype == CS_BIGDATETIME_TYPE && rec.datesecprec > 0) {
rec.datemsecond = rec.datesecfrac / 1000;
}
#endif
if
(type == 2) {
sprintf
(buff,
"%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d.%3.3dZ"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
else
{
sprintf
(buff,
"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d.%3.3d"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
return
strlen
(buff);
}
return
0;
}
#if defined(CS_DATE_TYPE)
static
int
date2str(CS_DATE *d, CS_DATAFMT *srcfmt,
char
*buff, CS_INT len,
int
type, CS_LOCALE *locale) {
if
(type == 0) {
CS_DATAFMT dstfmt;
memset
(&dstfmt, 0,
sizeof
(dstfmt));
dstfmt.datatype = CS_CHAR_TYPE;
dstfmt.maxlength = len;
dstfmt.format = CS_FMT_NULLTERM;
dstfmt.locale = locale;
cs_convert(context, srcfmt, d, &dstfmt, buff, &len);
return
len - 1;
}
else
{
CS_DATEREC rec;
cs_dt_crack(context, CS_DATE_TYPE, d, &rec);
if
(type == 2) {
sprintf
(buff,
"%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d.%3.3dZ"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
else
{
sprintf
(buff,
"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d.%3.3d"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
return
strlen
(buff);
}
return
0;
}
static
int
time2str(ColData *colData, CS_DATAFMT *srcfmt,
char
*buff, CS_INT len,
int
type, CS_LOCALE *locale) {
if
(type == 0) {
CS_DATAFMT dstfmt;
memset
(&dstfmt, 0,
sizeof
(dstfmt));
dstfmt.datatype = CS_CHAR_TYPE;
dstfmt.maxlength = len;
dstfmt.format = CS_FMT_NULLTERM;
dstfmt.locale = locale;
cs_convert(context, srcfmt, &colData->value.t, &dstfmt, buff, &len);
return
len - 1;
}
else
{
CS_DATEREC rec;
int
datatype;
void
*value;
#if defined(CS_BIGTIME_TYPE)
if
(srcfmt->datatype == CS_BIGTIME_TYPE) {
datatype = CS_BIGTIME_TYPE;
value = &colData->value.bt;
}
else
#endif
{
datatype = CS_TIME_TYPE;
value = &colData->value.t;
}
cs_dt_crack(context, datatype, value, &rec);
#if defined(CS_BIGTIME_TYPE)
if
(srcfmt->datatype == CS_BIGTIME_TYPE && rec.datesecprec > 0) {
rec.datemsecond = rec.datesecfrac / 1000;
}
#endif
if
(type == 2) {
sprintf
(buff,
"%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d.%3.3dZ"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
else
{
sprintf
(buff,
"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d.%3.3d"
,
rec.dateyear, rec.datemonth + 1, rec.datedmonth,
rec.datehour, rec.dateminute, rec.datesecond,
rec.datemsecond);
}
return
strlen
(buff);
}
return
0;
}
#endif
static
int
to_numeric(
char
*str, SV *sth, imp_sth_t *imp_sth, CS_DATAFMT *datafmt,
int
type, CS_NUMERIC *mn) {
D_imp_dbh_from_sth;
CS_DATAFMT srcfmt;
CS_INT reslen;
char
*p;
memset
(mn, 0,
sizeof
(*mn));
if
(!str || !*str) {
str =
"0"
;
}
memset
(&srcfmt, 0,
sizeof
(srcfmt));
srcfmt.datatype = CS_CHAR_TYPE;
srcfmt.format = CS_FMT_NULLTERM;
srcfmt.locale = LOCALE(imp_dbh);
datafmt->maxlength = 35;
if
(type) {
if
((p =
strchr
(str,
'.'
))) {
datafmt->scale =
strlen
(p + 1);
}
else
{
datafmt->scale = 0;
}
datafmt->precision =
strlen
(str);
}
else
{
if
((p =
strchr
(str,
'.'
))) {
int
len =
strlen
(++p);
if
(len > datafmt->scale) {
if
(p[datafmt->scale] <
'5'
) {
p[datafmt->scale] = 0;
}
else
{
p[datafmt->scale] = 0;
len =
strlen
(str);
while
(len--) {
if
(str[len] ==
'.'
) {
continue
;
}
if
(str[len] <
'9'
) {
str[len]++;
break
;
}
str[len] =
'0'
;
if
(len == 0) {
char
buf[64];
buf[0] =
'1'
;
buf[1] = 0;
strcat
(buf, str);
strcpy
(str, buf);
break
;
}
}
}
}
}
}
srcfmt.maxlength =
strlen
(str);
if
((cs_convert(context, &srcfmt, str, datafmt, mn, &reslen) != CS_SUCCEED) || (reslen == CS_UNUSED)) {
char
msg[64];
sprintf
(msg,
"cs_convert failed: to_numeric(%s)\n"
, str);
get_cs_msg(context, msg, sth, imp_sth);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" cs_convert failed (to_numeric(%s), type=%d, scale=%d, precision=%d, maxlen=%d)\n"
,
str, datafmt->datatype, datafmt->scale, datafmt->precision, datafmt->maxlength);
}
return
0;
}
return
1;
}
static
CS_MONEY to_money(
char
*str, CS_LOCALE *locale) {
CS_MONEY mn;
CS_DATAFMT srcfmt, destfmt;
CS_INT reslen;
memset
(&mn, 0,
sizeof
(mn));
if
(!str) {
return
mn;
}
memset
(&srcfmt, 0,
sizeof
(srcfmt));
srcfmt.datatype = CS_CHAR_TYPE;
srcfmt.maxlength =
strlen
(str);
srcfmt.format = CS_FMT_NULLTERM;
srcfmt.locale = locale;
memset
(&destfmt, 0,
sizeof
(destfmt));
destfmt.datatype = CS_MONEY_TYPE;
destfmt.locale = locale;
destfmt.maxlength =
sizeof
(CS_MONEY);
destfmt.format = CS_FMT_UNUSED;
if
(cs_convert(context, &srcfmt, str, &destfmt, &mn, &reslen) != CS_SUCCEED) {
warn(
"cs_convert failed (to_money(%s))"
, str);
}
if
(reslen == CS_UNUSED) {
warn(
"conversion failed: to_money(%s)"
, str);
}
return
mn;
}
static
CS_BINARY * to_binary(
char
*str, STRLEN *outlen) {
CS_BINARY *b, *b_ptr;
char
s[3], *strtol_end;
STRLEN i, b_len;
long
int
x;
if
(str[0] ==
'0'
&& str[1] ==
'x'
) {
str += 2;
}
b_len = (
strlen
(str) + 1) / 2;
b = (CS_BINARY *) safemalloc(b_len);
memset
(b, 0, b_len);
memset
(&s,
'\0'
, 3);
b_ptr = b;
for
(i = 0; i < b_len; i++, str += 2) {
strncpy
(s, str, 2);
x =
strtol
(s, &strtol_end, 16);
if
(*strtol_end !=
'\0'
) {
warn(
"conversion failed: invalid char '%c'"
, *strtol_end);
break
;
}
*b_ptr++ = x;
}
*outlen = b_len;
return
b;
}
static
int
_dbd_rebind_ph(SV *sth, imp_sth_t *imp_sth, phs_t *phs,
int
maxlen) {
dTHX;
D_imp_dbh_from_sth;
CS_RETCODE rc;
STRLEN value_len;
int
i_value;
double
d_value;
void
*value;
CS_NUMERIC n_value;
CS_MONEY m_value;
#if defined(CS_BIGINT_TYPE)
CS_BIGINT bi_value;
CS_UINT ui_value;
#endif
CS_INT datatype;
int
free_value = 0;
datatype = phs->datafmt.datatype;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 3) {
char
*text = neatsvpv(phs->sv, 0);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" bind %s (%s) <== %s ("
,
phs->name, phs->varname, text);
if
(SvOK(phs->sv)) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"size %ld/%ld/%ld, "
,
(
long
) SvCUR(phs->sv), (
long
) SvLEN(phs->sv), phs->maxlen);
}
else
{
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"NULL, "
);
}
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
"ptype %d, otype %d, datatype %d)\n"
,
(
int
) SvTYPE(phs->sv), phs->ftype, datatype);
}
(
void
) SvUPGRADE(phs->sv, SVt_PV);
if
(SvOK(phs->sv)) {
phs->sv_buf = SvPV(phs->sv, value_len);
switch
(phs->datafmt.datatype) {
case
CS_INT_TYPE:
case
CS_SMALLINT_TYPE:
case
CS_TINYINT_TYPE:
case
CS_BIT_TYPE:
phs->datafmt.datatype = CS_INT_TYPE;
i_value =
atoi
(phs->sv_buf);
value = &i_value;
value_len = 4;
break
;
#if defined(CS_UINT_TYPE)
case
CS_UINT_TYPE:
case
CS_USMALLINT_TYPE:
phs->datafmt.datatype = CS_UINT_TYPE;
ui_value =
atoi
(phs->sv_buf);
value = &ui_value;
value_len = 4;
break
;
#endif
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
phs->datafmt.datatype = CS_BIGINT_TYPE;
bi_value = atoll(phs->sv_buf);
value = &bi_value;
value_len = 8;
break
;
#endif
case
CS_NUMERIC_TYPE:
case
CS_DECIMAL_TYPE:
rc = to_numeric(phs->sv_buf, sth, imp_sth, &phs->datafmt,
imp_sth->type, &n_value);
if
(!rc) {
char
errbuf[64];
sprintf
(errbuf,
"to_numeric() failed for '%s'"
, phs->sv_buf);
syb_set_error(imp_dbh, -1, errbuf);
return
0;
}
phs->datafmt.datatype = CS_NUMERIC_TYPE;
value = &n_value;
value_len =
sizeof
(n_value);
break
;
case
CS_MONEY_TYPE:
case
CS_MONEY4_TYPE:
m_value = to_money(phs->sv_buf, LOCALE(imp_dbh));
phs->datafmt.datatype = CS_MONEY_TYPE;
value = &m_value;
value_len =
sizeof
(m_value);
break
;
case
CS_REAL_TYPE:
case
CS_FLOAT_TYPE:
phs->datafmt.datatype = CS_FLOAT_TYPE;
d_value =
atof
(phs->sv_buf);
value = &d_value;
value_len =
sizeof
(
double
);
break
;
case
CS_BINARY_TYPE:
phs->datafmt.datatype = CS_BINARY_TYPE;
if
((phs->sv_buf[0] ==
'0'
&& phs->sv_buf[1] ==
'x'
) ||
strspn
(
phs->sv_buf,
"abcdefABCDEF0123456789"
) == value_len) {
value = to_binary(phs->sv_buf, &value_len);
++free_value;
}
else
{
value = phs->sv_buf;
}
break
;
case
CS_DATETIME_TYPE:
case
CS_DATETIME4_TYPE:
phs->datafmt.datatype = CS_CHAR_TYPE;
value = phs->sv_buf;
value_len = CS_NULLTERM;
if
(*(
char
*) value == 0) {
value = NULL;
value_len = CS_UNUSED;
}
break
;
default
:
phs->datafmt.datatype = CS_CHAR_TYPE;
value = phs->sv_buf;
if
(*(
char
*) value == 0) {
if
(imp_dbh->bindEmptyStringNull) {
value = NULL;
value_len = CS_UNUSED;
}
else
{
value =
" "
;
value_len = CS_NULLTERM;
}
}
break
;
}
}
else
{
phs->sv_buf = SvPVX(phs->sv);
value_len = 0;
value = NULL;
}
phs->sv_type = SvTYPE(phs->sv);
phs->maxlen = SvLEN(phs->sv) - 1;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" bind %s <== '%.100s' (size %d, ok %d)\n"
, phs->name,
phs->sv_buf, phs->maxlen, SvOK(phs->sv) ? 1 : 0);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" datafmt: type=%d, name=%s, status=%d, len=%ld\n"
,
phs->datafmt.datatype, phs->datafmt.name, phs->datafmt.status,
value_len);
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" saved type: %d\n"
, datatype);
}
#if 0
if
(DBIc_ACTIVE(imp_sth) && imp_sth->exec_done) {
int
finish = imp_dbh->flushFinish;
imp_dbh->flushFinish = 1;
syb_st_finish(sth, imp_sth);
imp_dbh->flushFinish = finish;
}
#endif
if
(imp_sth->dyn_execed == 0) {
if
(imp_sth->type == 0) {
if
(ct_dynamic(imp_sth->cmd, CS_EXECUTE, imp_sth->dyn_id,
CS_NULLTERM, NULL, CS_UNUSED) != CS_SUCCEED)
return
0;
}
else
if
(imp_sth->type == 1) {
if
(ct_command(imp_sth->cmd, CS_RPC_CMD, imp_sth->proc,
CS_NULLTERM, CS_NO_RECOMPILE) != CS_SUCCEED) {
char
errbuf[1024];
sprintf
(errbuf,
"ct_command(CS_RPC_CMD, %s) failed\n"
,
imp_sth->proc);
syb_set_error(imp_dbh, -1, errbuf);
return
0;
}
}
imp_sth->dyn_execed = 1;
}
if
((rc = ct_param(imp_sth->cmd, &phs->datafmt, value, value_len, 0))
!= CS_SUCCEED) {
syb_set_error(imp_dbh, -1,
"ct_param() failed!"
);
}
phs->datafmt.datatype = datatype;
if
(free_value && value != NULL) {
Safefree(value);
}
return
(rc == CS_SUCCEED);
}
int
syb_bind_ph(SV *sth, imp_sth_t *imp_sth, SV *ph_namesv, SV *newvalue,
IV sql_type, SV *attribs,
int
is_inout, IV maxlen) {
dTHX;
SV **phs_svp;
STRLEN name_len;
char
*name;
char
namebuf[30];
phs_t *phs;
STRLEN lna;
D_imp_dbh_from_sth;
#if 1
if
(DBIc_ACTIVE(imp_sth) && imp_sth->exec_done) {
int
finish = imp_dbh->flushFinish;
imp_dbh->flushFinish = 1;
syb_st_finish(sth, imp_sth);
imp_dbh->flushFinish = finish;
}
#endif
if
(SvGMAGICAL(ph_namesv)) {
mg_get(ph_namesv);
}
if
(!SvNIOKp(ph_namesv)) {
name = SvPV(ph_namesv, name_len);
}
if
(SvNIOKp(ph_namesv) || (name && isDIGIT(name[0]))) {
sprintf
(namebuf,
":p%d"
, (
int
) SvIV(ph_namesv));
name = namebuf;
name_len =
strlen
(name);
}
if
(SvTYPE(newvalue) > SVt_PVLV) {
croak(
"Can't bind non-scalar value (currently)"
);
}
#if 0
if
(SvTYPE(newvalue) == SVt_PVLV && is_inout)
croak(
"Can't bind ``lvalue'' mode scalar as inout parameter (currently)"
);
#endif
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
"bind %s <== '%.200s' (attribs: %s)\n"
, name, SvPV(newvalue,
lna), attribs ? SvPV(attribs, lna) :
""
);
}
phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0);
if
(phs_svp == NULL) {
croak(
"Can't bind unknown placeholder '%s'"
, name);
}
phs = (phs_t*) SvPVX(*phs_svp);
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" parameter is output [%s]\n"
, is_inout ?
"true"
:
"false"
);
}
if
(phs->sv == &PL_sv_undef) {
phs->sql_type = (sql_type) ? sql_type : SQL_CHAR;
phs->ftype = map_sql_types(phs->sql_type);
if
(imp_sth->type == 1) {
if
(phs->varname[0] ==
'@'
) {
strcpy
(phs->datafmt.name, phs->varname);
phs->datafmt.namelen =
strlen
(phs->varname);
}
else
{
phs->datafmt.namelen = 0;
}
phs->datafmt.datatype = phs->ftype;
phs->datafmt.status = phs->is_inout ? CS_RETURN : CS_INPUTVALUE;
phs->datafmt.maxlength = 0;
}
phs->maxlen = maxlen;
#if 0
if
(is_inout) {
phs->sv = SvREFCNT_inc(newvalue);
++imp_sth->has_inout_params;
if
(!imp_sth->out_params_av)
imp_sth->out_params_av = newAV();
av_push(imp_sth->out_params_av, SvREFCNT_inc(*phs_svp));
}
#endif
phs->alen_incnull = 0;
}
#if 0
else
if
(is_inout || phs->is_inout) {
croak(
"Can't rebind or change param %s in/out mode after first bind"
, phs->name);
}
#endif
else
if
(maxlen && maxlen != phs->maxlen) {
croak(
"Can't change param %s maxlen (%ld->%ld) after first bind"
,
phs->name, phs->maxlen, maxlen);
}
if
(!is_inout) {
if
(phs->sv == &PL_sv_undef) {
phs->sv = newSV(0);
}
sv_setsv(phs->sv, newvalue);
phs->is_boundinout = 0;
}
else
{
phs->sv = SvREFCNT_inc(newvalue);
phs->is_boundinout = 1;
if
(DBIc_DBISTATE(imp_sth)->debug >= 3) {
PerlIO_printf(DBIc_LOGPIO(imp_sth),
" parameter is bound as inout\n"
);
}
}
if
(imp_sth->type == 2) {
return
1;
}
return
1;
}
static
CS_RETCODE fetch_data(imp_dbh_t *imp_dbh, CS_COMMAND *cmd) {
dTHX;
CS_RETCODE retcode;
CS_INT num_cols;
CS_INT i;
CS_INT j;
CS_INT row_count = 0;
CS_INT rows_read;
CS_INT disp_len;
CS_DATAFMT *datafmt;
ColData *coldata;
char
buff[1024];
if
((retcode = ct_res_info(cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL))
!= CS_SUCCEED) {
warn(
"fetch_data: ct_res_info() failed"
);
return
retcode;
}
if
(num_cols <= 0) {
warn(
"fetch_data: ct_res_info() returned zero columns"
);
return
CS_FAIL;
}
New(902, coldata, num_cols, ColData);
New(902, datafmt, num_cols, CS_DATAFMT);
for
(i = 0; i < num_cols; i++) {
if
((retcode = ct_describe(cmd, (i + 1), &datafmt[i])) != CS_SUCCEED) {
warn(
"fetch_data: ct_describe() failed"
);
break
;
}
datafmt[i].maxlength = display_dlen(&datafmt[i]) + 1;
datafmt[i].datatype = CS_CHAR_TYPE;
datafmt[i].format = CS_FMT_NULLTERM;
New(902, coldata[i].value.c, datafmt[i].maxlength,
char
);
if
((retcode = ct_bind(cmd, (i + 1), &datafmt[i], coldata[i].value.c,
&coldata[i].valuelen, &coldata[i].indicator)) != CS_SUCCEED) {
warn(
"fetch_data: ct_bind() failed"
);
break
;
}
}
if
(retcode != CS_SUCCEED) {
for
(j = 0; j < i; j++) {
Safefree(coldata[j].value.c);
}
Safefree(coldata);
Safefree(datafmt);
return
retcode;
}
display_header(imp_dbh, num_cols, datafmt);
while
(((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
&rows_read)) == CS_SUCCEED) || (retcode == CS_ROW_FAIL)) {
row_count = row_count + rows_read;
if
(retcode == CS_ROW_FAIL) {
sprintf
(buff,
"Error on row %d.\n"
, row_count);
sv_catpv(DBIc_ERRSTR(imp_dbh), buff);
}
for
(i = 0; i < num_cols; i++) {
sv_catpv(DBIc_ERRSTR(imp_dbh), coldata[i].value.c);
if
(i != num_cols - 1) {
disp_len = display_dlen(&datafmt[i]);
disp_len -= coldata[i].valuelen - 1;
for
(j = 0; j < disp_len; j++) {
sv_catpv(DBIc_ERRSTR(imp_dbh),
" "
);
}
}
}
sv_catpv(DBIc_ERRSTR(imp_dbh),
"\n"
);
}
for
(i = 0; i < num_cols; i++) {
Safefree(coldata[i].value.c);
}
Safefree(coldata);
Safefree(datafmt);
switch
((
int
) retcode) {
case
CS_END_DATA:
retcode = CS_SUCCEED;
break
;
case
CS_FAIL:
warn(
"fetch_data: ct_fetch() failed"
);
return
retcode;
break
;
default
:
warn(
"fetch_data: ct_fetch() returned an expected retcode"
);
return
retcode;
break
;
}
return
retcode;
}
static
int
map_sql_types(
int
sql_type) {
int
ret;
switch
(sql_type) {
case
SQL_NUMERIC:
case
SQL_DECIMAL:
ret = CS_NUMERIC_TYPE;
break
;
case
SQL_BIT:
case
SQL_INTEGER:
case
SQL_SMALLINT:
case
SQL_TINYINT:
ret = CS_INT_TYPE;
break
;
#if defined(CS_BIGINT_TYPE)
case
SQL_BIGINT:
ret = CS_BIGINT_TYPE;
break
;
#endif
case
SQL_FLOAT:
case
SQL_REAL:
case
SQL_DOUBLE:
ret = CS_FLOAT_TYPE;
break
;
case
SQL_BINARY:
return
CS_BINARY_TYPE;
break
;
default
:
ret = CS_CHAR_TYPE;
}
return
ret;
}
static
int
map_syb_types(
int
syb_type) {
switch
(syb_type) {
case
CS_CHAR_TYPE:
return
SQL_CHAR;
case
CS_BINARY_TYPE:
return
SQL_BINARY;
case
CS_TEXT_TYPE:
return
SQL_LONGVARCHAR;
case
CS_IMAGE_TYPE:
return
SQL_LONGVARBINARY;
case
CS_BIT_TYPE:
return
SQL_BIT;
case
CS_TINYINT_TYPE:
return
SQL_TINYINT;
case
CS_SMALLINT_TYPE:
return
SQL_SMALLINT;
case
CS_INT_TYPE:
return
SQL_INTEGER;
#if defined(CS_BIGINT_TYPE)
case
CS_BIGINT_TYPE:
return
SQL_BIGINT;
#endif
case
CS_REAL_TYPE:
return
SQL_REAL;
case
CS_FLOAT_TYPE:
return
SQL_FLOAT;
#if defined(CS_DATE_TYPE)
case
CS_DATE_TYPE:
return
SQL_DATE;
#endif
#if defined(CS_BIGDATETIME_TYPE)
case
CS_BIGDATETIME_TYPE:
#endif
case
CS_DATETIME_TYPE:
case
CS_DATETIME4_TYPE:
return
SQL_DATETIME;
#if defined(CS_BIGTIME_TYPE)
case
CS_BIGTIME_TYPE:
#endif
#if defined(CS_TIME_TYPE)
case
CS_TIME_TYPE:
return
SQL_TIME;
#endif
case
CS_MONEY_TYPE:
case
CS_MONEY4_TYPE:
case
CS_DECIMAL_TYPE:
return
SQL_DECIMAL;
case
CS_NUMERIC_TYPE:
return
SQL_NUMERIC;
case
CS_VARCHAR_TYPE:
return
SQL_VARCHAR;
case
CS_VARBINARY_TYPE:
return
SQL_VARBINARY;
default
:
return
SQL_CHAR;
}
}
static
char
*my_strdup(
char
*string) {
char
*buff = safemalloc(
strlen
(string) + 1);
strcpy
(buff, string);
return
buff;
}
static
void
fetchKerbTicket(imp_dbh_t *imp_dbh) {
dTHX;
if
(imp_dbh->kerbGetTicket) {
dSP;
SV *retval;
int
count;
char
*server = imp_dbh->server;
if
(!*server) {
char
*s =
getenv
(
"DSQUERY"
);
if
(s && *s) {
server = s;
}
else
{
server =
"SYBASE"
;
}
}
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(sv_2mortal(newSVpv(server, 0)));
PUTBACK;
if
((count = perl_call_sv(imp_dbh->kerbGetTicket, G_SCALAR)) != 1) {
croak(
"A Kerberos Ticket handler can't return a LIST."
);
}
SPAGAIN;
retval = POPs;
PUTBACK;
FREETMPS;
LEAVE;
if
(SvPOK(retval)) {
strncpy
(imp_dbh->kerberosPrincipal, SvPVX(retval), 255);
imp_dbh->kerberosPrincipal[31] = 0;
}
}
}
#if defined(NO_BLK)
static
CS_RETCODE syb_blk_init(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth)
{
return
CS_SUCCEED;
}
#else
static
CS_RETCODE syb_blk_init(imp_dbh_t *imp_dbh, imp_sth_t *imp_sth) {
dTHX;
CS_RETCODE ret;
char
table[256];
int
i, num_cols;
SV **svp;
phs_t *phs;
char
name[32];
if
(!getTableName(imp_sth->statement, table, 256)) {
char
str[512];
sprintf
(str,
"Can't get table name from '%.256s'"
, imp_sth->statement);
syb_set_error(imp_dbh, -1, str);
return
CS_FAIL;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_blk_init(): table=%s\n"
, table);
}
if
(!DBIc_is(imp_dbh, DBIcf_AutoCommit)) {
toggle_autocommit(NULL, imp_dbh, 1);
}
ret = blk_alloc(imp_sth->connection ? imp_sth->connection
: imp_dbh->connection, BLK_VERSION, &imp_sth->bcp_desc);
if
(ret != CS_SUCCEED) {
goto
FAIL;
}
ret = blk_props(imp_sth->bcp_desc, CS_SET, BLK_IDENTITY,
(CS_VOID*) &imp_sth->bcpIdentityFlag, CS_UNUSED, NULL);
if
(ret != CS_SUCCEED) {
goto
FAIL;
}
ret = blk_init(imp_sth->bcp_desc, CS_BLK_IN, table,
strlen
(table));
if
(ret != CS_SUCCEED) {
goto
FAIL;
}
num_cols = DBIc_NUM_PARAMS(imp_sth);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" syb_blk_init(): num_cols=%d, identityFlag=%d\n"
,
num_cols, imp_sth->bcpIdentityFlag);
}
imp_sth->numCols = num_cols;
Newz(902, imp_sth->coldata, num_cols, ColData);
for
(i = 1; i <= num_cols; ++i) {
sprintf
(name,
":p%d"
, i);
svp = hv_fetch(imp_sth->all_params_hv, name,
strlen
(name), 0);
phs = ((phs_t*) (
void
*) SvPVX(*svp));
memset
(&phs->datafmt, 0,
sizeof
(CS_DATAFMT));
ret = blk_describe(imp_sth->bcp_desc, i, &phs->datafmt);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(
DBIc_LOGPIO(imp_dbh),
" syb_blk_init: blk_describe()==%d col %d, type %d, status %d, length %d\n"
,
ret, i, phs->datafmt.datatype, phs->datafmt.status,
phs->datafmt.maxlength);
}
if
(ret != CS_SUCCEED) {
goto
FAIL;
}
}
FAIL: ;
if
(ret != CS_SUCCEED) {
blkCleanUp(imp_sth, imp_dbh);
}
else
{
imp_dbh->imp_sth = imp_sth;
imp_sth->bcpAutoCommit = DBIc_is(imp_dbh, DBIcf_AutoCommit);
DBIc_set(imp_dbh, DBIcf_AutoCommit, 0);
}
return
ret;
}
#endif
#if defined(NO_BLK)
static
void
blkCleanUp(imp_sth_t *imp_sth, imp_dbh_t *imp_dbh)
{
;
}
#else
static
void
blkCleanUp(imp_sth_t *imp_sth, imp_dbh_t *imp_dbh) {
int
i;
for
(i = 0; i < imp_sth->numCols; ++i) {
if
(imp_sth->coldata[i].value.p && imp_sth->coldata[i].v_alloc) {
Safefree(imp_sth->coldata[i].value.p);
}
}
if
(imp_sth->coldata) {
Safefree(imp_sth->coldata);
}
imp_sth->numCols = 0;
imp_sth->coldata = NULL;
imp_sth->datafmt = NULL;
if
(imp_sth->bcp_desc) {
CS_INT ret = blk_drop(imp_sth->bcp_desc);
if
(DBIc_DBISTATE(imp_dbh)->debug >= 4) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" blkCleanUp -> blk_drop(%d) = %d\n"
, imp_sth->bcp_desc,
ret);
}
imp_sth->bcp_desc = NULL;
}
}
#endif
static
int
getTableName(
char
*statement,
char
*table,
int
maxwidth) {
char
*ptr = safemalloc(
strlen
(statement) + 1);
char
*p;
strcpy
(ptr, statement);
p =
strtok
(ptr,
" "
);
if
(!p || !*p || strncasecmp(p,
"insert"
, 7)) {
goto
FAIL;
}
p =
strtok
(NULL,
" ("
);
if
(!p || !*p) {
goto
FAIL;
}
if
(!strncasecmp(p,
"into"
, 4)) {
p =
strtok
(NULL,
" ("
);
}
if
(!p || !*p) {
goto
FAIL;
}
strncpy
(table, p, maxwidth);
Safefree(ptr);
return
1;
FAIL: Safefree(ptr);
return
0;
}
SV *syb_set_cslib_cb(SV *cb) {
#if 0
warn(
"Can't set a CS-Lib callback: DBD::Sybase was not built with -DUSE_CSLIB_CB"
);
return
&PL_sv_undef;
#else
dTHX;
SV *old = cslib_cb;
if
(cslib_cb == (SV*) NULL) {
cslib_cb = newSVsv(cb);
}
else
{
sv_setsv(cslib_cb, cb);
}
return
old ? old : &PL_sv_undef;
#endif
}
static
int
toggle_autocommit(SV *dbh, imp_dbh_t *imp_dbh,
int
flag) {
CS_BOOL value;
CS_RETCODE ret;
int
current = DBIc_is(imp_dbh, DBIcf_AutoCommit);
if
(!imp_dbh->init_done) {
imp_dbh->init_done = 1;
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" toggle_autocommit: init_done not set, no action\n"
);
}
return
TRUE;
}
if
(DBIc_DBISTATE(imp_dbh)->debug >= 5) {
PerlIO_printf(DBIc_LOGPIO(imp_dbh),
" toggle_autocommit: current = %s, new = %s\n"
,
current ?
"on"
:
"off"
, flag ?
"on"
:
"off"
);
}
if
(flag) {
if
(!current && !imp_dbh->isMSSql) {
syb_db_commit(dbh, imp_dbh);
}
if
(!imp_dbh->doRealTran) {
value = CS_FALSE;
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_CHAINXACTS, &value,
CS_UNUSED, NULL);
}
}
else
{
if
(!imp_dbh->doRealTran) {
value = CS_TRUE;
ret = syb_set_options(imp_dbh, CS_SET, CS_OPT_CHAINXACTS, &value,
CS_UNUSED, NULL);
}
}
if
(!imp_dbh->doRealTran && ret != CS_SUCCEED) {
warn(
"Setting of CS_OPT_CHAINXACTS failed."
);
return
FALSE;
}
return
TRUE;
}