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 )