DBD-PgSPI
view release on metacpan or search on metacpan
phs->sv_type = SvTYPE(phs->sv); /* part of mutation check */
phs->maxlen = SvLEN(phs->sv)-1; /* avail buffer space */
if (phs->maxlen < 0) { /* can happen with nulls */
phs->maxlen = 0;
}
phs->alen = value_len + phs->alen_incnull;
imp_sth->all_params_len += phs->alen;
if (dbis->debug >= 3) {
PerlIO_printf(DBILOGFP, " bind %s <== '%.*s' (size %ld/%ld, otype %d, indp %d)\n",
phs->name,
(int)(phs->alen>SvIV(DBIS->neatsvpvlen) ? SvIV(DBIS->neatsvpvlen) : phs->alen),
(phs->progv) ? phs->progv : "",
(long)phs->alen, (long)phs->maxlen, phs->ftype, phs->indp);
}
return 1;
}
int
dbd_bind_ph (sth, imp_sth, ph_namesv, newvalue, sql_type, attribs, is_inout, maxlen)
SV *sth;
imp_sth_t *imp_sth;
SV *ph_namesv;
SV *newvalue;
IV sql_type;
SV *attribs;
int is_inout;
IV maxlen;
{
SV **phs_svp;
STRLEN name_len;
char *name;
char namebuf[30];
phs_t *phs;
if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_bind_ph\n"); }
/* check if placeholder was passed as a number */
if (SvGMAGICAL(ph_namesv)) { /* eg if from tainted expression */
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);
}
assert(name != Nullch);
if (SvTYPE(newvalue) > SVt_PVLV) { /* hook for later array logic */
croak("Can't bind a non-scalar value (%s)", neatsvpv(newvalue,0));
}
if (SvROK(newvalue) && !IS_DBI_HANDLE(newvalue)) {
/* dbi handle allowed for cursor variables */
croak("Can't bind a reference (%s)", neatsvpv(newvalue,0));
}
if (is_inout) { /* may allow later */
croak("inout parameters not supported");
}
if (dbis->debug >= 2) {
PerlIO_printf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type);
if (attribs) {
PerlIO_printf(DBILOGFP, ", attribs: %s", neatsvpv(attribs,0));
}
PerlIO_printf(DBILOGFP, ")\n");
}
phs_svp = hv_fetch(imp_sth->all_params_hv, name, name_len, 0);
if (phs_svp == NULL) {
croak("Can't bind unknown placeholder '%s' (%s)", name, neatsvpv(ph_namesv,0));
}
phs = (phs_t*)(void*)SvPVX(*phs_svp); /* placeholder struct */
if (phs->sv == &PL_sv_undef) { /* first bind for this placeholder */
phs->ftype = 1043; /* our default type VARCHAR */
if (attribs) { /* only look for pg_type on first bind of var */
SV **svp;
/* Setup / Clear attributes as defined by attribs. */
/* XXX If attribs is EMPTY then reset attribs to default? */
if ( (svp = hv_fetch((HV*)SvRV(attribs), "pg_type", 7, 0)) != NULL) {
int pg_type = SvIV(*svp);
if (!pgtype_bind_ok(pg_type)) {
croak("Can't bind %s, pg_type %d not supported by DBD::Pg", phs->name, pg_type);
}
if (sql_type) {
croak("Can't specify both TYPE (%d) and pg_type (%d) for %s", sql_type, pg_type, phs->name);
}
phs->ftype = pg_type;
}
}
if (sql_type) {
phs->ftype = pg_sql_type(imp_sth, phs->name, sql_type);
}
} /* was first bind for this placeholder */
else if (sql_type && phs->ftype != pg_sql_type(imp_sth, phs->name, sql_type)) {
croak("Can't change TYPE of param %s to %d after initial bind", phs->name, sql_type);
}
phs->maxlen = maxlen; /* 0 if not inout */
if (phs->sv == &PL_sv_undef) { /* (first time bind) */
phs->sv = newSV(0);
}
sv_setsv(phs->sv, newvalue);
return dbd_rebind_ph(sth, imp_sth, phs);
}
int
dbd_st_execute (sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */
char * pgspi_err_desc (int err) {
switch(err) {
case SPI_ERROR_ARGUMENT:
return "SPI_ERROR_ARGUMENT";
case SPI_ERROR_UNCONNECTED:
return "SPI_ERROR_UNCONNECTED";
case SPI_ERROR_COPY:
return "SPI_ERROR_COPY";
case SPI_ERROR_CURSOR:
return "SPI_ERROR_CURSOR";
case SPI_ERROR_TRANSACTION:
return "SPI_ERROR_TRANSACTION";
case SPI_ERROR_OPUNKNOWN:
return "SPI_ERROR_OPUNKNOWN";
default:
return "UNKNOWN SPI ERROR";
}
}
AV *
dbd_st_fetch (sth, imp_sth)
SV *sth;
imp_sth_t *imp_sth;
{
int num_fields;
HeapTuple tup;
HeapTuple typeTup;
TupleDesc tupdesc;
Form_pg_attribute attdesc;
int i;
AV *av;
SV *sv;
Oid typoutput;
Oid typioparam;
char * attname;
Datum attr;
char * val;
int len;
bool isnull;
if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_fetch\n"); }
/* Check that execute() was executed sucessfully */
if ( !DBIc_ACTIVE(imp_sth) ) {
pg_error(sth, 1, "no statement executing\n");
return Nullav;
}
if ( imp_sth->cur_tuple == imp_sth->rows ) {
imp_sth->cur_tuple = 0;
/* XXX: probably we should consider sth closed here. check latest DBD::Pg */
return Nullav; /* we reached the last tuple */
}
tup = imp_sth->tuples[imp_sth->cur_tuple];
tupdesc = imp_sth->tupdesc;
av = DBIS->get_fbav(imp_sth);
num_fields = AvFILL(av)+1;
/* maybe we should use portals and cursor here? maybe later */
for(i = 0; i < num_fields; ++i) {
attdesc = imp_sth->tupdesc->attrs[i];
attname = NameStr(imp_sth->tupdesc->attrs[i]->attname);
attr = heap_getattr(tup, i +1, tupdesc, &isnull);
sv = AvARRAY(av)[i];
if (isnull) {
sv_setsv(sv, &PL_sv_undef);
} else {
/* we have the value, now lets extract it correctly. We need to be aware
of boolean types to convert them to 0/1, but anything else we can get
as a CSTRING */
typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(attdesc->atttypid), 0, 0, 0);
if (!HeapTupleIsValid(typeTup)) {
elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed", attname, tupdesc->attrs[i]->atttypid);
}
typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput);
typioparam = getTypeIOParam(typeTup);
ReleaseSysCache(typeTup);
if (OidIsValid(typoutput)) {
/* fetch quickly for things that we know,
rely on GetCString for anything else */
switch (attdesc->atttypid) {
case BOOLOID:
sv_setiv(sv, DatumGetBool(attr)?1:0 );
break;
case INT2OID:
sv_setiv(sv, DatumGetInt16(attr) );
break;
case INT4OID:
sv_setiv(sv, DatumGetInt32(attr) );
break;
/* its a bit special
case INT8OID:
sv_setnv(sv, DatumGetInt64(attr) );
break;
*/
default:
val = DatumGetCString(OidFunctionCall3(typoutput, attr,
ObjectIdGetDatum(typioparam),
Int32GetDatum(tupdesc->attrs[i]->atttypmod)
));
switch (attdesc->atttypid) {
/* chopblanks won't quite work
case CHAROID:
case TEXTOID:
case NAMEOID:
case BPCHAROID:
if ( DBIc_has(imp_sth,DBIcf_ChopBlanks) ) {
len = strlen(val);
char *str = val;
while((len > 0) && (str[len-1] == ' ')) {
len--;
}
sv_setpvn(sv, val, len);
} else {
sv_setpv(sv, val);
( run in 1.389 second using v1.01-cache-2.11-cpan-39bf76dae61 )