#ifdef __cplusplus
extern "C" {
#endif
#include "coptypes.h"
#include "dbcarea.h"
#include "coperr.h"
#include "parcel.h"
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
I32 CliUsrLgnOn=0;
I32 CliPPsOn=0;
#define TDAT_HDR_SZ (52)
typedef unsigned char byte;
typedef unsigned short ushort;
typedef struct {
ushort StatementNo;
ushort Info;
ushort Code;
ushort Length;
char Msg[255];
} error_fail_t;
typedef struct {
I32 debug;
DBCAREA dbc;
} dbc_ctx_t, *dbc_ctxptr_t;
STATIC char dummy_hdr[TDAT_HDR_SZ];
STATIC I32
tdcli_write_dbs_error(char *parcel, char *errstr)
{
error_fail_t *Error_Fail = ((error_fail_t *) (parcel));
memcpy(errstr, Error_Fail->Msg, Error_Fail->Length);
errstr[Error_Fail->Length] = 0;
return Error_Fail->Code;
}
MODULE = DBD::Teradata PACKAGE = DBD::Teradata::Cli
void
tdxs_set_debug(dbc, val)
SV * dbc
SV * val
PPCODE:
dbc_ctxptr_t dbcp = INT2PTR(dbc_ctxptr_t, SvUV(dbc));
dbcp->debug = SvTRUE(val) ? SvIV(val) : 0;
ST(0) = &PL_sv_yes;
XSRETURN(1);
void
tdxs_init_dbcarea(debug)
SV * debug
PPCODE:
dbc_ctxptr_t dbc_ctx = NULL;
DBCAREA *dbcp = NULL;
SV *dbcarea = NULL;
I32 result;
char *cnta = NULL;
Newz(0, dbc_ctx, 1, dbc_ctx_t);
dbcp = &dbc_ctx->dbc;
dbc_ctx->debug = SvTRUE(debug) ? SvIV(debug) : 0;
ST(0) = sv_2mortal(newSVuv(PTR2UV(dbc_ctx)));
dbcp->total_len = sizeof (DBCAREA);
DBCHINI (&result, cnta, dbcp);
if (result != EM_OK) {
Perl_croak_nocontext("Cannot init, result is %d\n", result);
Safefree(dbc_ctx);
ST(0) = &PL_sv_undef;
}
XSRETURN(1);
void
tdxs_get_connection(dbcarea, logonstr, mode, runstring, logonsrc, charset)
SV * dbcarea
SV * logonstr
SV * mode
SV * runstring
SV * logonsrc
SV * charset
PPCODE:
I32 result;
STRLEN logonlen;
STRLEN runlen;
STRLEN logonsrclen;
char *mymode;
char *cnta = NULL;
dbc_ctxptr_t dbc_ctx = INT2PTR(dbc_ctxptr_t, SvUV(dbcarea));
DBCAREA *dbcp = &dbc_ctx->dbc;
byte charsetcode = (byte)(SvIV(charset));
char relstr[7];
char verstr[15];
char errstr[256];
I32 sessno = 0;
I32 hostid = 0;
I32 mylsn = 0;
if (dbc_ctx->debug > 2)
printf("Connect: dbcp is %p\n", dbcp);
dbcp->change_opts = 'Y';
dbcp->resp_mode = 'I';
dbcp->use_presence_bits = 'N';
dbcp->keep_resp = 'N';
dbcp->wait_across_crash = 'N';
dbcp->tell_about_crash = 'Y';
dbcp->loc_mode = 'Y';
dbcp->var_len_req = 'N';
dbcp->var_len_fetch = 'N';
dbcp->save_resp_buf = 'N';
dbcp->two_resp_bufs = 'Y';
dbcp->ret_time = 'N';
dbcp->parcel_mode = 'Y';
dbcp->wait_for_resp = 'Y';
dbcp->req_proc_opt = 'E';
dbcp->var_len_req = 'N';
dbcp->maximum_parcel = 'H';
dbcp->inter_ptr = &charsetcode;
dbcp->charset_type = 'C';
dbcp->connect_type = 'C';
mymode = SvPV_nolen(mode);
dbcp->tx_semantics = (! strcmp(mymode, "ANSI")) ? 'A' :
(! strcmp(mymode, "TERADATA")) ? 'T' : 'D';
dbcp->req_buf_len = 65536;
dbcp->resp_buf_len = 63000;
dbcp->logon_ptr = SvPV(logonstr, logonlen);
dbcp->logon_len = logonlen;
if (SvTRUE(runstring)) {
dbcp->run_ptr = SvPV(runstring, runlen);
dbcp->run_len = runlen;
}
if (SvTRUE(logonsrc)) {
dbcp->using_data_ptr = SvPV(logonsrc, logonsrclen);
dbcp->using_data_len = logonsrclen;
}
dbcp->func = DBFCON;
if (dbc_ctx->debug)
printf("get_connection: connecting\n");
EXTEND(SP, 6);
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK) {
if (dbc_ctx->debug)
printf("get_connection: connection failed\n");
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
Safefree(dbc_ctx);
XSRETURN(5);
}
dbcp->i_req_id = dbcp->o_req_id;
dbcp->i_sess_id = dbcp->o_sess_id;
if (dbc_ctx->debug)
printf("get_connection: fetching result\n");
dbcp->func = DBFFET;
result = EM_OK;
while (result == EM_OK) {
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK)
break;
switch (dbcp->fet_parcel_flavor) {
case PclLSN:
mylsn = *(I32 *)dbcp->fet_data_ptr;
break;
case PclSUCCESS:
break;
case PclFAILURE:
case PclERROR:
result = tdcli_write_dbs_error(dbcp->fet_data_ptr, errstr);
sv_setiv(dbcarea, (IV)0);
Safefree(dbc_ctx);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(errstr, strlen(errstr))));
XSRETURN(5);
case PclENDSTATEMENT:
case PclENDREQUEST:
break;
default:
break;
}
}
if ((result != EM_OK) && (result != REQEXHAUST)) {
if (dbc_ctx->debug)
printf("get_connection: odd result\n");
sv_setiv(dbcarea, (IV)0);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(&PL_sv_undef);
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
Safefree(dbc_ctx);
XSRETURN(5);
}
sessno = dbcp->o_dbc_sess_id;
hostid = dbcp->o_host_id;
if (dbc_ctx->debug)
printf("Connect: Session is %d\n", dbcp->o_dbc_sess_id);
dbcp->func = DBFERQ;
DBCHCL (&result, cnta, dbcp);
dbcp->charset_type = 0;
dbcp->connect_type = 0;
dbcp->inter_ptr = NULL;
DBCHREL(&result, cnta, dbcp->i_sess_id, relstr, verstr);
if (dbc_ctx->debug > 2)
printf("Connect exit: dbcp is %p\n", dbcp);
PUSHs(sv_2mortal(newSViv(sessno)));
PUSHs(sv_2mortal(newSViv(hostid)));
PUSHs(sv_2mortal(newSVpv(verstr, strlen(verstr))));
PUSHs(sv_2mortal(newSViv(mylsn)));
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(5);
void
tdxs_get_tdat_release(dbc)
SV *dbc
PPCODE:
dbc_ctx_t *dbc_ctx = (dbc_ctx_t *)SvIV(dbc);
DBCAREA *dbcp = &dbc_ctx->dbc;
char relstr[7];
char verstr[15];
I32 result;
char cnta[1];
DBCHREL(&result, cnta, dbcp->i_sess_id, relstr, verstr);
ST(0) = sv_2mortal(newSVpv(verstr, strlen(verstr)));
XSRETURN(1);
void
tdxs_cleanup(dbc, errstr)
SV *dbc
SV *errstr
PPCODE:
dbc_ctxptr_t dbc_ctx = INT2PTR(dbc_ctxptr_t, SvUV(dbc));
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result;
char *cnta = NULL;
dbcp->func = DBFDSC;
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK)
sv_setpv(errstr, dbcp->msg_text);
else
sv_setsv(errstr, &PL_sv_undef);
Safefree(dbc_ctx);
sv_setsv(dbc, &PL_sv_undef);
ST(0) = sv_2mortal(newSViv(result));
XSRETURN(1);
void
tdxs_send_request(dbc, len, keepresp, buffer, resplen)
SV * dbc
SV * len
SV * keepresp
SV * buffer
SV * resplen
PPCODE:
STRLEN buflen;
STRLEN rlen;
char *buf = SvPV(buffer, buflen) + TDAT_HDR_SZ;
dbc_ctxptr_t dbc_ctx = INT2PTR(dbc_ctxptr_t, SvUV(dbc));
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result;
char *cnta = NULL;
buflen = SvIV(len);
buflen -= TDAT_HDR_SZ;
rlen = SvIV(resplen);
rlen -= TDAT_HDR_SZ;
if (dbc_ctx->debug > 2)
printf("send_request: dbcp is %p\n", dbcp);
dbcp->change_opts = 'Y';
if (dbc_ctx->debug && SvTRUE(keepresp))
printf("KEEPRESP requested\n");
dbcp->keep_resp = (SvTRUE(keepresp) ? 'Y' : 'N');
dbcp->request_mode = 'B';
dbcp->loc_mode = 'Y';
dbcp->parcel_mode = 'N';
dbcp->req_proc_opt = 'E';
dbcp->req_ptr = buf;
dbcp->req_len = buflen;
dbcp->req_buf_len = buflen + 100;
dbcp->resp_buf_len = rlen;
if (dbc_ctx->debug)
printf("send_request: request length is %i\n", buflen);
dbcp->func = DBFIRQ;
DBCHCL (&result, cnta, dbcp);
EXTEND(SP, 3);
if (result != EM_OK) {
PUSHs(&PL_sv_undef);
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
XSRETURN(2);
}
dbcp->i_req_id = dbcp->o_req_id;
if (dbc_ctx->debug)
printf("send_request: request sent; reqid %i\n", dbcp->o_req_id);
PUSHs(sv_2mortal(newSViv(dbcp->o_req_id)));
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(2);
void
tdxs_wait_for_response()
PPCODE:
I32 result = EM_OK;
I32 sessid = 0;
I32 token = 0;
char *cnta = NULL;
DBCHWAT(&result, cnta, &sessid, &token);
EXTEND(SP, 3);
if (result != EM_OK) {
PUSHs(&PL_sv_undef);
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(&PL_sv_undef);
XSRETURN(3);
}
PUSHs(sv_2mortal(newSViv(sessid)));
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(3);
void
tdxs_get_response(dbc, buffer, reqid, keepresp, wait_for_resp)
SV *dbc
SV *buffer
SV *reqid
SV *keepresp
SV *wait_for_resp
PPCODE:
dbc_ctx_t *dbc_ctx = (dbc_ctx_t *)SvIV(dbc);
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result;
char *cnta = NULL;
char *fullbuf = NULL;
SV *newbuf = NULL;
if (dbc_ctx->debug > 2)
printf("get_response: dbcp is %p\n", dbcp);
dbcp->i_req_id = SvIV(reqid);
dbcp->change_opts = 'Y';
if (dbc_ctx->debug > 2)
printf((SvTRUE(keepresp) ? "reqid %d KEEPRESP\n" : "reqid %d RESP\n"),
dbcp->i_req_id);
if ((dbc_ctx->debug > 2) && SvTRUE(keepresp))
printf("KEEPRESP on req %d\n", dbcp->i_req_id);
dbcp->keep_resp = (SvTRUE(keepresp) ? 'Y' : 'N');
dbcp->wait_for_resp = (SvTRUE(wait_for_resp) ? 'Y' : 'N');
if (dbc_ctx->debug)
printf("Wait for resp is %c\n", dbcp->wait_for_resp);
dbcp->loc_mode = 'Y';
dbcp->parcel_mode = 'N';
dbcp->request_mode = 'B';
dbcp->resp_buf_len = 63000;
dbcp->func = DBFFET;
result = EM_OK;
if (dbc_ctx->debug)
printf("get_response: getting response for %d\n", SvIV(reqid));
DBCHCL (&result, cnta, dbcp);
EXTEND(SP, 2);
if (result != EM_OK) {
if (dbc_ctx->debug)
printf("get_response: got error %d\n", result);
PUSHs(sv_2mortal(newSViv(result)));
if (SvTRUE(wait_for_resp) || (result != EM_NODATA))
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
else
PUSHs(&PL_sv_undef);
XSRETURN(2);
}
if (dbc_ctx->debug)
printf("get_response: response length is %i\n", dbcp->fet_ret_data_len);
sv_setpvn(buffer, dummy_hdr, TDAT_HDR_SZ);
sv_catpvn(buffer, dbcp->fet_data_ptr, dbcp->fet_ret_data_len);
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(2);
void
tdxs_end_request(dbc, reqid)
SV *dbc
int reqid
PPCODE:
dbc_ctxptr_t dbc_ctx = INT2PTR(dbc_ctxptr_t, SvUV(dbc));
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result = EM_OK;
char *cnta = NULL;
if (dbc_ctx->debug)
printf("EndReq: End request for %d\n", reqid);
dbcp->i_req_id = reqid;
dbcp->func = DBFERQ;
DBCHCL (&result, cnta, dbcp);
EXTEND(SP,2);
if (result != EM_OK) {
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
XSRETURN(2);
}
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(2);
void
tdxs_abort_request(dbc, reqid)
SV * dbc
int reqid
PPCODE:
dbc_ctxptr_t dbc_ctx = INT2PTR(dbc_ctxptr_t, SvUV(dbc));
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result = EM_OK;
char *cnta = NULL;
if (dbc_ctx->debug)
printf("AbortReq: Abort request for %d\n", reqid);
dbcp->i_req_id = reqid;
dbcp->func = DBFABT;
DBCHCL (&result, cnta, dbcp);
EXTEND(SP,2);
if (result != EM_OK) {
PUSHs(sv_2mortal(newSViv(result)));
PUSHs(sv_2mortal(newSVpv(dbcp->msg_text, dbcp->msg_len)));
XSRETURN(2);
}
PUSHs(sv_2mortal(newSViv(0)));
PUSHs(&PL_sv_undef);
XSRETURN(2);
void
tdxs_test_leak(dbc, buffer, count)
SV * dbc
SV * buffer
SV * count
PPCODE:
STRLEN buflen;
char *buf = SvPV(buffer, buflen) + TDAT_HDR_SZ;
dbc_ctx_t *dbc_ctx = (dbc_ctx_t *)SvIV(dbc);
DBCAREA *dbcp = &dbc_ctx->dbc;
I32 result;
char *cnta = NULL;
int i = SvIV(count);
buflen -= TDAT_HDR_SZ;
while (i > 0) {
i--;
if (dbc_ctx->debug > 2)
printf("send_request: dbcp is %p\n", dbcp);
dbcp->change_opts = 'Y';
dbcp->request_mode = 'B';
dbcp->keep_resp = 'N';
dbcp->loc_mode = 'Y';
dbcp->parcel_mode = 'N';
dbcp->req_proc_opt = 'E';
dbcp->req_ptr = buf;
dbcp->req_len = buflen;
dbcp->req_buf_len = 65536;
dbcp->resp_buf_len = 63000;
dbcp->func = DBFIRQ;
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK) {
printf("%s\n", dbcp->msg_text);
ST(0) = sv_2mortal(newSViv(result));
XSRETURN(1);
}
dbcp->i_req_id = dbcp->o_req_id;
dbcp->i_sess_id = dbcp->o_sess_id;
dbcp->change_opts = 'Y';
dbcp->wait_for_resp = 'Y';
dbcp->loc_mode = 'Y';
dbcp->parcel_mode = 'N';
dbcp->request_mode = 'B';
dbcp->resp_buf_len = 63000;
dbcp->func = DBFFET;
result = EM_OK;
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK) {
printf("%s\n", dbcp->msg_text);
ST(0) = sv_2mortal(newSViv(result));
XSRETURN(1);
}
dbcp->func = DBFERQ;
DBCHCL (&result, cnta, dbcp);
if (result != EM_OK) {
printf("%s\n", dbcp->msg_text);
ST(0) = sv_2mortal(newSViv(result));
XSRETURN(1);
}
}
printf("test_leak comnpleted\n");
ST(0) = sv_2mortal(newSViv(0));
XSRETURN(1);