PAB3-DB-Driver-Postgres
view release on metacpan or search on metacpan
Postgres.xs view on Meta::CPAN
# ******************************************************************************/
U32
num_fields( resid )
void * resid;
PREINIT:
dMY_CXT;
CODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
RETVAL = ( (MY_RES *) resid )->numfields;
break;
case MY_TYPE_STMT:
RETVAL = ( (MY_STMT *) resid )->res != NULL
? ( (MY_STMT *) resid )->res->numfields : 0;
break;
default:
RETVAL = 0;
}
OUTPUT:
RETVAL
#/******************************************************************************
# * num_rows( resid )
# ******************************************************************************/
U32
num_rows( resid )
void * resid;
PREINIT:
dMY_CXT;
CODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
RETVAL = ( (MY_RES *) resid )->numrows;
break;
case MY_TYPE_STMT:
RETVAL = ( (MY_STMT *) resid )->res != NULL
? ( (MY_STMT *) resid )->res->numrows : 0;
break;
default:
RETVAL = 0;
}
OUTPUT:
RETVAL
#/******************************************************************************
# * fetch_names( resid )
# ******************************************************************************/
void
fetch_names( resid )
void * resid;
PREINIT:
dMY_CXT;
MY_RES *res;
const char *name;
int num_fields, i;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
res = (MY_RES *) resid;
num_fields = res->numfields;
for( i = 0; i < num_fields; i ++ ) {
name = PQfname( res->res, i );
XPUSHs( sv_2mortal( newSVpvn( name, strlen( name ) ) ) );
}
}
#/******************************************************************************
# * fetch_field( resid [, offset] )
# ******************************************************************************/
void
fetch_field( resid, offset = -1 )
void * resid;
long offset;
PREINIT:
dMY_CXT;
MY_RES *res = NULL;
const char *tmps;
UV tmpu;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
if( offset >= 0 ) {
if( (UV) offset >= res->numfields )
res->fieldpos = res->numfields - 1;
else
res->fieldpos = offset;
}
if( res->fieldpos < res->numfields ) {
XPUSHs( sv_2mortal( newSVpvn( "name", 4 ) ) );
tmps = PQfname( res->res, res->fieldpos );
XPUSHs( sv_2mortal( newSVpvn( tmps, strlen( tmps ) ) ) );
XPUSHs( sv_2mortal( newSVpvn( "length", 6 ) ) );
tmpu = PQfsize( res->res, res->fieldpos );
XPUSHs( sv_2mortal( newSVuv( tmpu ) ) );
}
}
#/******************************************************************************
# * field_seek( resid [, offset] )
# ******************************************************************************/
U32
field_seek( resid, offset = 0 )
void * resid;
U32 offset;
PREINIT:
dMY_CXT;
MY_RES *res;
CODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
RETVAL = res->fieldpos;
if( offset < 0 )
res->fieldpos = 0;
else if( offset >= res->numfields )
res->fieldpos = res->numfields - 1;
else
res->fieldpos = offset;
}
else RETVAL = 0;
OUTPUT:
RETVAL
#/******************************************************************************
# * field_tell( resid )
# ******************************************************************************/
U32
field_tell( resid )
void * resid;
PREINIT:
dMY_CXT;
CODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case 1:
RETVAL = ( (MY_RES *) resid )->fieldpos;
break;
case 2:
RETVAL = ( (MY_STMT *) resid )->res != NULL
? ( (MY_STMT *) resid )->res->fieldpos : 0;
break;
default:
RETVAL = 0;
break;
}
OUTPUT:
RETVAL
#/******************************************************************************
# * fetch_row( resid )
# ******************************************************************************/
void
fetch_row( resid )
void * resid;
PREINIT:
dMY_CXT;
DWORD i, l;
MY_RES *res;
const char *val;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
if( res->rowpos < res->numrows ) {
EXTEND( SP, res->numfields );
for( i = 0; i < res->numfields; i ++ ) {
if( PQgetisnull( res->res, res->rowpos, i ) ) {
XPUSHs( &PL_sv_undef );
}
else {
l = PQgetlength( res->res, res->rowpos, i );
val = PQgetvalue( res->res, res->rowpos, i );
XPUSHs( sv_2mortal( newSVpvn( val, l ) ) );
}
}
res->rowpos ++;
}
}
#/******************************************************************************
# * fetch_col( resid )
# ******************************************************************************/
void
fetch_col( resid )
void * resid;
PREINIT:
dMY_CXT;
MY_RES *res;
DWORD i, l;
const char *val;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
EXTEND( SP, res->numrows );
for( i = 0; i < res->numrows; i ++ ) {
if( PQgetisnull( res->res, i, 0 ) ) {
XPUSHs( &PL_sv_undef );
}
else {
l = PQgetlength( res->res, i, 0 );
val = PQgetvalue( res->res, i, 0 );
XPUSHs( sv_2mortal( newSVpvn( val, l ) ) );
}
}
res->rowpos = res->numrows;
}
#/******************************************************************************
# * fetch_hash( resid )
# ******************************************************************************/
void
fetch_hash( resid )
void * resid;
PREINIT:
dMY_CXT;
MY_RES *res;
DWORD i, l;
const char *val, *name;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
if( res->rowpos < res->numrows ) {
EXTEND( SP, res->numfields * 2 );
for( i = 0; i < res->numfields; i ++ ) {
name = PQfname( res->res, i );
XPUSHs( sv_2mortal( newSVpvn( name, strlen( name ) ) ) );
if( PQgetisnull( res->res, res->rowpos, i ) ) {
XPUSHs( &PL_sv_undef );
}
else {
l = PQgetlength( res->res, res->rowpos, i );
val = PQgetvalue( res->res, res->rowpos, i );
XPUSHs( sv_2mortal( newSVpvn( val, l ) ) );
}
}
res->rowpos ++;
}
}
#/******************************************************************************
# * fetch_lengths( resid )
# ******************************************************************************/
void
fetch_lengths( resid )
void * resid;
PREINIT:
dMY_CXT;
MY_RES *res;
DWORD i, s;
PPCODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
EXTEND( SP, res->numfields );
for( i = 0; i < res->numfields; i ++ ) {
s = PQfsize( res->res, i );
XPUSHs( sv_2mortal( newSVuv( s ) ) );
}
}
#/******************************************************************************
# * row_seek( resid, offset )
# ******************************************************************************/
long
row_seek( resid, offset = 0 )
void * resid;
U32 offset;
PREINIT:
dMY_CXT;
MY_RES *res;
CODE:
switch( my_stmt_or_result( &MY_CXT, resid ) ) {
case MY_TYPE_RES:
res = (MY_RES *) resid;
break;
case MY_TYPE_STMT:
res = ( (MY_STMT *) resid )->res;
break;
}
if( res != NULL ) {
RETVAL = res->rowpos;
if( offset < 0 )
res->rowpos = 0;
else if( offset >= res->numrows )
res->rowpos = res->numrows - 1;
else
res->rowpos = offset;
}
else RETVAL = -1;
OUTPUT:
RETVAL
#/******************************************************************************
# * row_tell( resid )
# ******************************************************************************/
long
row_tell( resid )
void * resid;
PREINIT:
dMY_CXT;
Postgres.xs view on Meta::CPAN
OUTPUT:
RETVAL
#/******************************************************************************
# * rollback( [linkid] )
# ******************************************************************************/
int
rollback( linkid )
void * linkid;
PREINIT:
dMY_CXT;
MY_CON *con;
PGresult *res;
CODE:
RETVAL = 0;
con = my_con_verify( &MY_CXT, linkid );
if( con == NULL ) goto exit;
if( ( con->my_flags & MYCF_TRANSACTION ) != 0 ) {
res = PQexec( con->con, "ROLLBACK" );
if( PQresultStatus( res ) == PGRES_COMMAND_OK ) {
con->my_flags ^= MYCF_TRANSACTION;
if( ( con->my_flags & MYCF_AUTOCOMMIT ) == 0 ) {
// disable auto commit
PQclear( res );
res = PQexec( con->con, "BEGIN" );
if( PQresultStatus( res ) == PGRES_COMMAND_OK )
RETVAL = 1;
else
RETVAL = 0;
}
else
RETVAL = 1;
}
else
RETVAL = 0;
PQclear( res );
}
else
RETVAL = 1;
exit:
OUTPUT:
RETVAL
#/******************************************************************************
# * show_catalogs( [linkid [, wild]] )
# ******************************************************************************/
void
show_catalogs( linkid = 0, wild = 0 )
void * linkid;
const char *wild;
PREINIT:
dMY_CXT;
MY_CON *con;
PGresult *pres;
DWORD numrows, i, l;
const char *val;
PPCODE:
con = my_con_verify( &MY_CXT, linkid );
if( con == NULL ) goto error;
pres = PQexec( con->con, "select datname from pg_database" );
if( PQresultStatus( pres ) == PGRES_TUPLES_OK ) {
numrows = PQntuples( pres );
for( i = 0; i < numrows; i ++ ) {
l = PQgetlength( pres, i, 0 );
val = PQgetvalue( pres, i, 0 );
XPUSHs( sv_2mortal( newSVpvn( val, l ) ) );
}
}
PQclear( pres );
error:
{}
#/******************************************************************************
# * show_tables( [linkid [, schema [, db [, wild]]]] )
# ******************************************************************************/
void
show_tables( ... )
PREINIT:
dMY_CXT;
void *linkid = NULL;
const char *db = NULL;
const char *schema = NULL;
const char *wild = NULL;
MY_CON *con;
char sql[1024], *p1;
DWORD numrows, i, l, dbl;
int itemp = 0;
const char *val;
AV *av;
PGresult *res;
PPCODE:
if( items < 0 || items > 4 )
Perl_croak( aTHX_ "Usage: " __PACKAGE__ "::show_tables(linkid = 0, schema = NULL, db = NULL, wild = NULL)" );
if( SvIOK( ST( itemp ) ) ) {
linkid = INT2PTR( void *, SvIV( ST( itemp ) ) );
itemp ++;
}
if( itemp < items ) {
schema = (const char *) SvPV_nolen( ST( itemp ) );
itemp ++;
}
if( itemp < items ) {
db = (const char *) SvPV_nolen( ST( itemp ) );
itemp ++;
}
if( itemp < items )
wild = (const char *) SvPV_nolen( ST( itemp ) );
con = my_con_verify( &MY_CXT, linkid );
if( con == NULL ) goto error;
/*
SELECT
c.relname AS objectname,
n.nspname AS schemaname,
c.relkind AS objecttype
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE ( c.relkind = 'r'::"char" OR c.relkind = 'v'::"char" ) AND ( n.nspname = 'schema' )
ORDER BY c.relkind, c.relname
*/
p1 = my_strcpy( sql,
"SELECT c.relname AS f0, n.nspname AS f1, c.relkind AS f2"
" FROM pg_class c"
" LEFT JOIN pg_namespace n ON n.oid = c.relnamespace"
" WHERE ("
);
itemp = 0;
if( wild == NULL || my_stristr( wild, "table" ) != NULL ) {
p1 = my_strcpy( p1, "c.relkind = 'r'::\"char\"" );
itemp ++;
}
if( wild == NULL || my_stristr( wild, "view" ) != NULL ) {
if( itemp )
p1 = my_strcpy( p1, " OR " );
p1 = my_strcpy( p1, "c.relkind = 'v'::\"char\"" );
itemp ++;
}
p1 = my_strcpy( p1, ")" );
if( schema && schema[0] != '\0' ) {
p1 = my_strcpy( p1, " AND n.nspname = '" );
p1 = my_strcpy( p1, schema );
p1 = my_strcpy( p1, "'" );
}
p1 = my_strcpy( p1, " ORDER BY c.relkind, c.relname" );
//printf( "%s\n", sql );
res = PQexec( con->con, sql );
if( PQresultStatus( res ) == PGRES_TUPLES_OK ) {
// only connected db is permitted
db = PQdb( con->con );
dbl = strlen( db );
numrows = PQntuples( res );
for( i = 0; i < numrows; i ++ ) {
( run in 2.262 seconds using v1.01-cache-2.11-cpan-5511b514fd6 )