--- parser3/src/sql/pgsql/Attic/parser3pgsql.C 2001/07/31 07:58:47 1.3 +++ parser3/src/sql/pgsql/Attic/parser3pgsql.C 2001/07/31 14:22:00 1.6 @@ -7,13 +7,20 @@ 2001.07.30 using PgSQL 7.1.2 */ -static const char *RCSId="$Id: parser3pgsql.C,v 1.3 2001/07/31 07:58:47 parser Exp $"; +static const char *RCSId="$Id: parser3pgsql.C,v 1.6 2001/07/31 14:22:00 parser Exp $"; #include "config_includes.h" #include "pa_sql_driver.h" #include +#include + +// #include +#define OIDOID 26 +#define LO_BUFSIZE 8192 + + #include "ltdl.h" #define MAX_STRING 0x400 @@ -24,6 +31,11 @@ static const char *RCSId="$Id: parser3pg # define strcasecmp _stricmp #endif +#ifndef max +inline int max(int a,int b) { return a>b?a:b; } +inline int min(int a,int b){ return a=0) { + // seek to end + if(lo_lseek(conn, fd, 0, SEEK_END)<0) + PQclear_throwPQerror; + // get size + int size_tell=lo_tell(conn, fd); + if(size_tell<0) + PQclear_throwPQerror; + // seek to begin + if(lo_lseek(conn, fd, 0, SEEK_SET)<0) + PQclear_throwPQerror; + size=(size_t)size_tell; + if(size) { + // read + ptr=services.malloc(size); + char *buf=(char *)ptr; + int countdown=size_tell; + int size_read; + while(countdown && (size_read=lo_read(conn, fd, buf, min(LO_BUFSIZE, countdown)))>0) { + buf+=size_read; + countdown-=size_read; + } + if(countdown) + PQclear_throw("lo_read can not read all bytes of object"); + } else + ptr=0; + if(lo_close(conn, fd)<0) + PQclear_throwPQerror; + } else + PQclear_throwPQerror; + } else { + // normal column, read it as ASCII string + size=(size_t)PQgetlength(res, r, i); + if(size) { + ptr=services.malloc(size); + memcpy(ptr, cell, size); + } else + ptr=0; + } handlers.add_row_cell(ptr, size); } } @@ -191,7 +249,84 @@ public: PQclear(res); } -private: // pgsql client library funcs +private: // private funcs + + void begin_transaction(SQL_Driver_services& services, PGconn *conn) { + if(PGresult *res=PQexec(conn, "BEGIN")) + PQclear(res); + else + services._throw(PQerrorMessage(conn)); + } + + const char *preprocess_statement(SQL_Driver_services& services, PGconn *conn, + const char *astatement, unsigned long offset, unsigned long limit) { + size_t statement_size=strlen(astatement); + //_asm int 3; + + char *result=(char *)services.malloc(statement_size + +MAX_NUMBER*2+15 // limit # offset # + +MAX_STRING // in case of short 'strings' + +1); + // offset & limit -> suffixes + const char *o; + if(offset || limit) { + char *cur=result; + memcpy(cur, astatement, statement_size); cur+=statement_size; + if(limit) + cur+=snprintf(cur, 7+MAX_NUMBER, " limit %u", limit); + if(offset) + cur+=snprintf(cur, 8+MAX_NUMBER, " offset %u", offset); + o=result; + } else + o=astatement; + + // /*:zzzz*/'literal' -> oid + char *n=result; + while(*o) { + if( + o[0]=='/' && + o[1]=='*' && + o[2]==':') { // name start + o+=3; + while(*o) + if( + o[0]=='*' && + o[1]=='/' && + o[2]=='\'') { // name end + o+=3; + Oid oid=lo_creat(conn, INV_READ|INV_WRITE); + int fd=lo_open(conn, oid, INV_WRITE); + const char *start=o; + bool escaped=false; + while(*o && !(o[0]=='\'' && o[1]!='\'' && !escaped)) { + escaped=*o=='\\' || (o[0]=='\'' && o[1]=='\''); + if(escaped) { + // write pending, skip "\" or "'" + if(o!=start) + lo_write(conn, fd, start, o-start); + start=++o; + } else + o++; + } + if(o!=start) + lo_write(conn, fd, start, o-start); + lo_close(conn, fd); + if(*o) + o++; // skip "'" + + n+=snprintf(n, MAX_NUMBER, "%u", oid); + break; + } else + o++; // /*:skip*/ + } else + *n++=*o++; + } + *n=0; + + return result; + } + +private: // conn client library funcs typedef PGconn* (*t_PQsetdbLogin)( const char *pghost, @@ -219,8 +354,20 @@ private: // pgsql client library funcs typedef int (*t_PQnfields)(const PGresult *res); t_PQnfields PQnfields; typedef void (*t_PQclear)(PGresult *res); t_PQclear PQclear; + typedef Oid (*t_PQftype)(const PGresult *res, int field_num); t_PQftype PQftype; + + typedef int (*t_lo_open)(PGconn *conn, Oid lobjId, int mode); t_lo_open lo_open; + typedef int (*t_lo_close)(PGconn *conn, int fd); t_lo_close lo_close; + typedef int (*t_lo_read)(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len); t_lo_read lo_read; + typedef int (*t_lo_write)(PGconn *conn, int fd, const/*paf*/ char *buf, size_t len); t_lo_write lo_write; + typedef int (*t_lo_lseek)(PGconn *conn, int fd, int offset, int whence); t_lo_lseek lo_lseek; + typedef Oid (*t_lo_creat)(PGconn *conn, int mode); t_lo_creat lo_creat; + typedef int (*t_lo_tell)(PGconn *conn, int fd); t_lo_tell lo_tell; + typedef int (*t_lo_unlink)(PGconn *conn, Oid lobjId); t_lo_unlink lo_unlink; + typedef Oid (*t_lo_import)(PGconn *conn, const char *filename); t_lo_import lo_import; + typedef int (*t_lo_export)(PGconn *conn, Oid lobjId, const char *filename); t_lo_export lo_export; -private: // pgsql client library funcs linking +private: // conn client library funcs linking const char *dlink(const char *dlopen_file_spec) { lt_dlhandle handle=lt_dlopen(dlopen_file_spec); @@ -246,6 +393,12 @@ private: // pgsql client library funcs l DLINK(PQclear); DLINK(PQresultStatus); DLINK(PQexec); + DLINK(PQftype); + DLINK(lo_open); DLINK(lo_close); + DLINK(lo_read); DLINK(lo_write); + DLINK(lo_lseek); DLINK(lo_creat); + DLINK(lo_tell); DLINK(lo_unlink); + DLINK(lo_import); DLINK(lo_export); return 0; }