summaryrefslogtreecommitdiff
path: root/install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c
diff options
context:
space:
mode:
Diffstat (limited to 'install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c')
-rw-r--r--install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c2024
1 files changed, 0 insertions, 2024 deletions
diff --git a/install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c b/install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c
deleted file mode 100644
index 55f4ee7..0000000
--- a/install/5.005/DBD-Pg-1.22-fixvercmp/dbdimp.c
+++ /dev/null
@@ -1,2024 +0,0 @@
-/*
- $Id: dbdimp.c,v 1.1 2004-04-29 09:21:28 ivan Exp $
-
- Copyright (c) 1997,1998,1999,2000 Edmund Mergl
- Copyright (c) 2002 Jeffrey W. Baker
- Portions Copyright (c) 1994,1995,1996,1997 Tim Bunce
-
- You may distribute under the terms of either the GNU General Public
- License or the Artistic License, as specified in the Perl README file.
-
-*/
-
-
-/*
- hard-coded OIDs: (here we need the postgresql types)
- pg_sql_type() 1042 (bpchar), 1043 (varchar)
- ddb_st_fetch() 1042 (bpchar), 16 (bool)
- ddb_preparse() 1043 (varchar)
- pgtype_bind_ok()
-*/
-
-#include "Pg.h"
-
-/* XXX DBI should provide a better version of this */
-#define IS_DBI_HANDLE(h) (SvROK(h) && SvTYPE(SvRV(h)) == SVt_PVHV && SvRMAGICAL(SvRV(h)) && (SvMAGIC(SvRV(h)))->mg_type == 'P')
-
-DBISTATE_DECLARE;
-
-/* hard-coded array delimiter */
-static char* array_delimiter = ",";
-
-static void dbd_preparse (imp_sth_t *imp_sth, char *statement);
-
-
-void
-dbd_init (dbistate)
- dbistate_t *dbistate;
-{
- DBIS = dbistate;
-}
-
-
-int
-dbd_discon_all (drh, imp_drh)
- SV *drh;
- imp_drh_t *imp_drh;
-{
- dTHR;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_discon_all\n"); }
-
- /* The disconnect_all concept is flawed and needs more work */
- if (!dirty && !SvTRUE(perl_get_sv("DBI::PERL_ENDING",0))) {
- sv_setiv(DBIc_ERR(imp_drh), (IV)1);
- sv_setpv(DBIc_ERRSTR(imp_drh),
- (char*)"disconnect_all not implemented");
- DBIh_EVENT2(drh, ERROR_event,
- DBIc_ERR(imp_drh), DBIc_ERRSTR(imp_drh));
- return FALSE;
- }
- if (perl_destruct_level) {
- perl_destruct_level = 0;
- }
- return FALSE;
-}
-
-
-/* Database specific error handling. */
-
-void
-pg_error (h, error_num, error_msg)
- SV *h;
- int error_num;
- char *error_msg;
-{
- D_imp_xxh(h);
- char *err, *src, *dst;
- int len = strlen(error_msg);
-
- err = (char *)malloc(len + 1);
- if (!err) {
- return;
- }
- src = error_msg;
- dst = err;
-
- /* copy error message without trailing newlines */
- while (*src != '\0' && *src != '\n') {
- *dst++ = *src++;
- }
- *dst = '\0';
-
- sv_setiv(DBIc_ERR(imp_xxh), (IV)error_num); /* set err early */
- sv_setpv(DBIc_ERRSTR(imp_xxh), (char*)err);
- DBIh_EVENT2(h, ERROR_event, DBIc_ERR(imp_xxh), DBIc_ERRSTR(imp_xxh));
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "%s error %d recorded: %s\n", err, error_num, SvPV(DBIc_ERRSTR(imp_xxh),na)); }
- free(err);
-}
-
-static int
-pgtype_bind_ok (dbtype)
- int dbtype;
-{
- /* basically we support types that can be returned as strings */
- switch(dbtype) {
- case 16: /* bool */
- case 17: /* bytea */
- case 18: /* char */
- case 20: /* int8 */
- case 21: /* int2 */
- case 23: /* int4 */
- case 25: /* text */
- case 26: /* oid */
- case 700: /* float4 */
- case 701: /* float8 */
- case 702: /* abstime */
- case 703: /* reltime */
- case 704: /* tinterval */
- case 1042: /* bpchar */
- case 1043: /* varchar */
- case 1082: /* date */
- case 1083: /* time */
- case 1184: /* datetime */
- case 1186: /* timespan */
- case 1296: /* timestamp */
- return 1;
- }
- return 0;
-}
-
-
-/* ================================================================== */
-
-int
-pg_db_login (dbh, imp_dbh, dbname, uid, pwd)
- SV *dbh;
- imp_dbh_t *imp_dbh;
- char *dbname;
- char *uid;
- char *pwd;
-{
- dTHR;
-
- char *conn_str;
- char *src;
- char *dest;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "pg_db_login\n"); }
-
- /* build connect string */
- /* DBD-Pg syntax: 'dbname=dbname;host=host;port=port' */
- /* pgsql syntax: 'dbname=dbname host=host port=port user=uid password=pwd' */
-
- conn_str = (char *)malloc(strlen(dbname) + strlen(uid) + strlen(pwd) + 16 + 1);
- if (! conn_str) {
- return 0;
- }
-
- src = dbname;
- dest = conn_str;
- while (*src) {
- if (*src != ';') {
- *dest++ = *src++;
- continue;
- }
- *dest++ = ' ';
- src++;
- }
- *dest = '\0';
-
- if (strlen(uid)) {
- strcat(conn_str, " user=");
- strcat(conn_str, uid);
- }
- if (strlen(uid) && strlen(pwd)) {
- strcat(conn_str, " password=");
- strcat(conn_str, pwd);
- }
-
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "pg_db_login: conn_str = >%s<\n", conn_str); }
-
- /* make a connection to the database */
- imp_dbh->conn = PQconnectdb(conn_str);
- free(conn_str);
-
- /* check to see that the backend connection was successfully made */
- if (PQstatus(imp_dbh->conn) != CONNECTION_OK) {
- pg_error(dbh, PQstatus(imp_dbh->conn), PQerrorMessage(imp_dbh->conn));
- PQfinish(imp_dbh->conn);
- return 0;
- }
-
- imp_dbh->init_commit = 1; /* initialize AutoCommit */
- imp_dbh->pg_auto_escape = 1; /* initialize pg_auto_escape */
- imp_dbh->pg_bool_tf = 0; /* initialize pg_bool_tf */
-
- DBIc_IMPSET_on(imp_dbh); /* imp_dbh set up now */
- DBIc_ACTIVE_on(imp_dbh); /* call disconnect before freeing */
- return 1;
-}
-
-
-int
-dbd_db_getfd (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- char id;
- SV* retsv;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_getfd\n"); }
-
- return PQsocket(imp_dbh->conn);
-}
-
-SV *
-dbd_db_pg_notifies (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- char id;
- PGnotify* notify;
- AV* ret;
- SV* retsv;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_pg_notifies\n"); }
-
- PQconsumeInput(imp_dbh->conn);
-
- notify = PQnotifies(imp_dbh->conn);
-
- if (!notify) return &sv_undef;
-
- ret=newAV();
-
- av_push(ret, newSVpv(notify->relname,0) );
- av_push(ret, newSViv(notify->be_pid) );
-
- /* Should free notify memory with PQfreemem() */
-
- retsv = newRV(sv_2mortal((SV*)ret));
-
- return retsv;
-}
-
-int
-dbd_db_ping (dbh)
- SV *dbh;
-{
- char id;
- D_imp_dbh(dbh);
- PGresult* result;
- ExecStatusType status;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_ping\n"); }
-
- if (NULL != imp_dbh->conn) {
- result = PQexec(imp_dbh->conn, " ");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
-
- if (PGRES_EMPTY_QUERY != status) {
- return 0;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-
-int
-dbd_db_commit (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_commit\n"); }
-
- /* no commit if AutoCommit = on */
- if (DBIc_has(imp_dbh, DBIcf_AutoCommit) != FALSE) {
- return 0;
- }
-
- if (NULL != imp_dbh->conn) {
- PGresult* result = 0;
- ExecStatusType commitstatus, beginstatus;
-
- /* execute commit */
- result = PQexec(imp_dbh->conn, "commit");
- commitstatus = result ? PQresultStatus(result) : -1;
- PQclear(result);
-
- /* check result */
- if (commitstatus != PGRES_COMMAND_OK) {
- /* Only put the error message in DBH->errstr */
- pg_error(dbh, commitstatus, PQerrorMessage(imp_dbh->conn));
- }
-
- /* start new transaction. AutoCommit must be FALSE, ref. 20 lines up */
- result = PQexec(imp_dbh->conn, "begin");
- beginstatus = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (beginstatus != PGRES_COMMAND_OK) {
- /* Maybe add some loud barf here? Raising some very high error? */
- pg_error(dbh, beginstatus, "begin failed\n");
- return 0;
- }
-
- /* if the initial COMMIT failed, return 0 now */
- if (commitstatus != PGRES_COMMAND_OK) {
- return 0;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-
-int
-dbd_db_rollback (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_rollback\n"); }
-
- /* no rollback if AutoCommit = on */
- if (DBIc_has(imp_dbh, DBIcf_AutoCommit) != FALSE) {
- return 0;
- }
-
- if (NULL != imp_dbh->conn) {
- PGresult* result = 0;
- ExecStatusType status;
-
- /* execute rollback */
- result = PQexec(imp_dbh->conn, "rollback");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
-
- /* check result */
- if (status != PGRES_COMMAND_OK) {
- pg_error(dbh, status, "rollback failed\n");
- return 0;
- }
-
- /* start new transaction. AutoCommit must be FALSE, ref. 20 lines up */
- result = PQexec(imp_dbh->conn, "begin");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(dbh, status, "begin failed\n");
- return 0;
- }
-
- return 1;
- }
-
- return 0;
-}
-
-
-int
-dbd_db_disconnect (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- dTHR;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_disconnect\n"); }
-
- /* We assume that disconnect will always work */
- /* since most errors imply already disconnected. */
- DBIc_ACTIVE_off(imp_dbh);
-
- if (NULL != imp_dbh->conn) {
- /* rollback if AutoCommit = off */
- if (DBIc_has(imp_dbh, DBIcf_AutoCommit) == FALSE) {
- PGresult* result = 0;
- ExecStatusType status;
- result = PQexec(imp_dbh->conn, "rollback");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(dbh, status, "rollback failed\n");
- return 0;
- }
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_disconnect: AutoCommit=off -> rollback\n"); }
- }
-
- PQfinish(imp_dbh->conn);
-
- imp_dbh->conn = NULL;
- }
-
- /* We don't free imp_dbh since a reference still exists */
- /* The DESTROY method is the only one to 'free' memory. */
- /* Note that statement objects may still exists for this dbh! */
- return 1;
-}
-
-
-void
-dbd_db_destroy (dbh, imp_dbh)
- SV *dbh;
- imp_dbh_t *imp_dbh;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_destroy\n"); }
-
- if (DBIc_ACTIVE(imp_dbh)) {
- dbd_db_disconnect(dbh, imp_dbh);
- }
-
- /* Nothing in imp_dbh to be freed */
- DBIc_IMPSET_off(imp_dbh);
-}
-
-
-int
-dbd_db_STORE_attrib (dbh, imp_dbh, keysv, valuesv)
- SV *dbh;
- imp_dbh_t *imp_dbh;
- SV *keysv;
- SV *valuesv;
-{
- STRLEN kl;
- char *key = SvPV(keysv,kl);
- int newval = SvTRUE(valuesv);
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_STORE\n"); }
-
- if (kl==10 && strEQ(key, "AutoCommit")) {
- int oldval = DBIc_has(imp_dbh, DBIcf_AutoCommit);
- DBIc_set(imp_dbh, DBIcf_AutoCommit, newval);
- if (oldval == FALSE && newval != FALSE && imp_dbh->init_commit) {
- /* do nothing, fall through */
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_STORE: initialize AutoCommit to on\n"); }
- } else if (oldval == FALSE && newval != FALSE) {
- if (NULL != imp_dbh->conn) {
- /* commit any outstanding changes */
- PGresult* result = 0;
- ExecStatusType status;
- result = PQexec(imp_dbh->conn, "commit");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(dbh, status, "commit failed\n");
- return 0;
- }
- }
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_STORE: switch AutoCommit to on: commit\n"); }
- } else if ((oldval != FALSE && newval == FALSE) || (oldval == FALSE && newval == FALSE && imp_dbh->init_commit)) {
- if (NULL != imp_dbh->conn) {
- /* start new transaction */
- PGresult* result = 0;
- ExecStatusType status;
- result = PQexec(imp_dbh->conn, "begin");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(dbh, status, "begin failed\n");
- return 0;
- }
- }
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_db_STORE: switch AutoCommit to off: begin\n"); }
- }
- /* only needed once */
- imp_dbh->init_commit = 0;
- return 1;
- } else if (kl==14 && strEQ(key, "pg_auto_escape")) {
- imp_dbh->pg_auto_escape = newval;
- } else if (kl==10 && strEQ(key, "pg_bool_tf")) {
- imp_dbh->pg_bool_tf = newval;
-#ifdef SvUTF8_off
- } else if (kl==14 && strEQ(key, "pg_enable_utf8")) {
- imp_dbh->pg_enable_utf8 = newval;
-#endif
- } else {
- return 0;
- }
-}
-
-
-SV *
-dbd_db_FETCH_attrib (dbh, imp_dbh, keysv)
- SV *dbh;
- imp_dbh_t *imp_dbh;
- SV *keysv;
-{
- STRLEN kl;
- char *key = SvPV(keysv,kl);
- SV *retsv = Nullsv;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_db_FETCH\n"); }
-
- if (kl==10 && strEQ(key, "AutoCommit")) {
- retsv = boolSV(DBIc_has(imp_dbh, DBIcf_AutoCommit));
- } else if (kl==14 && strEQ(key, "pg_auto_escape")) {
- retsv = newSViv((IV)imp_dbh->pg_auto_escape);
- } else if (kl==10 && strEQ(key, "pg_bool_tf")) {
- retsv = newSViv((IV)imp_dbh->pg_bool_tf);
-#ifdef SvUTF8_off
- } else if (kl==14 && strEQ(key, "pg_enable_utf8")) {
- retsv = newSViv((IV)imp_dbh->pg_enable_utf8);
-#endif
- } else if (kl==11 && strEQ(key, "pg_INV_READ")) {
- retsv = newSViv((IV)INV_READ);
- } else if (kl==12 && strEQ(key, "pg_INV_WRITE")) {
- retsv = newSViv((IV)INV_WRITE);
- }
-
- if (!retsv) {
- return Nullsv;
- }
- if (retsv == &sv_yes || retsv == &sv_no) {
- return retsv; /* no need to mortalize yes or no */
- }
- return sv_2mortal(retsv);
-}
-
-
-/* driver specific functins */
-
-
-int
-pg_db_lo_open (dbh, lobjId, mode)
- SV *dbh;
- unsigned int lobjId;
- int mode;
-{
- D_imp_dbh(dbh);
- return lo_open(imp_dbh->conn, lobjId, mode);
-}
-
-
-int
-pg_db_lo_close (dbh, fd)
- SV *dbh;
- int fd;
-{
- D_imp_dbh(dbh);
- return lo_close(imp_dbh->conn, fd);
-}
-
-
-int
-pg_db_lo_read (dbh, fd, buf, len)
- SV *dbh;
- int fd;
- char *buf;
- int len;
-{
- D_imp_dbh(dbh);
- return lo_read(imp_dbh->conn, fd, buf, len);
-}
-
-
-int
-pg_db_lo_write (dbh, fd, buf, len)
- SV *dbh;
- int fd;
- char *buf;
- int len;
-{
- D_imp_dbh(dbh);
- return lo_write(imp_dbh->conn, fd, buf, len);
-}
-
-
-int
-pg_db_lo_lseek (dbh, fd, offset, whence)
- SV *dbh;
- int fd;
- int offset;
- int whence;
-{
- D_imp_dbh(dbh);
- return lo_lseek(imp_dbh->conn, fd, offset, whence);
-}
-
-
-unsigned int
-pg_db_lo_creat (dbh, mode)
- SV *dbh;
- int mode;
-{
- D_imp_dbh(dbh);
- return lo_creat(imp_dbh->conn, mode);
-}
-
-
-int
-pg_db_lo_tell (dbh, fd)
- SV *dbh;
- int fd;
-{
- D_imp_dbh(dbh);
- return lo_tell(imp_dbh->conn, fd);
-}
-
-
-int
-pg_db_lo_unlink (dbh, lobjId)
- SV *dbh;
- unsigned int lobjId;
-{
- D_imp_dbh(dbh);
- return lo_unlink(imp_dbh->conn, lobjId);
-}
-
-
-unsigned int
-pg_db_lo_import (dbh, filename)
- SV *dbh;
- char *filename;
-{
- D_imp_dbh(dbh);
- return lo_import(imp_dbh->conn, filename);
-}
-
-
-int
-pg_db_lo_export (dbh, lobjId, filename)
- SV *dbh;
- unsigned int lobjId;
- char *filename;
-{
- D_imp_dbh(dbh);
- return lo_export(imp_dbh->conn, lobjId, filename);
-}
-
-
-int
-pg_db_putline (dbh, buffer)
- SV *dbh;
- char *buffer;
-{
- D_imp_dbh(dbh);
- return PQputline(imp_dbh->conn, buffer);
-}
-
-
-int
-pg_db_getline (dbh, buffer, length)
- SV *dbh;
- char *buffer;
- int length;
-{
- D_imp_dbh(dbh);
- return PQgetline(imp_dbh->conn, buffer, length);
-}
-
-
-int
-pg_db_endcopy (dbh)
- SV *dbh;
-{
- D_imp_dbh(dbh);
- return PQendcopy(imp_dbh->conn);
-}
-
-
-/* ================================================================== */
-
-
-int
-dbd_st_prepare (sth, imp_sth, statement, attribs)
- SV *sth;
- imp_sth_t *imp_sth;
- char *statement;
- SV *attribs;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_prepare: statement = >%s<\n", statement); }
-
- /* scan statement for '?', ':1' and/or ':foo' style placeholders */
- dbd_preparse(imp_sth, statement);
-
- /* initialize new statement handle */
- imp_sth->result = 0;
- imp_sth->cur_tuple = 0;
-
- DBIc_IMPSET_on(imp_sth);
- return 1;
-}
-
-
-static void
-dbd_preparse (imp_sth, statement)
- imp_sth_t *imp_sth;
- char *statement;
-{
- bool in_literal = FALSE;
- char in_comment = '\0';
- char *src, *start, *dest;
- phs_t phs_tpl;
- SV *phs_sv;
- int idx=0;
- char *style="", *laststyle=Nullch;
- STRLEN namelen;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_preparse: statement = >%s<\n", statement); }
-
- /* allocate room for copy of statement with spare capacity */
- /* for editing '?' or ':1' into ':p1'. */
- /* */
- /* Note: the calculated length used here for the safemalloc */
- /* isn't related in any way to the actual worst case length */
- /* of the translated statement, but allowing for 3 times */
- /* the length of the original statement should be safe... */
- imp_sth->statement = (char*)safemalloc(strlen(statement) * 3 + 1);
-
- /* initialise phs ready to be cloned per placeholder */
- memset(&phs_tpl, 0, sizeof(phs_tpl));
- phs_tpl.ftype = 1043; /* VARCHAR */
-
- src = statement;
- dest = imp_sth->statement;
- while(*src) {
-
- if (in_comment) {
- /* SQL-style and C++-style */
- if ((in_comment == '-' || in_comment == '/') && *src == '\n') {
- in_comment = '\0';
- }
- /* C-style */
- else if (in_comment == '*' && *src == '*' && *(src+1) == '/') {
- *dest++ = *src++; /* avoids asterisk-slash-asterisk issues */
- in_comment = '\0';
- }
- *dest++ = *src++;
- continue;
- }
-
- if (in_literal) {
- /* check if literal ends but keep quotes in literal */
- if (*src == in_literal) {
- int bs=0;
- char *str;
- str = src-1;
- while (*(str-bs) == '\\')
- bs++;
- if (!(bs & 1))
- in_literal = 0;
- }
- *dest++ = *src++;
- continue;
- }
-
- /* Look for comments: SQL-style or C++-style or C-style */
- if ((*src == '-' && *(src+1) == '-') ||
- (*src == '/' && *(src+1) == '/') ||
- (*src == '/' && *(src+1) == '*'))
- {
- in_comment = *(src+1);
- /* We know *src & the next char are to be copied, so do */
- /* it. In the case of C-style comments, it happens to */
- /* help us avoid slash-asterisk-slash oddities. */
- *dest++ = *src++;
- *dest++ = *src++;
- continue;
- }
-
- /* check if no placeholders */
- if (*src != ':' && *src != '?') {
- if (*src == '\'' || *src == '"') {
- in_literal = *src;
- }
- *dest++ = *src++;
- continue;
- }
-
- /* check for cast operator */
- if (*src == ':' && (*(src-1) == ':' || *(src+1) == ':')) {
- *dest++ = *src++;
- continue;
- }
-
- /* only here for : or ? outside of a comment or literal and no cast */
-
- start = dest; /* save name inc colon */
- *dest++ = *src++;
- if (*start == '?') { /* X/Open standard */
- sprintf(start,":p%d", ++idx); /* '?' -> ':p1' (etc) */
- dest = start+strlen(start);
- style = "?";
-
- } else if (isDIGIT(*src)) { /* ':1' */
- idx = atoi(src);
- *dest++ = 'p'; /* ':1'->':p1' */
- if (idx <= 0) {
- croak("Placeholder :%d invalid, placeholders must be >= 1", idx);
- }
- while(isDIGIT(*src)) {
- *dest++ = *src++;
- }
- style = ":1";
-
- } else if (isALNUM(*src)) { /* ':foo' */
- while(isALNUM(*src)) { /* includes '_' */
- *dest++ = *src++;
- }
- style = ":foo";
- } else { /* perhaps ':=' PL/SQL construct */
- continue;
- }
- *dest = '\0'; /* handy for debugging */
- namelen = (dest-start);
- if (laststyle && style != laststyle) {
- croak("Can't mix placeholder styles (%s/%s)",style,laststyle);
- }
- laststyle = style;
- if (imp_sth->all_params_hv == NULL) {
- imp_sth->all_params_hv = newHV();
- }
- phs_tpl.sv = &sv_undef;
- phs_sv = newSVpv((char*)&phs_tpl, sizeof(phs_tpl)+namelen+1);
- hv_store(imp_sth->all_params_hv, start, namelen, phs_sv, 0);
- strcpy( ((phs_t*)(void*)SvPVX(phs_sv))->name, start);
- }
- *dest = '\0';
- if (imp_sth->all_params_hv) {
- DBIc_NUM_PARAMS(imp_sth) = (int)HvKEYS(imp_sth->all_params_hv);
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, " dbd_preparse scanned %d distinct placeholders\n", (int)DBIc_NUM_PARAMS(imp_sth)); }
- }
-}
-
-
-/* if it LOOKS like a string, this function will determine whether the type needs to be surrounded in single quotes */
-static int pg_sql_needquote (sql_type)
- int sql_type;
-{
- if (sql_type > 1000 || sql_type == 17 || sql_type == 25 ) {
- return 1;
- }
- return 0;
-}
-
-
-
-static int
-pg_sql_type (imp_sth, name, sql_type)
- imp_sth_t *imp_sth;
- char *name;
- int sql_type;
-{
- switch (sql_type) {
- case SQL_CHAR:
- return 1042; /* bpchar */
- case SQL_NUMERIC:
- return 700; /* float4 */
- case SQL_DECIMAL:
- return 700; /* float4 */
- case SQL_INTEGER:
- return 23; /* int4 */
- case SQL_SMALLINT:
- return 21; /* int2 */
- case SQL_FLOAT:
- return 700; /* float4 */
- case SQL_REAL:
- return 701; /* float8 */
- case SQL_DOUBLE:
- return 20; /* int8 */
- case SQL_VARCHAR:
- return 1043; /* varchar */
- case SQL_BINARY:
- return 17; /* bytea */
- default:
- if (DBIc_WARN(imp_sth) && imp_sth && name) {
- warn("SQL type %d for '%s' is not fully supported, bound as VARCHAR instead",
- sql_type, name);
- }
- return pg_sql_type(imp_sth, name, SQL_VARCHAR);
- }
-}
-
-static int
-sql_pg_type (imp_sth, name, sql_type)
- imp_sth_t *imp_sth;
- char *name;
- int sql_type;
-{
- if (dbis->debug >= 1) {
- PerlIO_printf(DBILOGFP, "sql_pg_type name '%s' type '%d'\n", name, sql_type );
- }
-
- switch (sql_type) {
- case 17: /* bytea */
- return SQL_BINARY;
- case 20: /* int8 */
- return SQL_DOUBLE;
- case 21: /* int2 */
- return SQL_SMALLINT;
- case 23: /* int4 */
- return SQL_INTEGER;
- case 700: /* float4 */
- return SQL_NUMERIC;
- case 701: /* float8 */
- return SQL_REAL;
- case 1042: /* bpchar */
- return SQL_CHAR;
- case 1043: /* varchar */
- return SQL_VARCHAR;
- case 1082: /* date */
- return SQL_DATE;
- case 1083: /* time */
- return SQL_TIME;
- case 1296: /* date */
- return SQL_TIMESTAMP;
-
- default:
- return sql_type;
- }
-}
-
-
-static int
-dbd_rebind_ph (sth, imp_sth, phs)
- SV *sth;
- imp_sth_t *imp_sth;
- phs_t *phs;
-{
- STRLEN value_len;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_rebind\n"); }
-
- /* convert to a string ASAP */
- if (!SvPOK(phs->sv) && SvOK(phs->sv)) {
- sv_2pv(phs->sv, &na);
- }
-
- if (dbis->debug >= 2) {
- char *val = neatsvpv(phs->sv,0);
- PerlIO_printf(DBILOGFP, " bind %s <== %.1000s (", phs->name, val);
- if (SvOK(phs->sv)) {
- PerlIO_printf(DBILOGFP, "size %ld/%ld/%ld, ", (long)SvCUR(phs->sv),(long)SvLEN(phs->sv),phs->maxlen);
- } else {
- PerlIO_printf(DBILOGFP, "NULL, ");
- }
- PerlIO_printf(DBILOGFP, "ptype %d, otype %d%s)\n", (int)SvTYPE(phs->sv), phs->ftype, (phs->is_inout) ? ", inout" : "");
- }
-
- /* At the moment we always do sv_setsv() and rebind. */
- /* Later we may optimise this so that more often we can */
- /* just copy the value & length over and not rebind. */
-
- if (phs->is_inout) { /* XXX */
- if (SvREADONLY(phs->sv)) {
- croak(no_modify);
- }
- /* phs->sv _is_ the real live variable, it may 'mutate' later */
- /* pre-upgrade high to reduce risk of SvPVX realloc/move */
- (void)SvUPGRADE(phs->sv, SVt_PVNV);
- /* ensure room for result, 28 is magic number (see sv_2pv) */
- SvGROW(phs->sv, (phs->maxlen < 28) ? 28 : phs->maxlen+1);
- }
- else {
- /* phs->sv is copy of real variable, upgrade to at least string */
- (void)SvUPGRADE(phs->sv, SVt_PV);
- }
-
- /* At this point phs->sv must be at least a PV with a valid buffer, */
- /* even if it's undef (null) */
- /* Here we set phs->progv, phs->indp, and value_len. */
- if (SvOK(phs->sv)) {
- phs->progv = SvPV(phs->sv, value_len);
- phs->indp = 0;
- }
- else { /* it's null but point to buffer in case it's an out var */
- phs->progv = SvPVX(phs->sv);
- phs->indp = -1;
- value_len = 0;
- }
- 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 += SvOK(phs->sv) ? phs->alen : 4; /* NULL */
-
- 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;
-}
-
-
-void dereference(value)
-SV** value;
-{
- AV* buf;
- SV* val;
- char *src;
- int is_ref;
- STRLEN len;
-
- if (SvTYPE(SvRV(*value)) != SVt_PVAV)
- croak("Not an array reference (%s)", neatsvpv(*value,0));
-
- buf = (AV *) SvRV(*value);
- sv_setpv(*value, "{");
- while ( SvOK(val = av_shift(buf)) ) {
- is_ref = SvROK(val);
- if (is_ref)
- dereference(&val);
- else
- sv_catpv(*value, "\"");
- /* Quote */
- src = SvPV(val, len);
- while (len--) {
- if (!is_ref && *src == '\"')
- sv_catpv(*value, "\\");
- sv_catpvn(*value, src++, 1);
- }
- /* End of quote */
- if (!is_ref)
- sv_catpv(*value, "\"");
- if (av_len(buf) > -1)
- sv_catpv(*value, array_delimiter);
- }
- sv_catpv(*value, "}");
- av_clear(buf);
-}
-
-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 */
- dereference(&newvalue);
- }
- if (SvTYPE(newvalue) == SVt_PVLV && is_inout) { /* may allow later */
- croak("Can't bind ``lvalue'' mode scalar as inout parameter (currently)");
- }
-
- if (dbis->debug >= 2) {
- PerlIO_printf(DBILOGFP, " bind %s <== %s (type %ld", name, neatsvpv(newvalue,0), (long)sql_type);
- if (is_inout) {
- PerlIO_printf(DBILOGFP, ", inout 0x%lx, maxlen %ld", (long)newvalue, (long)maxlen);
- }
- 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 == &sv_undef) { /* first bind for this placeholder */
- phs->ftype = 1043; /* our default type VARCHAR */
- phs->is_inout = is_inout;
- if (is_inout) {
- /* phs->sv assigned in the code below */
- ++imp_sth->has_inout_params;
- /* build array of phs's so we can deal with out vars fast */
- if (!imp_sth->out_params_av) {
- imp_sth->out_params_av = newAV();
- }
- av_push(imp_sth->out_params_av, SvREFCNT_inc(*phs_svp));
- }
-
- 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) {
- /* SQL_BINARY (-2) is deprecated. */
- if (sql_type == -2 && DBIc_WARN(imp_sth)) {
- warn("Use of SQL type SQL_BINARY (%d) is deprecated. Use { pg_type => DBD::Pg::PG_BYTEA } instead.", sql_type);
- }
- phs->ftype = pg_sql_type(imp_sth, phs->name, sql_type);
- }
- } /* was first bind for this placeholder */
-
- /* check later rebinds for any changes */
- else if (is_inout || phs->is_inout) {
- croak("Can't rebind or change param %s in/out mode after first bind (%d => %d)", phs->name, phs->is_inout , is_inout);
- }
- 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 (!is_inout) { /* normal bind to take a (new) copy of current value */
- if (phs->sv == &sv_undef) { /* (first time bind) */
- phs->sv = newSV(0);
- }
- sv_setsv(phs->sv, newvalue);
- } else if (newvalue != phs->sv) {
- if (phs->sv) {
- SvREFCNT_dec(phs->sv);
- }
- phs->sv = SvREFCNT_inc(newvalue); /* point to live var */
- }
-
- return dbd_rebind_ph(sth, imp_sth, phs);
-}
-
-
-int
-dbd_st_execute (sth, imp_sth) /* <= -2:error, >=0:ok row count, (-1=unknown count) */
- SV *sth;
- imp_sth_t *imp_sth;
-{
- dTHR;
-
- D_imp_dbh_from_sth;
- ExecStatusType status = -1;
- char *cmdStatus;
- char *cmdTuples;
- char *statement;
- int ret = -2;
- int num_fields;
- int i;
- STRLEN len;
- bool in_literal = FALSE;
- char in_comment = '\0';
- char *src;
- char *dest;
- char *val;
- char namebuf[30];
- phs_t *phs;
- SV **svp;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_execute\n"); }
-
- /*
- here we get the statement from the statement handle where
- it has been stored when creating a blank sth during prepare
- svp = hv_fetch((HV *)SvRV(sth), "Statement", 9, FALSE);
- statement = SvPV(*svp, na);
- */
-
- if (NULL == imp_dbh->conn) {
- pg_error(sth, -1, "execute on disconnected handle");
- return -2;
- }
-
- statement = imp_sth->statement;
- if (! statement) {
- /* are we prepared ? */
- pg_error(sth, -1, "statement not prepared\n");
- return -2;
- }
-
- /* do we have input parameters ? */
- if ((int)DBIc_NUM_PARAMS(imp_sth) > 0) {
- /*
- we have to allocate some additional memory for possible escaping
- quotes and backslashes:
- max_len = length of statement
- + total length of all params allowing for worst case all
- characters binary-escaped (\\xxx)
- + null terminator
- Note: parameters look like :p1 at this point, so there's no
- need to explicitly allow for surrounding quotes because '' is
- shorter than :p1
- */
- int max_len = strlen(imp_sth->statement) + imp_sth->all_params_len * 5 + 1;
- statement = (char*)safemalloc( max_len );
- dest = statement;
- src = imp_sth->statement;
- /* scan statement for ':p1' style placeholders */
- while(*src) {
-
- if (in_comment) {
- /* SQL-style and C++-style */
- if ((in_comment == '-' || in_comment == '/') && *src == '\n') {
- in_comment = '\0';
- }
- /* C-style */
- else if (in_comment == '*' && *src == '*' && *(src+1) == '/') {
- *dest++ = *src++; /* avoids asterisk-slash-asterisk issues */
- in_comment = '\0';
- }
- *dest++ = *src++;
- continue;
- }
-
- if (in_literal) {
- /* check if literal ends but keep quotes in literal */
- if (*src == in_literal) {
- int bs=0;
- char *str;
- str = src-1;
- while (*(str-bs) == '\\')
- bs++;
- if (!(bs & 1))
- in_literal = 0;
- }
- *dest++ = *src++;
- continue;
- }
-
- /* Look for comments: SQL-style or C++-style or C-style */
- if ((*src == '-' && *(src+1) == '-') ||
- (*src == '/' && *(src+1) == '/') ||
- (*src == '/' && *(src+1) == '*'))
- {
- in_comment = *(src+1);
- /* We know *src & the next char are to be copied, so do */
- /* it. In the case of C-style comments, it happens to */
- /* help us avoid slash-asterisk-slash oddities. */
- *dest++ = *src++;
- *dest++ = *src++;
- continue;
- }
-
- /* check if no placeholders */
- if (*src != ':' && *src != '?') {
- if (*src == '\'' || *src == '"') {
- in_literal = *src;
- }
- *dest++ = *src++;
- continue;
- }
-
- /* check for cast operator */
- if (*src == ':' && (*(src-1) == ':' || *(src+1) == ':')) {
- *dest++ = *src++;
- continue;
- }
-
-
- i = 0;
- namebuf[i++] = *src++; /* ':' */
- namebuf[i++] = *src++; /* 'p' */
-
- while (isDIGIT(*src) && i < (sizeof(namebuf)-1) ) {
- namebuf[i++] = *src++;
- }
- if ( i == (sizeof(namebuf) - 1)) {
- pg_error(sth, -1, "namebuf buffer overrun\n");
- return -2;
- }
- namebuf[i] = '\0';
- svp = hv_fetch(imp_sth->all_params_hv, namebuf, i, 0);
- if (svp == NULL) {
- pg_error(sth, -1, "parameter unknown\n");
- return -2;
- }
- /* get attribute */
- phs = (phs_t*)(void*)SvPVX(*svp);
- /* replace undef with NULL */
- if(!SvOK(phs->sv)) {
- val = "NULL";
- len = 4;
- } else {
- val = SvPV(phs->sv, len);
- }
- /* quote string attribute */
- if(!SvNIOK(phs->sv) && SvOK(phs->sv) && pg_sql_needquote(phs->ftype)) { /* avoid quoting NULL, tpf: bind_param as numeric */
- *dest++ = '\'';
- }
- while (len--) {
- if (imp_dbh->pg_auto_escape) {
- /* if the parameter was bound as PG_BYTEA, escape nonprintables */
- if (phs->ftype == 17 && !isPRINT(*val)) { /* escape null character */
- dest+=snprintf(dest, (statement + max_len) - dest, "\\\\%03o", *((unsigned char *)val));
- if (dest > statement + max_len) {
- pg_error(sth, -1, "statement buffer overrun\n");
- return -2;
- }
- val++;
- continue; /* do not copy the null */
- }
- /* escape quote */
- if (*val == '\'') {
- *dest++ = '\'';
- }
- /* escape backslash */
- if (*val == '\\') {
- if (phs->ftype == 17) { /* four backslashes. really. */
- *dest++ = '\\';
- *dest++ = '\\';
- *dest++ = '\\';
- } else {
- *dest++ = '\\';
- }
- }
- }
- /* copy attribute to statement */
- *dest++ = *val++;
- }
- /* quote string attribute */
- if(!SvNIOK(phs->sv) && SvOK(phs->sv) && pg_sql_needquote(phs->ftype)) { /* avoid quoting NULL, tpf: bind_param as numeric */
- *dest++ = '\'';
- }
- }
- *dest = '\0';
- }
-
- if (dbis->debug >= 2) { PerlIO_printf(DBILOGFP, "dbd_st_execute: statement = >%s<\n", statement); }
-
- /* clear old result (if any) */
- if (imp_sth->result) {
- PQclear(imp_sth->result);
- }
-
- /* execute statement */
- imp_sth->result = PQexec(imp_dbh->conn, statement);
-
- /* free statement string in case of input parameters */
- if ((int)DBIc_NUM_PARAMS(imp_sth) > 0) {
- Safefree(statement);
- }
-
- /* check status */
- status = imp_sth->result ? PQresultStatus(imp_sth->result) : -1;
- cmdStatus = imp_sth->result ? (char *)PQcmdStatus(imp_sth->result) : "";
- cmdTuples = imp_sth->result ? (char *)PQcmdTuples(imp_sth->result) : "";
-
- if (PGRES_TUPLES_OK == status) {
- /* select statement */
- num_fields = PQnfields(imp_sth->result);
- imp_sth->cur_tuple = 0;
- DBIc_NUM_FIELDS(imp_sth) = num_fields;
- DBIc_ACTIVE_on(imp_sth);
- ret = PQntuples(imp_sth->result);
- } else if (PGRES_COMMAND_OK == status) {
- /* non-select statement */
- if (! strncmp(cmdStatus, "DELETE", 6) || ! strncmp(cmdStatus, "INSERT", 6) || ! strncmp(cmdStatus, "UPDATE", 6)) {
- ret = atoi(cmdTuples);
- } else {
- ret = -1;
- }
- } else if (PGRES_COPY_OUT == status || PGRES_COPY_IN == status) {
- /* Copy Out/In data transfer in progress */
- ret = -1;
- } else {
- pg_error(sth, status, PQerrorMessage(imp_dbh->conn));
- ret = -2;
- }
-
- /* store the number of affected rows */
- imp_sth->rows = ret;
-
- return ret;
-}
-
-
-int
-is_high_bit_set(val)
- char *val;
-{
- while (*val++)
- if (*val & 0x80) return 1;
- return 0;
-}
-
-AV *
-dbd_st_fetch (sth, imp_sth)
- SV *sth;
- imp_sth_t *imp_sth;
-{
- D_imp_dbh_from_sth;
- int num_fields;
- int i;
- AV *av;
-
- 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 == PQntuples(imp_sth->result) ) {
- imp_sth->cur_tuple = 0;
- DBIc_ACTIVE_off(imp_sth);
- return Nullav; /* we reached the last tuple */
- }
-
- av = DBIS->get_fbav(imp_sth);
- num_fields = AvFILL(av)+1;
-
- for(i = 0; i < num_fields; ++i) {
-
- SV *sv = AvARRAY(av)[i];
- if (PQgetisnull(imp_sth->result, imp_sth->cur_tuple, i)) {
- sv_setsv(sv, &sv_undef);
- } else {
- char *val = (char*)PQgetvalue(imp_sth->result, imp_sth->cur_tuple, i);
- int val_len = strlen(val);
- int type = PQftype(imp_sth->result, i); /* hopefully these hard coded values will not change */
- if (16 == type && ! imp_dbh->pg_bool_tf) {
- *val = (*val == 'f') ? '0' : '1'; /* bool: translate postgres into perl */
- }
- if (17 == type) { /* decode \001 -> chr(1), etc, in-place */
- char *p = val; /* points to next available pos */
- char *s = val; /* points to current scanning pos */
- int c1,c2,c3;
- while (*s) {
- if (*s == '\\') {
- if (*(s+1) == '\\') { /* double backslash */
- *p++ = '\\';
- s += 2;
- continue;
- }
- else if ( isdigit(c1=(*(s+1))) &&
- isdigit(c2=(*(s+2))) &&
- isdigit(c3=(*(s+3))) ) {
- *p++ = (c1 - '0') * 64 + (c2 - '0') * 8 + (c3 - '0');
- s += 4;
- continue;
- }
- }
- *p++ = *s++;
- }
- val_len = (p - val);
- }
- else if (1042 == type && DBIc_has(imp_sth,DBIcf_ChopBlanks)) {
- char *str = val;
- while((val_len > 0) && (str[val_len-1] == ' ')) {
- val_len--;
- }
- val[val_len] = '\0';
- }
- sv_setpvn(sv, val, val_len);
-#ifdef SvUTF8_off
- if (imp_dbh->pg_enable_utf8) {
- SvUTF8_off(sv);
- /* XXX Is this all the character data types? */
- if (18 == type || 25 == type || 1042 ==type || 1043 == type) {
- if (is_high_bit_set(val) && is_utf8_string(val, val_len))
- SvUTF8_on(sv);
- }
- }
-#endif
- }
- }
-
- imp_sth->cur_tuple += 1;
-
- return av;
-}
-
-
-int
-dbd_st_blob_read (sth, imp_sth, lobjId, offset, len, destrv, destoffset)
- SV *sth;
- imp_sth_t *imp_sth;
- int lobjId;
- long offset;
- long len;
- SV *destrv;
- long destoffset;
-{
- D_imp_dbh_from_sth;
- int ret, lobj_fd, nbytes, nread;
- PGresult* result;
- ExecStatusType status;
- SV *bufsv;
- char *tmp;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_blob_read\n"); }
- /* safety check */
- if (lobjId <= 0) {
- pg_error(sth, -1, "dbd_st_blob_read: lobjId <= 0");
- return 0;
- }
- if (offset < 0) {
- pg_error(sth, -1, "dbd_st_blob_read: offset < 0");
- return 0;
- }
- if (len < 0) {
- pg_error(sth, -1, "dbd_st_blob_read: len < 0");
- return 0;
- }
- if (! SvROK(destrv)) {
- pg_error(sth, -1, "dbd_st_blob_read: destrv not a reference");
- return 0;
- }
- if (destoffset < 0) {
- pg_error(sth, -1, "dbd_st_blob_read: destoffset < 0");
- return 0;
- }
-
- /* dereference destination and ensure it's writable string */
- bufsv = SvRV(destrv);
- if (! destoffset) {
- sv_setpvn(bufsv, "", 0);
- }
-
- /* execute begin
- result = PQexec(imp_dbh->conn, "begin");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(sth, status, PQerrorMessage(imp_dbh->conn));
- return 0;
- }
- */
-
- /* open large object */
- lobj_fd = lo_open(imp_dbh->conn, lobjId, INV_READ);
- if (lobj_fd < 0) {
- pg_error(sth, -1, PQerrorMessage(imp_dbh->conn));
- return 0;
- }
-
- /* seek on large object */
- if (offset > 0) {
- ret = lo_lseek(imp_dbh->conn, lobj_fd, offset, SEEK_SET);
- if (ret < 0) {
- pg_error(sth, -1, PQerrorMessage(imp_dbh->conn));
- return 0;
- }
- }
-
- /* read from large object */
- nread = 0;
- SvGROW(bufsv, destoffset + nread + BUFSIZ + 1);
- tmp = (SvPVX(bufsv)) + destoffset + nread;
- while ((nbytes = lo_read(imp_dbh->conn, lobj_fd, tmp, BUFSIZ)) > 0) {
- nread += nbytes;
- /* break if user wants only a specified chunk */
- if (len > 0 && nread > len) {
- nread = len;
- break;
- }
- SvGROW(bufsv, destoffset + nread + BUFSIZ + 1);
- tmp = (SvPVX(bufsv)) + destoffset + nread;
- }
-
- /* terminate string */
- SvCUR_set(bufsv, destoffset + nread);
- *SvEND(bufsv) = '\0';
-
- /* close large object */
- ret = lo_close(imp_dbh->conn, lobj_fd);
- if (ret < 0) {
- pg_error(sth, -1, PQerrorMessage(imp_dbh->conn));
- return 0;
- }
-
- /* execute end
- result = PQexec(imp_dbh->conn, "end");
- status = result ? PQresultStatus(result) : -1;
- PQclear(result);
- if (status != PGRES_COMMAND_OK) {
- pg_error(sth, status, PQerrorMessage(imp_dbh->conn));
- return 0;
- }
- */
-
- return nread;
-}
-
-
-int
-dbd_st_rows (sth, imp_sth)
- SV *sth;
- imp_sth_t *imp_sth;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_rows\n"); }
-
- return imp_sth->rows;
-}
-
-
-int
-dbd_st_finish (sth, imp_sth)
- SV *sth;
- imp_sth_t *imp_sth;
-{
- dTHR;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_finish\n"); }
-
- if (DBIc_ACTIVE(imp_sth) && imp_sth->result) {
- PQclear(imp_sth->result);
- imp_sth->result = 0;
- imp_sth->rows = 0;
- }
-
- DBIc_ACTIVE_off(imp_sth);
- return 1;
-}
-
-
-void
-dbd_st_destroy (sth, imp_sth)
- SV *sth;
- imp_sth_t *imp_sth;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_destroy\n"); }
-
- /* Free off contents of imp_sth */
-
- Safefree(imp_sth->statement);
- if (imp_sth->result) {
- PQclear(imp_sth->result);
- imp_sth->result = 0;
- }
-
- 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);
- }
-
- DBIc_IMPSET_off(imp_sth); /* let DBI know we've done it */
-}
-
-
-int
-dbd_st_STORE_attrib (sth, imp_sth, keysv, valuesv)
- SV *sth;
- imp_sth_t *imp_sth;
- SV *keysv;
- SV *valuesv;
-{
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_STORE\n"); }
-
- return FALSE;
-}
-
-
-SV *
-dbd_st_FETCH_attrib (sth, imp_sth, keysv)
- SV *sth;
- imp_sth_t *imp_sth;
- SV *keysv;
-{
- STRLEN kl;
- char *key = SvPV(keysv,kl);
- int i, sz;
- SV *retsv = Nullsv;
-
- if (dbis->debug >= 1) { PerlIO_printf(DBILOGFP, "dbd_st_FETCH\n"); }
-
- if (! imp_sth->result) {
- return Nullsv;
- }
-
- i = DBIc_NUM_FIELDS(imp_sth);
-
- if (kl == 4 && strEQ(key, "NAME")) {
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- av_store(av, i, newSVpv(PQfname(imp_sth->result, i),0));
- }
- } else if ( kl== 4 && strEQ(key, "TYPE")) {
- /* Need to convert the Pg type to ANSI/SQL type. */
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- av_store(av, i, newSViv(sql_pg_type( imp_sth,
- PQfname(imp_sth->result, i),
- PQftype(imp_sth->result, i))));
- }
- } else if (kl==9 && strEQ(key, "PRECISION")) {
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- sz = PQfsize(imp_sth->result, i);
- av_store(av, i, sz > 0 ? newSViv(sz) : &sv_undef);
- }
- } else if (kl==5 && strEQ(key, "SCALE")) {
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- av_store(av, i, &sv_undef);
- }
- } else if (kl==8 && strEQ(key, "NULLABLE")) {
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- av_store(av, i, newSViv(2));
- }
- } else if (kl==10 && strEQ(key, "CursorName")) {
- retsv = &sv_undef;
- } else if (kl==11 && strEQ(key, "RowsInCache")) {
- retsv = &sv_undef;
- } else if (kl==7 && strEQ(key, "pg_size")) {
- AV *av = newAV();
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- av_store(av, i, newSViv(PQfsize(imp_sth->result, i)));
- }
- } else if (kl==7 && strEQ(key, "pg_type")) {
- AV *av = newAV();
- char *type_nam;
- retsv = newRV(sv_2mortal((SV*)av));
- while(--i >= 0) {
- switch (PQftype(imp_sth->result, i)) {
- case 16:
- type_nam = "bool";
- break;
- case 17:
- type_nam = "bytea";
- break;
- case 18:
- type_nam = "char";
- break;
- case 19:
- type_nam = "name";
- break;
- case 20:
- type_nam = "int8";
- break;
- case 21:
- type_nam = "int2";
- break;
- case 22:
- type_nam = "int28";
- break;
- case 23:
- type_nam = "int4";
- break;
- case 24:
- type_nam = "regproc";
- break;
- case 25:
- type_nam = "text";
- break;
- case 26:
- type_nam = "oid";
- break;
- case 27:
- type_nam = "tid";
- break;
- case 28:
- type_nam = "xid";
- break;
- case 29:
- type_nam = "cid";
- break;
- case 30:
- type_nam = "oid8";
- break;
- case 32:
- type_nam = "SET";
- break;
- case 210:
- type_nam = "smgr";
- break;
- case 600:
- type_nam = "point";
- break;
- case 601:
- type_nam = "lseg";
- break;
- case 602:
- type_nam = "path";
- break;
- case 603:
- type_nam = "box";
- break;
- case 604:
- type_nam = "polygon";
- break;
- case 605:
- type_nam = "filename";
- break;
- case 628:
- type_nam = "line";
- break;
- case 629:
- type_nam = "_line";
- break;
- case 700:
- type_nam = "float4";
- break;
- case 701:
- type_nam = "float8";
- break;
- case 702:
- type_nam = "abstime";
- break;
- case 703:
- type_nam = "reltime";
- break;
- case 704:
- type_nam = "tinterval";
- break;
- case 705:
- type_nam = "unknown";
- break;
- case 718:
- type_nam = "circle";
- break;
- case 719:
- type_nam = "_circle";
- break;
- case 790:
- type_nam = "money";
- break;
- case 791:
- type_nam = "_money";
- break;
- case 810:
- type_nam = "oidint2";
- break;
- case 910:
- type_nam = "oidint4";
- break;
- case 911:
- type_nam = "oidname";
- break;
- case 1000:
- type_nam = "_bool";
- break;
- case 1001:
- type_nam = "_bytea";
- break;
- case 1002:
- type_nam = "_char";
- break;
- case 1003:
- type_nam = "_name";
- break;
- case 1005:
- type_nam = "_int2";
- break;
- case 1006:
- type_nam = "_int28";
- break;
- case 1007:
- type_nam = "_int4";
- break;
- case 1008:
- type_nam = "_regproc";
- break;
- case 1009:
- type_nam = "_text";
- break;
- case 1028:
- type_nam = "_oid";
- break;
- case 1010:
- type_nam = "_tid";
- break;
- case 1011:
- type_nam = "_xid";
- break;
- case 1012:
- type_nam = "_cid";
- break;
- case 1013:
- type_nam = "_oid8";
- break;
- case 1014:
- type_nam = "_lock";
- break;
- case 1015:
- type_nam = "_stub";
- break;
- case 1016:
- type_nam = "_ref";
- break;
- case 1017:
- type_nam = "_point";
- break;
- case 1018:
- type_nam = "_lseg";
- break;
- case 1019:
- type_nam = "_path";
- break;
- case 1020:
- type_nam = "_box";
- break;
- case 1021:
- type_nam = "_float4";
- break;
- case 1022:
- type_nam = "_float8";
- break;
- case 1023:
- type_nam = "_abstime";
- break;
- case 1024:
- type_nam = "_reltime";
- break;
- case 1025:
- type_nam = "_tinterval";
- break;
- case 1026:
- type_nam = "_filename";
- break;
- case 1027:
- type_nam = "_polygon";
- break;
- case 1033:
- type_nam = "aclitem";
- break;
- case 1034:
- type_nam = "_aclitem";
- break;
- case 1042:
- type_nam = "bpchar";
- break;
- case 1043:
- type_nam = "varchar";
- break;
- case 1082:
- type_nam = "date";
- break;
- case 1083:
- type_nam = "time";
- break;
- case 1182:
- type_nam = "_date";
- break;
- case 1183:
- type_nam = "_time";
- break;
- case 1184:
- type_nam = "datetime";
- break;
- case 1185:
- type_nam = "_datetime";
- break;
- case 1186:
- type_nam = "timespan";
- break;
- case 1187:
- type_nam = "_timespan";
- break;
- case 1231:
- type_nam = "_numeric";
- break;
- case 1296:
- type_nam = "timestamp";
- break;
- case 1700:
- type_nam = "numeric";
- break;
-
- default:
- type_nam = "unknown";
-
- }
- av_store(av, i, newSVpv(type_nam, 0));
- }
- } else if (kl==13 && strEQ(key, "pg_oid_status")) {
- retsv = newSVpv((char *)PQoidStatus(imp_sth->result), 0);
- } else if (kl==13 && strEQ(key, "pg_cmd_status")) {
- retsv = newSVpv((char *)PQcmdStatus(imp_sth->result), 0);
- } else {
- return Nullsv;
- }
-
- return sv_2mortal(retsv);
-}
-
-
-/* end of dbdimp.c */