#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "tdsql.h"
int
g_msglevel;
double
g_activcount;
int
g_errorcode;
char
g_errormsg[260];
struct
datadescr ddesc[3];
static
SV * c_msgl_sv;
static
SV * c_actv_sv;
static
SV * c_errc_sv;
static
SV * c_emsg_sv;
Request request0;
int
r0_in_use = 0;
static
int
not_here(
char
*s)
{
croak(
"%s not implemented on this architecture"
, s);
return
-1;
}
MODULE = Teradata::SQL PACKAGE = Teradata::SQL
# CONNECT to Teradata
SV *
Xconnect(
log
, ccs, tmode, logmech)
PROTOTYPE:$$$$
INPUT:
char
*
log
char
* ccs
char
* tmode
char
* logmech
PREINIT:
pSession sess_ptr;
int
ok;
CODE:
c_msgl_sv = get_sv(
"Teradata::SQL::msglevel"
, FALSE);
c_actv_sv = get_sv(
"Teradata::SQL::activcount"
, FALSE);
c_errc_sv = get_sv(
"Teradata::SQL::errorcode"
, FALSE);
c_emsg_sv = get_sv(
"Teradata::SQL::errormsg"
, FALSE);
g_msglevel = SvIV(c_msgl_sv);
New(0, sess_ptr, 1, Session);
ok = Zconnect(sess_ptr,
log
, ccs, tmode, logmech);
if
(ok) {
RETVAL = newSVpvn((
char
*) sess_ptr,
sizeof
(Session));
}
else
{
RETVAL = newSVpvn(
"NO SESS"
, 7);
}
Safefree(sess_ptr);
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# DISCONNECT
int
Xdisconnect(sess)
PROTOTYPE:$
INPUT:
SV * sess
CODE:
pSession sess_ptr;
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
RETVAL = Zdisconnect(sess_ptr);
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# EXECUTE without arguments
int
Xexecute(sess, sql)
PROTOTYPE:$$
INPUT:
SV * sess
char
* sql
CODE:
pSession sess_ptr;
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
RETVAL = Zexecute(sess_ptr, sql);
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# OPEN without arguments
SV *
Xopen(sess, sql)
PROTOTYPE:$$
INPUT:
SV * sess
char
* sql
PREINIT:
pSession sess_ptr;
Request req;
int
ok;
CODE:
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
req.dbcp = &(sess_ptr->dbc);
ok = Zopen(&req, sql);
if
(ok) {
RETVAL = newSVpvn((
char
*) &req,
sizeof
(Request));
}
else
{
RETVAL = newSV(0);
}
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# EXECUTE a prepared request with optional arguments
int
Xexecutep(sess, sql, ...)
PROTOTYPE:$$
INPUT:
SV * sess
char
* sql
PREINIT:
pSession sess_ptr;
int
i, nindic, idlen, nargs;
Int32 wint;
char
* sptr;
STRLEN slen;
double
wdouble;
Byte hv_data[MAX_RDA_LEN];
Byte * hvdata_ptr;
Byte * hvindic_ptr;
Byte indic_mask;
struct
ModCliDataInfoType hv_datainfo;
struct
ModCliDInfoType * hv_datainfo_ptr;
CODE:
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
if
(items == 2) {
RETVAL = Zexecutep(sess_ptr, sql);
}
else
{
nargs = items - 2;
nindic = (nargs + 7) / 8;
idlen = nindic;
hvindic_ptr = hv_data;
*hvindic_ptr = 0x00;
indic_mask = 0x80;
hvdata_ptr = hv_data + nindic;
hv_datainfo.FieldCount = (PclWord) nargs;
hv_datainfo_ptr = &(hv_datainfo.InfoVar[0]);
for
(i = 2; i < items; i++) {
if
( SvIOK(ST(i)) ) {
hv_datainfo_ptr->SQLType = INTEGER_N;
hv_datainfo_ptr->SQLLen = 4;
wint = SvIV(ST(i));
memcpy
(hvdata_ptr, &wint, 4);
hvdata_ptr += 4;
idlen += 4;
}
else
if
( SvNOK(ST(i)) ) {
hv_datainfo_ptr->SQLType = FLOAT_N;
hv_datainfo_ptr->SQLLen = 8;
wdouble = SvNV(ST(i));
memcpy
(hvdata_ptr, &wdouble, 8);
hvdata_ptr += 8;
idlen += 8;
}
else
if
( SvPOK(ST(i)) ) {
sptr = SvPV(ST(i), slen);
hv_datainfo_ptr->SQLType = CHAR_N;
hv_datainfo_ptr->SQLLen = slen;
memcpy
(hvdata_ptr, sptr, slen);
hvdata_ptr += slen;
idlen += slen;
}
else
{
hv_datainfo_ptr->SQLType = INTEGER_N;
hv_datainfo_ptr->SQLLen = 4;
wint = 0;
memcpy
(hvdata_ptr, &wint, 4);
*hvindic_ptr |= indic_mask;
hvdata_ptr += 4;
idlen += 4;
}
hv_datainfo_ptr++;
if
(indic_mask != 0x01) {
indic_mask >>= 1;
}
else
{
indic_mask = 0x80;
hvindic_ptr++;
}
}
RETVAL = Zexecutep_args(sess_ptr, sql, &hv_datainfo,
hv_data, idlen);
}
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# OPEN without arguments, segmented
SV *
Xopenseg(sess, sql, save_spl)
PROTOTYPE:$$
INPUT:
SV * sess
char
* sql
char
* save_spl
PREINIT:
pSession sess_ptr;
Request req;
int
ok;
CODE:
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
req.dbcp = &(sess_ptr->dbc);
ok = Zopenseg(&req, sql, save_spl);
if
(ok) {
RETVAL = newSVpvn((
char
*) &req,
sizeof
(Request));
}
else
{
RETVAL = newSV(0);
}
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# OPEN a prepared request with optional arguments
SV *
Xopenp(sess, sql, ...)
PROTOTYPE:$$
INPUT:
SV * sess
char
* sql
PREINIT:
int
i, wint, nindic, idlen, nargs;
int
ok;
pSession sess_ptr;
Request req;
char
* sptr;
STRLEN slen;
double
wdouble;
Byte hv_data[MAX_RDA_LEN];
Byte * hvdata_ptr;
Byte * hvindic_ptr;
Byte indic_mask;
struct
ModCliDataInfoType hv_datainfo;
struct
ModCliDInfoType * hv_datainfo_ptr;
CODE:
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
req.dbcp = &(sess_ptr->dbc);
if
(items == 2) {
ok = Zopenp(&req, sql);
}
else
{
nargs = items - 2;
nindic = (nargs + 7) / 8;
idlen = nindic;
hvindic_ptr = hv_data;
*hvindic_ptr = 0x00;
indic_mask = 0x80;
hvdata_ptr = hv_data + nindic;
hv_datainfo.FieldCount = (PclWord) nargs;
hv_datainfo_ptr = &(hv_datainfo.InfoVar[0]);
for
(i = 2; i < items; i++) {
if
( SvIOK(ST(i)) ) {
hv_datainfo_ptr->SQLType = INTEGER_N;
hv_datainfo_ptr->SQLLen = 4;
wint = SvIV(ST(i));
memcpy
(hvdata_ptr, &wint, 4);
hvdata_ptr += 4;
idlen += 4;
}
else
if
( SvNOK(ST(i)) ) {
hv_datainfo_ptr->SQLType = FLOAT_N;
hv_datainfo_ptr->SQLLen = 8;
wdouble = SvNV(ST(i));
memcpy
(hvdata_ptr, &wdouble, 8);
hvdata_ptr += 8;
idlen += 8;
}
else
if
( SvPOK(ST(i)) ) {
sptr = SvPV(ST(i), slen);
hv_datainfo_ptr->SQLType = CHAR_N;
hv_datainfo_ptr->SQLLen = slen;
memcpy
(hvdata_ptr, sptr, slen);
hvdata_ptr += slen;
idlen += slen;
}
else
{
hv_datainfo_ptr->SQLType = INTEGER_N;
hv_datainfo_ptr->SQLLen = 4;
wint = 0;
memcpy
(hvdata_ptr, &wint, 4);
*hvindic_ptr |= indic_mask;
hvdata_ptr += 4;
idlen += 4;
}
hv_datainfo_ptr++;
if
(indic_mask != 0x01) {
indic_mask >>= 1;
}
else
{
indic_mask = 0x80;
hvindic_ptr++;
}
}
ok = Zopenp_args(&req, sql,
&hv_datainfo, hv_data, idlen);
}
if
(ok) {
RETVAL = newSVpvn((
char
*) &req,
sizeof
(Request));
}
else
{
RETVAL = newSV(0);
}
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# FETCH. Last argument says whether this is fetching into a
# hash or not.
void
Xfetch(req, hash)
PROTOTYPE:$$
INPUT:
SV * req
int
hash
PREINIT:
int
i, decp, decs;
pRequest req_ptr;
STRLEN slen;
Int16 dlen;
char
* sptr;
char
* ret_data;
Byte * indic_ptr;
Byte * data_ptr;
struct
datadescr * ddesc_ptr;
Int32 wint;
double
wdouble;
char
wstring[24];
Byte indic_mask;
PPCODE:
g_msglevel = SvIV(c_msgl_sv);
req_ptr = (pRequest) SvPV_nolen(req);
ret_data = Zfetch(req_ptr);
if
(ret_data) {
ddesc_ptr = &(req_ptr->ddesc);
indic_ptr = (Byte *) ret_data;
indic_mask = 0x80;
data_ptr = ((Byte *) ret_data) + ( (ddesc_ptr->nfields + 7) / 8);
for
(i = 0; i < ddesc_ptr->nfields; i++) {
if
(hash) {
slen =
strlen
(ddesc_ptr->sqlvar[i].colident);
sptr = (
char
*)ddesc_ptr->sqlvar[i].colident;
XPUSHs(sv_2mortal(newSVpvn(sptr, slen)));
}
switch
(ddesc_ptr->sqlvar[i].sqltype) {
case
INTEGER_N:
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
wint = *((Int32 *)data_ptr) + 0;
XPUSHs(sv_2mortal(newSViv(wint)));
}
data_ptr += 4;
break
;
case
SMALLINT_N:
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
wint = *((Int16 *)data_ptr) + 0;
XPUSHs(sv_2mortal(newSViv(wint)));
}
data_ptr += 2;
break
;
case
BYTEINT_N:
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
wint = *((ByteInt *)data_ptr) + 0;
XPUSHs(sv_2mortal(newSViv(wint)));
}
data_ptr++;
break
;
case
CHAR_N:
slen = ddesc_ptr->sqlvar[i].datalen;
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
sptr = (
char
*) data_ptr;
XPUSHs(sv_2mortal(newSVpvn(sptr, slen)));
}
data_ptr += slen;
break
;
case
VARCHAR_N:
slen = *((UInt16 *) data_ptr);
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
sptr = (
char
*) (data_ptr + 2);
XPUSHs(sv_2mortal(newSVpvn(sptr, slen)));
}
data_ptr += slen + 2;
break
;
case
DECIMAL_N:
decp = ddesc_ptr->sqlvar[i].datalen;
decs = ddesc_ptr->sqlvar[i].decscale;
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
data_ptr += ddesc_ptr->sqlvar[i].dlb;
}
else
if
(decp <= 9) {
wdouble = _dec_to_double(data_ptr, decp, decs);
XPUSHs(sv_2mortal(newSVnv(wdouble)));
data_ptr += ddesc_ptr->sqlvar[i].dlb;
}
else
if
(decp <= 18) {
_dec_to_string(wstring, data_ptr, decs);
slen =
strlen
(wstring);
XPUSHs(sv_2mortal(newSVpvn(wstring, slen)));
data_ptr += 8;
}
else
{
if
(g_msglevel > 0)
warn(
"Decimal field too large"
);
XPUSHs(sv_2mortal(newSVnv(0.0)));
data_ptr += 16;
}
break
;
case
BIGINT_N:
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
_dec_to_string(wstring, data_ptr, 0);
slen =
strlen
(wstring);
XPUSHs(sv_2mortal(newSVpvn(wstring, slen)));
}
data_ptr += 8;
break
;
case
NUMBER_N:
dlen = 0 + *((
char
*) data_ptr);
decp = ddesc_ptr->sqlvar[i].datalen;
decs = ddesc_ptr->sqlvar[i].decscale;
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
data_ptr += dlen + 1;
}
else
if
(dlen <= 9) {
wdouble = _num_to_double(data_ptr);
XPUSHs(sv_2mortal(newSVnv(wdouble)));
data_ptr += dlen + 1;
}
else
if
(dlen == 10) {
_num_to_string(wstring, data_ptr);
slen =
strlen
(wstring);
XPUSHs(sv_2mortal(newSVpvn(wstring, slen)));
data_ptr += dlen + 1;
}
else
{
if
(g_msglevel > 0)
warn(
"Number field too large"
);
XPUSHs(sv_2mortal(newSVnv(0.0)));
data_ptr += dlen + 1;
}
break
;
case
FLOAT_N:
if
( (*indic_ptr & indic_mask) > 0) {
XPUSHs(&PL_sv_undef);
}
else
{
wdouble = *((
double
*) data_ptr);
XPUSHs(sv_2mortal(newSVnv(wdouble)));
}
data_ptr += 8;
break
;
default
:
croak(
"Data type %d not supported\n"
,
ddesc_ptr->sqlvar[i].sqltype);
}
if
(indic_mask != 0x01) {
indic_mask >>= 1;
}
else
{
indic_mask = 0x80;
indic_ptr++;
}
}
}
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
# CLOSE
int
Xclose(req)
PROTOTYPE:$
INPUT:
SV * req
CODE:
pRequest req_ptr;
g_msglevel = SvIV(c_msgl_sv);
req_ptr = (pRequest) SvPV_nolen(req);
RETVAL = Zclose(req_ptr);
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# ABORT (DBFABT)
int
Xabort(sess)
PROTOTYPE:$
INPUT:
SV * sess
CODE:
pSession sess_ptr;
g_msglevel = SvIV(c_msgl_sv);
sess_ptr = (pSession) SvPV_nolen(sess);
RETVAL = Zabort(sess_ptr);
sv_setnv(c_actv_sv, g_activcount);
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);
OUTPUT:
RETVAL
# SERVER_INFO (DBCHQE)
void
Xserver_info(server, qepitem)
PROTOTYPE:$$
INPUT:
char
* server
int
qepitem
PREINIT:
int
wint, string_len;
int
ok;
DBCHQEP our_qep;
Byte hqe_ret_data[200];
char
* RArea_char_ptr;
char
* ret_ptr;
char
hqe_message[258];
struct
QEPDBLIMIT_ our_dblimit;
PPCODE:
c_msgl_sv = get_sv(
"Teradata::SQL::msglevel"
, FALSE);
c_errc_sv = get_sv(
"Teradata::SQL::errorcode"
, FALSE);
c_emsg_sv = get_sv(
"Teradata::SQL::errormsg"
, FALSE);
g_msglevel = SvIV(c_msgl_sv);
our_qep.qepLevel = QEPL10NLVL1;
our_qep.qepItem = qepitem;
our_qep.qepTLen =
strlen
(server);
#ifdef CLI_64BIT
our_qep.qepTIdP = server;
#else
our_qep.qepTDP = (Int32) server;
#endif
our_qep.qepRALen = 200;
our_qep.qepRArea = hqe_ret_data;
memcpy
(our_qep.qepMLid,
"EN"
, 2);
our_qep.qepMsgP = hqe_message;
our_qep.qepMsgM = 256;
ok = Zserver_info(&our_qep);
if
(ok) {
RArea_char_ptr = (
char
*) our_qep.qepRArea;
switch
(our_qep.qepItem) {
case
QEPIDBR:
ret_ptr = RArea_char_ptr;
for
(string_len=0; string_len < 30; string_len++) {
if
(*ret_ptr ==
' '
)
break
;
else
ret_ptr++;
}
XPUSHs(sv_2mortal(newSVpvn(RArea_char_ptr, string_len)));
RArea_char_ptr += 30;
ret_ptr = RArea_char_ptr;
for
(string_len=0; string_len < 32; string_len++) {
if
(*ret_ptr ==
' '
)
break
;
else
ret_ptr++;
}
XPUSHs(sv_2mortal(newSVpvn(RArea_char_ptr, string_len)));
break
;
case
QEPISC:
case
QEPICL2R:
case
QEPIASL:
case
QEPIDCS:
XPUSHs(sv_2mortal(newSVpvn(RArea_char_ptr,
our_qep.qepRDLen)));
break
;
case
QEPIFTSM:
case
QEPIFLCS:
case
QEPIFUCR:
case
QEPIFRFI:
case
QEPIDTSM:
case
QEP64K:
case
QEPIFSSO:
case
QEPIFUPS:
case
QEPIAOP:
case
QEPIFMRG:
case
QEPIFLOB:
case
QEPIXRS:
case
QEPIUD:
case
QEPIRPO:
case
QEPIESS:
case
QEPIUDT:
case
QEPIRCA:
XPUSHs(sv_2mortal(newSVpvn(our_qep.qepRArea, 1)));
break
;
case
QEPIDPF:
case
QEPIDMSS:
wint = *((
int
*)our_qep.qepRArea);
XPUSHs(sv_2mortal(newSViv(wint)));
break
;
case
QEPIEPU:
case
QEPIAPH:
wint = *((Int16 *)our_qep.qepRArea);
XPUSHs(sv_2mortal(newSViv(wint)));
break
;
case
QEPITPR:
wint = *((Int16 *)RArea_char_ptr);
XPUSHs(sv_2mortal(newSViv(wint)));
wint = *((Int16 *)(RArea_char_ptr + 2));
XPUSHs(sv_2mortal(newSViv(wint)));
break
;
case
QEPISQL:
memcpy
(&our_dblimit, our_qep.qepRArea,
sizeof
(
struct
QEPDBLIMIT_));
wint = (
int
) our_dblimit.MaxRowBytes;
XPUSHs(sv_2mortal(newSViv(wint)));
wint = (
int
) our_dblimit.MaxLobBytes;
XPUSHs(sv_2mortal(newSViv(wint)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxObjectNameChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxColinTbl)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxTblinSel)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxColinSel)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxColGrpBy)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxColOrdrBy)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxCharLiteralChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxBinLiteralChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxColBytes)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxCharChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxVarcharChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxGraphicChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxVargraphicChars)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxByteBytes)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxVarbyteBytes)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxDecimal)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxTimeScale)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxTimeStampScale)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxIntervalToSecondScale)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxFldsUsingRow)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxParamsInRequest)));
XPUSHs(sv_2mortal(newSViv(our_dblimit.MaxSPParams)));
break
;
default
:
XPUSHs(&PL_sv_undef);
}
}
else
{
XPUSHs(&PL_sv_undef);
}
sv_setiv(c_errc_sv, g_errorcode);
sv_setpv(c_emsg_sv, g_errormsg);