@ -1,6 +1,6 @@
/*-------------------------------------------------------
*
* $Id: Pg.xs,v 1.8 1998/09/03 02:10:56 momjian Exp $
* $Id: Pg.xs,v 1.9 1998/09/27 19:12:23 mergl Exp $
*
* Copyright (c) 1997, 1998 Edmund Mergl
*
@ -10,8 +10,11 @@
#include "perl.h"
#include "XSUB.h"
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include "libpq-fe.h"
#include "libpq-int.h" /* need this for sizeof(PGresult) */
typedef struct pg_conn *PG_conn;
typedef struct pg_result *PG_result;
@ -28,8 +31,7 @@ typedef struct pg_results *PG_results;
static double
constant(name, arg)
char *name;
int arg;
{
int arg; {
errno = 0;
switch (*name) {
case 'A':
@ -178,10 +180,6 @@ not_there:
MODULE = Pg PACKAGE = Pg
PROTOTYPES: DISABLE
@ -200,11 +198,11 @@ PQconnectdb(conninfo)
/* convert dbname to lower case if not surrounded by double quotes */
char *ptr = strstr(conninfo, "dbname");
if (ptr) {
ptr += 6;
while (*ptr && *ptr++ != '=') {
;
while (*ptr && *ptr != '=') {
ptr++;
}
while (*ptr && (*ptr == ' ' || *ptr == '\t')) {
ptr++;
while (*ptr == ' ' || *ptr == '\t') {
ptr++;
}
if (*ptr == '"') {
@ -226,6 +224,26 @@ PQconnectdb(conninfo)
RETVAL
PGconn *
PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbname, login, pwd)
char * pghost
char * pgport
char * pgoptions
char * pgtty
char * dbname
char * login
char * pwd
PGconn *
PQsetdb(pghost, pgport, pgoptions, pgtty, dbname)
char * pghost
char * pgport
char * pgoptions
char * pgtty
char * dbname
HV *
PQconndefaults()
CODE:
@ -233,7 +251,11 @@ PQconndefaults()
RETVAL = newHV();
if (infoOption = PQconndefaults()) {
while (infoOption->keyword != NULL) {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv(infoOption->val, 0), 0);
if (infoOption->val != NULL) {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv(infoOption->val, 0), 0);
} else {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv("", 0), 0);
}
infoOption++;
}
}
@ -241,15 +263,6 @@ PQconndefaults()
RETVAL
PGconn *
PQsetdb(pghost, pgport, pgoptions, pgtty, dbname)
char * pghost
char * pgport
char * pgoptions
char * pgtty
char * dbname
void
PQfinish(conn)
PGconn * conn
@ -260,6 +273,10 @@ PQreset(conn)
PGconn * conn
int
PQrequestCancel(conn)
PGconn * conn
char *
PQdb(conn)
PGconn * conn
@ -271,12 +288,12 @@ PQuser(conn)
char *
PQhost (conn)
PQpass (conn)
PGconn * conn
char *
PQoptions (conn)
PQhost (conn)
PGconn * conn
@ -290,6 +307,11 @@ PQtty(conn)
PGconn * conn
char *
PQoptions(conn)
PGconn * conn
ConnStatusType
PQstatus(conn)
PGconn * conn
@ -300,6 +322,16 @@ PQerrorMessage(conn)
PGconn * conn
int
PQsocket(conn)
PGconn * conn
int
PQbackendPID(conn)
PGconn * conn
void
PQtrace(conn, debug_port)
PGconn * conn
@ -318,19 +350,63 @@ PQexec(conn, query)
char * query
CODE:
RETVAL = PQexec(conn, query);
if (! RETVAL) { RETVAL = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR); }
if (! RETVAL) {
RETVAL = (PGresult *)calloc(1, sizeof(PGresult));
}
OUTPUT:
RETVAL
void
PQnotifies(conn)
PGconn * conn
PREINIT:
PGnotify *notify;
PPCODE:
notify = PQnotifies(conn);
if (notify) {
XPUSHs(sv_2mortal(newSVpv((char *)notify->relname, 0)));
XPUSHs(sv_2mortal(newSViv(notify->be_pid)));
free(notify);
}
int
PQsendQuery(conn, query)
PGconn * conn
char * query
PGresult *
PQgetResult(conn)
PGconn * conn
CODE:
RETVAL = PQgetResult(conn);
if (! RETVAL) {
RETVAL = (PGresult *)calloc(1, sizeof(PGresult));
}
OUTPUT:
RETVAL
int
PQisBusy(conn)
PGconn * conn
int
PQconsumeInput(conn)
PGconn * conn
int
PQgetline(conn, string, length)
PREINIT:
SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
INPUT:
PGconn * conn
int length
char * string = sv_grow(sv_buffer, length);
char * string = sv_grow(bufsv , length);
CODE:
RETVAL = PQgetline(conn, string, length);
OUTPUT:
@ -339,28 +415,42 @@ PQgetline(conn, string, length)
int
PQendcopy(conn )
PQputline(conn, string )
PGconn * conn
char * string
void
PQputline(conn, string)
int
PQgetlineAsync(conn, buffer, bufsize)
PREINIT:
SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
INPUT:
PGconn * conn
int bufsize
char * buffer = sv_grow(bufsv, bufsize);
CODE:
RETVAL = PQgetlineAsync(conn, buffer, bufsize);
OUTPUT:
RETVAL
buffer
int
PQputnbytes(conn, buffer, nbytes)
PGconn * conn
char * string
char * buffer
int nbytes
void
PQnotifies(conn)
int
PQendcopy (conn)
PGconn * conn
PREINIT:
PGnotify *notify;
PPCODE:
notify = PQnotifies(conn);
if (notify) {
XPUSHs(sv_2mortal(newSVpv((char *)notify->relname, 0)));
XPUSHs(sv_2mortal(newSViv(notify->be_pid)));
free(notify);
}
PGresult *
PQmakeEmptyPGresult(conn, status)
PGconn * conn
ExecStatusType status
ExecStatusType
@ -378,6 +468,11 @@ PQnfields(res)
PGresult * res
int
PQbinaryTuples(res)
PGresult * res
char *
PQfname(res, field_num)
PGresult * res
@ -402,6 +497,12 @@ PQfsize(res, field_num)
int field_num
int
PQfmod(res, field_num)
PGresult * res
int field_num
char *
PQcmdStatus(res)
PGresult * res
@ -451,37 +552,16 @@ PQclear(res)
PGresult * res
void
PQdisplayTuples(res, fp, fillAlign, fieldSep, printHeader, quiet)
PGresult * res
FILE * fp
int fillAlign
char * fieldSep
int printHeader
int quiet
CODE:
PQdisplayTuples(res, fp, fillAlign, (const char *)fieldSep, printHeader, quiet);
void
PQprintTuples(res, fout, printAttName, terseOutput, width)
PGresult * res
FILE * fout
int printAttName
int terseOutput
int width
void
PQprint(fout, res, header, align, standard, html3, expanded, pager, fieldSep, tableOpt, caption, ...)
FILE * fout
PGresult * res
bool header
bool align
bool standard
bool html3
bool expanded
bool pager
pqbool header
pqbool align
pqbool standard
pqbool html3
pqbool expanded
pqbool pager
char * fieldSep
char * tableOpt
char * caption
@ -506,6 +586,27 @@ PQprint(fout, res, header, align, standard, html3, expanded, pager, fieldSep, ta
Safefree(ps.fieldName);
void
PQdisplayTuples(res, fp, fillAlign, fieldSep, printHeader, quiet)
PGresult * res
FILE * fp
int fillAlign
char * fieldSep
int printHeader
int quiet
CODE:
PQdisplayTuples(res, fp, fillAlign, (const char *)fieldSep, printHeader, quiet);
void
PQprintTuples(res, fout, printAttName, terseOutput, width)
PGresult * res
FILE * fout
int printAttName
int terseOutput
int width
int
lo_open(conn, lobjId, mode)
PGconn * conn
@ -528,22 +629,21 @@ lo_read(conn, fd, buf, len)
ALIAS:
PQlo_read = 1
PREINIT:
SV *sv_buffer = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
SV *bufsv = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
INPUT:
PGconn * conn
int fd
int len
char * buf = sv_grow(sv_buffer, len + 1);
CLEANUP:
if (RETVAL >= 0) {
SvCUR(sv_buffer) = RETVAL;
SvPOK_only(sv_buffer);
*SvEND(sv_buffer) = '\0';
if (tainting) {
sv_magic(sv_buffer, 0, 't', 0, 0);
}
char * buf = sv_grow(bufsv, len + 1);
CODE:
RETVAL = lo_read(conn, fd, buf, len);
if (RETVAL > 0) {
SvCUR_set(bufsv, RETVAL);
*SvEND(bufsv) = '\0';
}
OUTPUT:
RETVAL
buf
int
lo_write(conn, fd, buf, len)
@ -641,17 +741,17 @@ connectdb(conninfo)
RETVAL
HV *
conndefaults()
PG_conn
setdbLogin(pghost, pgport, pgoptions, pgtty, dbname, login, pwd)
char * pghost
char * pgport
char * pgoptions
char * pgtty
char * dbname
char * login
char * pwd
CODE:
PQconninfoOption *infoOption;
RETVAL = newHV();
if (infoOption = PQconndefaults()) {
while (infoOption->keyword != NULL) {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv(infoOption->val, 0), 0);
infoOption++;
}
}
RETVAL = PQsetdb(pghost, pgport, pgoptions, pgtty, dbname);
OUTPUT:
RETVAL
@ -669,6 +769,25 @@ setdb(pghost, pgport, pgoptions, pgtty, dbname)
RETVAL
HV *
conndefaults()
CODE:
PQconninfoOption *infoOption;
RETVAL = newHV();
if (infoOption = PQconndefaults()) {
while (infoOption->keyword != NULL) {
if (infoOption->val != NULL) {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv(infoOption->val, 0), 0);
} else {
hv_store(RETVAL, infoOption->keyword, strlen(infoOption->keyword), newSVpv("", 0), 0);
}
infoOption++;
}
}
OUTPUT:
RETVAL
@ -692,6 +811,11 @@ PQreset(conn)
PG_conn conn
int
PQrequestCancel(conn)
PG_conn conn
char *
PQdb(conn)
PG_conn conn
@ -703,12 +827,12 @@ PQuser(conn)
char *
PQhost (conn)
PQpass (conn)
PG_conn conn
char *
PQoptions (conn)
PQhost (conn)
PG_conn conn
@ -722,6 +846,11 @@ PQtty(conn)
PG_conn conn
char *
PQoptions(conn)
PG_conn conn
ConnStatusType
PQstatus(conn)
PG_conn conn
@ -732,6 +861,16 @@ PQerrorMessage(conn)
PG_conn conn
int
PQsocket(conn)
PG_conn conn
int
PQbackendPID(conn)
PG_conn conn
void
PQtrace(conn, debug_port)
PG_conn conn
@ -752,21 +891,66 @@ PQexec(conn, query)
if (RETVAL) {
RETVAL->result = PQexec((PGconn *)conn, query);
if (!RETVAL->result) {
RETVAL->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
RETVAL->result = (PG_result)calloc(1, sizeof(PGresult));
}
}
OUTPUT:
RETVAL
void
PQnotifies(conn)
PG_conn conn
PREINIT:
PGnotify *notify;
PPCODE:
notify = PQnotifies(conn);
if (notify) {
XPUSHs(sv_2mortal(newSVpv((char *)notify->relname, 0)));
XPUSHs(sv_2mortal(newSViv(notify->be_pid)));
free(notify);
}
int
PQsendQuery(conn, query)
PG_conn conn
char * query
PG_results
PQgetResult(conn)
PG_conn conn
CODE:
RETVAL = (PG_results)calloc(1, sizeof(PGresults));
if (RETVAL) {
RETVAL->result = PQgetResult((PGconn *)conn);
if (!RETVAL->result) {
RETVAL->result = (PG_result)calloc(1, sizeof(PGresult));
}
}
OUTPUT:
RETVAL
int
PQisBusy(conn)
PG_conn conn
int
PQconsumeInput(conn)
PG_conn conn
int
PQgetline(conn, string, length)
PREINIT:
SV *sv_buffer = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
INPUT:
PG_conn conn
int length
char * string = sv_grow(sv_buffer, length);
char * string = sv_grow(bufsv , length);
CODE:
RETVAL = PQgetline(conn, string, length);
OUTPUT:
@ -775,28 +959,45 @@ PQgetline(conn, string, length)
int
PQendcopy(conn )
PQputline(conn, string )
PG_conn conn
char * string
void
PQputline(conn, string)
int
PQgetlineAsync(conn, buffer, bufsize)
PREINIT:
SV *bufsv = SvROK(ST(1)) ? SvRV(ST(1)) : ST(1);
INPUT:
PG_conn conn
int bufsize
char * buffer = sv_grow(bufsv, bufsize);
CODE:
RETVAL = PQgetline(conn, buffer, bufsize);
OUTPUT:
RETVAL
buffer
int
PQendcopy(conn)
PG_conn conn
char * string
void
PQnotifies(conn)
PG_results
PQmakeEmptyPGresult(conn, status )
PG_conn conn
PREINIT:
PGnotify *notify;
PPCODE:
notify = PQnotifies(conn);
if (notify) {
XPUSHs(sv_2mortal(newSVpv((char *)notify->relname, 0)));
XPUSHs(sv_2mortal(newSViv(notify->be_pid)));
free(notify);
ExecStatusType status
CODE:
RETVAL = (PG_results)calloc(1, sizeof(PGresults));
if (RETVAL) {
RETVAL->result = PQmakeEmptyPGresult((PGconn *)conn, status);
if (!RETVAL->result) {
RETVAL->result = (PG_result)calloc(1, sizeof(PGresult ));
}
}
OUTPUT:
RETVAL
int
@ -815,21 +1016,21 @@ lo_close(conn, fd)
int
lo_read(conn, fd, buf, len)
PREINIT:
SV *sv_buffer = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
SV *bufsv = SvROK(ST(2)) ? SvRV(ST(2)) : ST(2);
INPUT:
PG_conn conn
int fd
int len
char * buf = sv_grow(sv_buffer, len + 1);
CLEANUP:
if (RETVAL >= 0) {
SvCUR(sv_buffer) = RETVAL;
SvPOK_only(sv_buffer);
*SvEND(sv_buffer) = '\0';
if (tainting) {
sv_magic(sv_buffer, 0, 't', 0, 0);
}
char * buf = sv_grow(bufsv, len + 1);
CODE:
RETVAL = lo_read(conn, fd, buf, len);
if (RETVAL > 0) {
SvCUR_set(bufsv, RETVAL);
*SvEND(bufsv) = '\0';
}
OUTPUT:
RETVAL
buf
int
@ -920,6 +1121,15 @@ PQnfields(res)
RETVAL
int
PQbinaryTuples(res)
PG_results res
CODE:
RETVAL = PQbinaryTuples(res->result);
OUTPUT:
RETVAL
char *
PQfname(res, field_num)
PG_results res
@ -960,6 +1170,16 @@ PQfsize(res, field_num)
RETVAL
int
PQfmod(res, field_num)
PG_results res
int field_num
CODE:
RETVAL = PQfmod(res->result, field_num);
OUTPUT:
RETVAL
char *
PQcmdStatus(res)
PG_results res
@ -1021,38 +1241,38 @@ PQgetisnull(res, tup_num, field_num)
void
PQdisplayTuples(res, fp, fillAlign, fieldSep, printHeader, quiet)
PG_results res
FILE * fp
int fillAlign
char * fieldSep
int printHeader
int quiet
CODE:
PQdisplayTuples(res->result, fp, fillAlign, (const char *)fieldSep, printHeader, quiet);
void
PQprintTuples(res, fout, printAttName, terseOutput, width)
PQfetchrow(res)
PG_results res
FILE * fout
int printAttName
int terseOutput
int width
CODE:
PQprintTuples(res->result, fout, printAttName, terseOutput, width);
PPCODE:
if (res && res->result) {
int cols = PQnfields(res->result);
if (PQntuples(res->result) > res->row) {
int col = 0;
EXTEND(sp, cols);
while (col < cols) {
if (PQgetisnull(res->result, res->row, col)) {
PUSHs(&sv_undef);
} else {
char *val = PQgetvalue(res->result, res->row, col);
PUSHs(sv_2mortal((SV*)newSVpv(val, 0)));
}
++col;
}
++res->row;
}
}
void
PQprint(res, fout, header, align, standard, html3, expanded, pager, fieldSep, tableOpt, caption, ...)
FILE * fout
PG_results res
bool header
bool align
bool standard
bool html3
bool expanded
bool pager
pq bool header
pq bool align
pq bool standard
pq bool html3
pq bool expanded
pq bool pager
char * fieldSep
char * tableOpt
char * caption
@ -1078,23 +1298,23 @@ PQprint(res, fout, header, align, standard, html3, expanded, pager, fieldSep, ta
void
PQfetchrow(res )
PQdisplayTuples(res, fp, fillAlign, fieldSep, printHeader, quiet )
PG_results res
PPCODE:
if (res && res->result) {
int cols = PQnfields(res->result);
if (PQntuples(res->result) > res->row) {
int col = 0;
EXTEND(sp, cols);
while (col < cols) {
if (PQgetisnull(res->result, res->row, col)) {
PUSHs(&sv_undef);
} else {
char *val = PQgetvalue(res->result, res->row, col);
PUSHs(sv_2mortal((SV*)newSVpv(val, 0)));
}
++col;
}
++res->row;
}
}
FILE * fp
int fillAlign
char * fieldSep
int printHeader
int quiet
CODE:
PQdisplayTuples(res->result, fp, fillAlign, (const char *)fieldSep, printHeader, quiet);
void
PQprintTuples(res, fout, printAttName, terseOutput, width)
PG_results res
FILE * fout
int printAttName
int terseOutput
int width
CODE:
PQprintTuples(res->result, fout, printAttName, terseOutput, width);