DBD-Adabas
view release on metacpan or search on metacpan
while(isDIGIT(*src))
*p++ = *src++;
*p = 0;
style = 1;
}
else if (isALNUM(*src)) { /* ':foo' */
char *p = name;
*dest++ = '?';
while(isALNUM(*src)) /* includes '_' */
*p++ = *src++;
*p = 0;
style = 2;
}
else { /* perhaps ':=' PL/SQL construct */
*dest++ = ch;
continue;
}
*dest = '\0'; /* handy for debugging */
if (laststyle && style != laststyle)
croak("Can't mix placeholder styles (%d/%d)",style,laststyle);
laststyle = style;
if (imp_sth->all_params_hv == NULL)
imp_sth->all_params_hv = newHV();
namelen = strlen(name);
svpp = hv_fetch(imp_sth->all_params_hv, name, namelen, 0);
if (svpp == NULL) {
/* create SV holding the placeholder */
phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1);
phs = (phs_t*)SvPVX(phs_sv);
strcpy(phs->name, name);
phs->idx = idx;
/* store placeholder to all_params_hv */
svpp = hv_store(imp_sth->all_params_hv, name, namelen, phs_sv, 0);
}
}
*dest = '\0';
if (imp_sth->all_params_hv) {
DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv);
if (dbis->debug >= 2)
fprintf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n",
(int)DBIc_NUM_PARAMS(imp_sth));
}
}
int
dbd_st_tables(dbh, sth, qualifier, table_type)
SV *dbh;
SV *sth;
char *qualifier;
char *table_type;
{
D_imp_dbh(dbh);
D_imp_sth(sth);
RETCODE rc;
SV **svp;
char cname[128]; /* cursorname */
dTHR;
imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
imp_sth->hdbc = imp_dbh->hdbc;
imp_sth->done_desc = 0;
rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
if (rc != SQL_SUCCESS) {
dbd_error(sth, rc, "st_tables/SQLAllocStmt");
return 0;
}
/* just for sanity, later. Any internals that may rely on this (including */
/* debugging) will have valid data */
imp_sth->statement = (char *)safemalloc(strlen(cSqlTables)+strlen(qualifier)+1);
sprintf(imp_sth->statement, cSqlTables, qualifier);
rc = SQLTables(imp_sth->hstmt,
0, SQL_NTS, /* qualifier */
0, SQL_NTS, /* schema/user */
0, SQL_NTS, /* table name */
table_type, SQL_NTS /* type (view, table, etc) */
);
dbd_error(sth, rc, "st_tables/SQLTables");
if (!SQL_ok(rc)) {
SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
imp_sth->hstmt = SQL_NULL_HSTMT;
return 0;
}
/* XXX Way too much duplicated code here */
if (dbis->debug >= 2)
fprintf(DBILOGFP, " dbd_st_tables sql f%d\n\t%s\n",
imp_sth->hstmt, imp_sth->statement);
/* init sth pointers */
imp_sth->fbh = NULL;
imp_sth->ColNames = NULL;
imp_sth->RowBuffer = NULL;
imp_sth->RowCount = -1;
imp_sth->eod = -1;
if (!dbd_describe(sth, imp_sth)) {
SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
imp_sth->hstmt = SQL_NULL_HSTMT;
return 0; /* dbd_describe already called ora_error() */
}
if (dbd_describe(sth, imp_sth) <= 0)
return 0;
DBIc_IMPSET_on(imp_sth);
imp_sth->RowCount = -1;
rc = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
dbd_error(sth, rc, "dbd_st_tables/SQLRowCount");
if (rc != SQL_SUCCESS) {
return -1;
}
DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */
imp_sth->eod = SQL_SUCCESS;
return 1;
}
int
dbd_st_prepare(sth, imp_sth, statement, attribs)
SV *sth;
imp_sth_t *imp_sth;
char *statement;
SV *attribs;
{
dTHR;
D_imp_dbh_from_sth;
RETCODE rc;
SV **svp;
char cname[128]; /* cursorname */
imp_sth->done_desc = 0;
imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
imp_sth->hdbc = imp_dbh->hdbc;
rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "st_prepare/SQLAllocStmt");
return 0;
}
/* scan statement for '?', ':1' and/or ':foo' style placeholders */
dbd_preparse(imp_sth, statement);
/* parse the (possibly edited) SQL statement */
rc = SQLPrepare(imp_sth->hstmt,
imp_sth->statement, strlen(imp_sth->statement));
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "st_prepare/SQLPrepare");
SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
imp_sth->hstmt = SQL_NULL_HSTMT;
return 0;
}
if (dbis->debug >= 2)
fprintf(DBILOGFP, " dbd_st_prepare'd sql f%d\n\t%s\n",
imp_sth->hstmt, imp_sth->statement);
/* init sth pointers */
imp_sth->henv = imp_dbh->henv;
imp_sth->hdbc = imp_dbh->hdbc;
imp_sth->fbh = NULL;
imp_sth->ColNames = NULL;
imp_sth->RowBuffer = NULL;
imp_sth->RowCount = -1;
imp_sth->eod = -1;
DBIc_IMPSET_on(imp_sth);
return 1;
}
int
dbtype_is_string(int bind_type)
{
switch(bind_type) {
case SQL_C_CHAR:
case SQL_C_BINARY:
return 1;
}
return 0;
}
static const char *
S_SqlTypeToString (SWORD sqltype)
{
switch(sqltype) {
case SQL_CHAR: return "CHAR";
case SQL_NUMERIC: return "NUMERIC";
continue;
}
if (fbh->datalen > fbh->ColDisplaySize || fbh->datalen < 0) {
/* truncated LONG ??? DBIcf_LongTruncOk() */
/* DBIcf_LongTruncOk this should only apply to LONG type fields */
/* truncation of other fields should always be an error since it's */
/* a sign of an internal error */
if (!DBIc_has(imp_sth, DBIcf_LongTruncOk)
/* && rc == SQL_SUCCESS_WITH_INFO */) {
dbd_error(sth, rc, "st_fetch/SQLFetch (long truncated)");
return Nullav;
}
sv_setpvn(sv, (char*)fbh->data, fbh->ColDisplaySize);
}
else switch(fbh->ftype) {
#ifdef TIMESTAMP_STRUCT /* iODBC doesn't define this */
case SQL_C_TIMESTAMP:
{
TIMESTAMP_STRUCT *ts;
ts = (TIMESTAMP_STRUCT *)fbh->data;
sprintf(cvbuf, "%04d-%02d-%02d %02d:%02d:%02d",
ts->year, ts->month, ts->day,
ts->hour, ts->minute, ts->second, ts->fraction);
sv_setpv(sv, cvbuf);
break;
}
#endif
default:
if (ChopBlanks && fbh->ColSqlType == SQL_CHAR && fbh->datalen > 0) {
char *p = (char*)fbh->data;
while(fbh->datalen && p[fbh->datalen - 1]==' ')
--fbh->datalen;
}
sv_setpvn(sv, (char*)fbh->data, fbh->datalen);
}
}
return av;
}
int
dbd_st_rows(sth, imp_sth)
SV *sth;
imp_sth_t *imp_sth;
{
return imp_sth->RowCount;
}
int
dbd_st_finish(sth, imp_sth)
SV *sth;
imp_sth_t *imp_sth;
{
dTHR;
D_imp_dbh_from_sth;
RETCODE rc;
int ret = 0;
/* Cancel further fetches from this cursor. */
/* We don't close the cursor till DESTROY (dbd_st_destroy). */
/* The application may re execute(...) it. */
/* XXX semantics of finish (eg oracle vs odbc) need lots more thought */
/* re-read latest DBI specs and ODBC manuals */
if (DBIc_ACTIVE(imp_sth) && imp_dbh->hdbc != SQL_NULL_HDBC) {
rc = SQLFreeStmt(imp_sth->hstmt, SQL_CLOSE);
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "finish/SQLFreeStmt(SQL_CLOSE)");
return 0;
}
}
DBIc_ACTIVE_off(imp_sth);
return 1;
}
void
dbd_st_destroy(sth, imp_sth)
SV *sth;
imp_sth_t *imp_sth;
{
dTHR;
D_imp_dbh_from_sth;
RETCODE rc;
/* SQLxxx functions dump core when no connection exists. This happens
* when the db was disconnected before perl ending.
*/
if (imp_dbh->hdbc != SQL_NULL_HDBC) {
rc = SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "st_destroy/SQLFreeStmt(SQL_DROP)");
/* return 0; */
}
}
/* Free contents of imp_sth */
Safefree(imp_sth->fbh);
Safefree(imp_sth->ColNames);
Safefree(imp_sth->RowBuffer);
Safefree(imp_sth->statement);
if (imp_sth->out_params_av)
sv_free((SV*)imp_sth->out_params_av);
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 != &sv_undef) {
phs_t *phs_tpl = (phs_t*)(void*)SvPVX(sv);
sv_free(phs_tpl->sv);
}
}
sv_free((SV*)imp_sth->all_params_hv);
}
case SQL_OPT_TRACEFILE:
retsv = newSVpv((char *)vParam, 0);
break;
default:
if (vParam == pars->true)
retsv = newSViv(1);
else
retsv = newSViv(0);
break;
} /* switch */
return sv_2mortal(retsv);
}
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"), /* 0 */
s_A("NUM_OF_FIELDS"), /* 1 */
s_A("NAME"), /* 2 */
s_A("NULLABLE"), /* 3 */
s_A("TYPE"), /* 4 */
s_A("PRECISION"), /* 5 */
s_A("SCALE"), /* 6 */
s_A("sol_type"), /* 7 */
s_A("sol_length"), /* 8 */
s_A("CursorName"), /* 9 */
s_A(""), /* END */
};
static T_st_params S_st_store_params[] =
{
s_A(""), /* END */
};
#undef s_A
/*----------------------------------------
* dummy routines st_XXXX
*----------------------------------------
*/
SV *
dbd_st_FETCH_attrib(sth, imp_sth, keysv)
SV *sth;
imp_sth_t *imp_sth;
SV *keysv;
{
dTHR;
STRLEN kl;
char *key = SvPV(keysv,kl);
int i;
SV *retsv = NULL;
T_st_params *par;
int n_fields;
imp_fbh_t *fbh;
char cursor_name[256];
SWORD cursor_name_len;
RETCODE rc;
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 (!imp_sth->done_desc && !dbd_describe(sth, imp_sth))
{
/* dbd_describe has already called ora_error() */
/* we can't return Nullsv here because the xs code will */
/* then just pass the attribute name to DBI for FETCH. */
croak("Describe failed during %s->FETCH(%s)",
SvPV(sth,na), key);
}
i = DBIc_NUM_FIELDS(imp_sth);
switch(par - S_st_fetch_params)
{
AV *av;
case 0: /* NUM_OF_PARAMS */
return Nullsv; /* handled by DBI */
case 1: /* NUM_OF_FIELDS */
retsv = newSViv(i);
break;
case 2: /* NAME */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSVpv(imp_sth->fbh[i].ColName, 0));
break;
case 3: /* NULLABLE */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i,
(imp_sth->fbh[i].ColNullable == SQL_NO_NULLS)
? &sv_no : &sv_yes);
break;
case 4: /* TYPE */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
break;
case 5: /* PRECISION */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSViv(imp_sth->fbh[i].ColDef));
break;
case 6: /* SCALE */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSViv(imp_sth->fbh[i].ColScale));
break;
case 7: /* sol_type */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSViv(imp_sth->fbh[i].ColSqlType));
break;
case 8: /* sol_length */
av = newAV();
retsv = newRV(sv_2mortal((SV*)av));
while(--i >= 0)
av_store(av, i, newSViv(imp_sth->fbh[i].ColLength));
break;
case 9: /* CursorName */
rc = SQLGetCursorName(imp_sth->hstmt,
cursor_name, sizeof(cursor_name), &cursor_name_len);
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "st_FETCH/SQLGetCursorName");
return Nullsv;
}
retsv = newSVpv(cursor_name, cursor_name_len);
break;
case 10:
retsv = newSViv(DBIc_LongReadLen(imp_sth));
break;
default:
return Nullsv;
}
return sv_2mortal(retsv);
}
int
dbd_st_STORE_attrib(sth, imp_sth, keysv, valuesv)
SV *sth;
imp_sth_t *imp_sth;
SV *keysv;
SV *valuesv;
{
dTHR;
D_imp_dbh_from_sth;
STRLEN kl;
STRLEN vl;
char *key = SvPV(keysv,kl);
char *value = SvPV(valuesv, vl);
T_st_params *par;
RETCODE rc;
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;
switch(par - S_st_store_params)
{
case 0:/* */
return TRUE;
}
return FALSE;
}
SV *
adabas_get_info(dbh, ftype)
SV *dbh;
int ftype;
{
dTHR;
D_imp_dbh(dbh);
RETCODE rc;
SV *retsv = NULL;
int i;
char rgbInfoValue[256];
SWORD cbInfoValue = -2;
/* See fancy logic below */
for (i = 0; i < 6; i++)
rgbInfoValue[i] = 0xFF;
}
/* Fancy logic here to determine if result is a string or int */
if (cbInfoValue == -2) /* is int */
retsv = newSViv(*(int *)rgbInfoValue); /* XXX cast */
else if (cbInfoValue != 2 && cbInfoValue != 4) /* must be string */
retsv = newSVpv(rgbInfoValue, 0);
else if (rgbInfoValue[cbInfoValue+1] == '\0') /* must be string */
retsv = newSVpv(rgbInfoValue, 0);
else if (cbInfoValue == 2) /* short */
retsv = newSViv(*(short *)rgbInfoValue); /* XXX cast */
else if (cbInfoValue == 4) /* int */
retsv = newSViv(*(int *)rgbInfoValue); /* XXX cast */
else
croak("panic: SQLGetInfo cbInfoValue == %d", cbInfoValue);
if (dbis->debug >= 2)
fprintf(DBILOGFP, "SQLGetInfo: ftype %d, cbInfoValue %d: %s\n",
ftype, cbInfoValue, neatsvpv(retsv,0));
return sv_2mortal(retsv);
}
int
adabas_describe_col(sth, colno, ColumnName, BufferLength, NameLength, DataType, ColumnSize, DecimalDigits, Nullable)
SV *sth;
int colno;
char *ColumnName;
I16 BufferLength;
I16 *NameLength;
I16 *DataType;
U32 *ColumnSize;
I16 *DecimalDigits;
I16 *Nullable;
{
D_imp_sth(sth);
RETCODE rc;
rc = SQLDescribeCol(imp_sth->hstmt, colno,
ColumnName, BufferLength, NameLength,
DataType, ColumnSize, DecimalDigits, Nullable);
if (!SQL_ok(rc)) {
dbd_error(sth, rc, "DescribeCol/SQLDescribeCol");
return 0;
}
return 1;
}
int
adabas_get_type_info(dbh, sth, ftype)
SV *dbh;
SV *sth;
int ftype;
{
dTHR;
D_imp_dbh(dbh);
D_imp_sth(sth);
RETCODE rc;
SV **svp;
char cname[128]; /* cursorname */
imp_sth->henv = imp_dbh->henv; /* needed for dbd_error */
imp_sth->hdbc = imp_dbh->hdbc;
imp_sth->done_desc = 0;
rc = SQLAllocStmt(imp_dbh->hdbc, &imp_sth->hstmt);
if (rc != SQL_SUCCESS) {
dbd_error(sth, rc, "adabas_get_type_info/SQLGetTypeInfo");
return 0;
}
/* just for sanity, later. Any internals that may rely on this (including */
/* debugging) will have valid data */
imp_sth->statement = (char *)safemalloc(strlen(cSqlGetTypeInfo)+ftype/10+1);
sprintf(imp_sth->statement, cSqlGetTypeInfo, ftype);
rc = SQLGetTypeInfo(imp_sth->hstmt, ftype);
dbd_error(sth, rc, "adabas_get_type_info/SQLGetTypeInfo");
if (!SQL_ok(rc)) {
SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
imp_sth->hstmt = SQL_NULL_HSTMT;
return 0;
}
/* XXX Way too much duplicated code here */
if (dbis->debug >= 2)
fprintf(DBILOGFP,
" adabas_get_type_info/SQLGetTypeInfo sql f%d\n\t%s\n",
imp_sth->hstmt, imp_sth->statement);
/* init sth pointers */
imp_sth->fbh = NULL;
imp_sth->ColNames = NULL;
imp_sth->RowBuffer = NULL;
imp_sth->RowCount = -1;
imp_sth->eod = -1;
if (!dbd_describe(sth, imp_sth)) {
SQLFreeStmt(imp_sth->hstmt, SQL_DROP);
imp_sth->hstmt = SQL_NULL_HSTMT;
return 0; /* dbd_describe already called ora_error() */
}
if (dbd_describe(sth, imp_sth) <= 0)
return 0;
DBIc_IMPSET_on(imp_sth);
imp_sth->RowCount = -1;
rc = SQLRowCount(imp_sth->hstmt, &imp_sth->RowCount);
dbd_error(sth, rc, "st_execute/SQLRowCount");
if (rc != SQL_SUCCESS) {
return -1;
}
DBIc_ACTIVE_on(imp_sth); /* XXX should only set for select ? */
imp_sth->eod = SQL_SUCCESS;
return 1;
( run in 0.506 second using v1.01-cache-2.11-cpan-437f7b0c052 )