PAB3-DB-Driver-Sqlite3

 view release on metacpan or  search on metacpan

Sqlite3.xs  view on Meta::CPAN

# * num_fields( resid )
# ******************************************************************************/

U32
num_fields( resid )
	void * resid;
PREINIT:
	dMY_CXT;
CODE:
	switch( my_stmt_or_res( &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_res( &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;
	DWORD i;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	for( i = 0; i < res->numfields; i ++ )
		XPUSHs( sv_2mortal( newSVpvn( res->fields[i].name, res->fields[i].name_length ) ) );	
exit:
	{}


#/******************************************************************************
# * fetch_field( resid [, offset] )
# ******************************************************************************/

void
fetch_field( resid, offset = -1 )
	void * resid;
	long offset;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_STMT *stmt;
	DWORD i;
	const char *table, *catalog, *dt, *cs;
	int nn, pk, ai, r;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		stmt = res->stmt;
		break;
	case MY_TYPE_STMT:
		stmt = (MY_STMT *) resid;
		res = stmt->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	if( offset >= 0 ) {
		if( offset >= res->numfields )
			res->fieldpos = res->numfields - 1;
		else
			res->fieldpos = offset;
	}
	i = res->fieldpos;
	if( i >= res->numfields ) goto exit;
	XPUSHs( sv_2mortal( newSVpvn( "name", 4 ) ) );
	XPUSHs( sv_2mortal( newSVpvn( res->fields[i].name, res->fields[i].name_length ) ) );
#ifdef SQLITE_ENABLE_COLUMN_METADATA
	if( stmt != NULL ) {
		table = sqlite3_column_table_name( stmt->stmt, i );
		XPUSHs( sv_2mortal( newSVpvn( "table", 5 ) ) );
		XPUSHs( sv_2mortal( newSVpvn( table, strlen( table ) ) ) );
		catalog = sqlite3_column_database_name( stmt->stmt, i );
		XPUSHs( sv_2mortal( newSVpvn( "catalog", 7 ) ) );
		XPUSHs( sv_2mortal( newSVpvn( catalog, strlen( catalog ) ) ) );
		r = sqlite3_table_column_metadata(
			stmt->con->con, catalog, table, res->fields[i].name,
			&dt, &cs, &nn, &pk, &ai
		);
		if( r == SQLITE_OK ) {
			XPUSHs( sv_2mortal( newSVpvn( "nullable", 8 ) ) );
			XPUSHs( sv_2mortal( newSViv( ! nn ) ) );
			XPUSHs( sv_2mortal( newSVpvn( "primary", 7 ) ) );
			XPUSHs( sv_2mortal( newSViv( pk ) ) );
			XPUSHs( sv_2mortal( newSVpvn( "identity", 8 ) ) );
			XPUSHs( sv_2mortal( newSViv( ai ) ) );
		}
	}
#endif
exit:
	{}


#/******************************************************************************
# * field_seek( resid [, offset] )
# ******************************************************************************/

U32
field_seek( resid, offset = 0 )
	void * resid;
	long offset;
PREINIT:
	dMY_CXT;
	MY_RES *res;
CODE:
	RETVAL = 0;
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	RETVAL = res->fieldpos;
	if( offset < 0 )
		res->fieldpos = 0;
	else if( offset >= res->numfields )
		res->fieldpos = res->numfields - 1;
	else
		res->fieldpos = offset;
exit:
OUTPUT:
	RETVAL


#/******************************************************************************
# * fetch_row( resid )
# ******************************************************************************/

void
fetch_row( resid )
	void * resid;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_ROWS *row;
	unsigned long i;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	row = res->current_row;
	if( row == NULL ) goto exit;
	EXTEND( SP, res->numfields );
	for( i = 0; i < res->numfields; i ++ ) {
		switch( row->types[i] ) {
		case SQLITE_INTEGER:
			XPUSHs( sv_2mortal( newSViv( *((int*) row->data[i]) ) ) );
			break;
		case SQLITE_FLOAT:
			XPUSHs( sv_2mortal( newSVnv( *((double*) row->data[i]) ) ) );
			break;
		case SQLITE_TEXT:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[i] ) ) );
			break;
		case SQLITE_BLOB:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[i] ) ) );
			break;
		case SQLITE_NULL:
			XPUSHs( &PL_sv_undef );
			break;
		}
	}
	res->current_row = row->next;
	res->rowpos ++;
exit:
	{}


#/******************************************************************************
# * fetch_col( resid )
# ******************************************************************************/

void
fetch_col( resid )
	void * resid;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_ROWS *row;
	unsigned long i;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	EXTEND( SP, res->numrows );
	row = res->data_cursor;
	while( row ) {
		switch( row->types[0] ) {
		case SQLITE_INTEGER:
			XPUSHs( sv_2mortal( newSViv( *((int*) row->data[0]) ) ) );
			break;
		case SQLITE_FLOAT:
			XPUSHs( sv_2mortal( newSVnv( *((double*) row->data[0]) ) ) );
			break;
		case SQLITE_TEXT:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[0] ) ) );
			break;
		case SQLITE_BLOB:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[0] ) ) );
			break;
		case SQLITE_NULL:
			XPUSHs( &PL_sv_undef );
			break;
		}
		row = row->next;
	}
	res->rowpos = res->numrows;
	res->current_row = NULL;
exit:
	{}


#/******************************************************************************
# * fetch_hash( resid )
# ******************************************************************************/

void
fetch_hash( resid )
	void * resid;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_ROWS *row;
	DWORD i;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	row = res->current_row;
	if( row == NULL ) goto exit;
	EXTEND( SP, res->numfields );
	for( i = 0; i < res->numfields; i ++ ) {
		XPUSHs( sv_2mortal( newSVpvn( res->fields[i].name, res->fields[i].name_length ) ) );	
		switch( row->types[i] ) {
		case SQLITE_INTEGER:
			XPUSHs( sv_2mortal( newSViv( *((int*) row->data[i]) ) ) );
			break;
		case SQLITE_FLOAT:
			XPUSHs( sv_2mortal( newSVnv( *((double*) row->data[i]) ) ) );
			break;
		case SQLITE_TEXT:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[i] ) ) );
			break;
		case SQLITE_BLOB:
			XPUSHs( sv_2mortal( newSVpvn( row->data[i], row->lengths[i] ) ) );
			break;
		case SQLITE_NULL:
			XPUSHs( &PL_sv_undef );
			break;
		}
	}
	res->current_row = row->next;
	res->rowpos ++;
exit:
	{}


#/******************************************************************************
# * fetch_lengths( resid )
# ******************************************************************************/

void
fetch_lengths( resid )
	void * resid;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_ROWS *row;
	DWORD i;
PPCODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		res = (MY_RES *) resid;
		break;
	case MY_TYPE_STMT:
		res = ((MY_STMT *) resid)->res;
		if( res == NULL ) goto exit;
		break;
	default:
		goto exit;
	}
	row = res->current_row;
	if( row == NULL ) goto exit;
	EXTEND( SP, res->numfields );
	for( i = 0; i < res->numfields; i ++ ) {
		XPUSHs( sv_2mortal( newSVuv( row->lengths[i] ) ) );	
	}
exit:
	{}


#/******************************************************************************
# * row_tell( resid )
# ******************************************************************************/

U32
row_tell( resid )
	void * resid;
PREINIT:
	dMY_CXT;
CODE:
	switch( my_stmt_or_res( &MY_CXT, resid ) ) {
	case MY_TYPE_RES:
		RETVAL = ( (MY_RES *) resid )->rowpos;
		break;
	case MY_TYPE_STMT:
		RETVAL = ((MY_STMT *) resid)->res != NULL
			? ((MY_STMT *) resid)->res->rowpos : 0;
		break;
	default:
		RETVAL = 0;
	}
OUTPUT:
	RETVAL


#/******************************************************************************
# * row_seek( resid, offset )
# ******************************************************************************/

long
row_seek( resid, offset = 0 )
	void * resid;
	long offset;
PREINIT:
	dMY_CXT;
	MY_RES *res;
	MY_ROWS *row;
	unsigned long remaining;
CODE:

Sqlite3.xs  view on Meta::CPAN

		if( ( con->my_flags & MYCF_AUTOCOMMIT ) == 0 ) {
			r = sqlite3_exec( con->con, "BEGIN TRANSACTION", 0, 0, 0 );
			if( r != SQLITE_OK ) goto error;
			con->my_flags |= MYCF_TRANSACTION;
		}
	}
	RETVAL = 1;
	goto exit;
error:
	RETVAL = 0;
exit:
OUTPUT:
	RETVAL


#/******************************************************************************
# * rollback( [linkid] )
# ******************************************************************************/

int
rollback( linkid = 0 )
	void * linkid;
PREINIT:
	dMY_CXT;
	MY_CON *con;
	int r;
CODE:
	con = (MY_CON *) my_verify_linkid( &MY_CXT, linkid );
	if( con == NULL ) goto error;
	if( ( con->my_flags & MYCF_TRANSACTION ) != 0 ) {
		r = sqlite3_exec( con->con, "ROLLBACK TRANSACTION", 0, 0, 0 );
		if( r != SQLITE_OK ) goto error;
		con->my_flags ^= MYCF_TRANSACTION;
		if( ( con->my_flags & MYCF_AUTOCOMMIT ) == 0 ) {
			r = sqlite3_exec( con->con, "BEGIN TRANSACTION", 0, 0, 0 );
			if( r != SQLITE_OK ) goto error;
			con->my_flags |= MYCF_TRANSACTION;
		}
	}
	RETVAL = 1;
	goto exit;
error:
	RETVAL = 0;
exit:
OUTPUT:
	RETVAL


#/******************************************************************************
# * show_catalogs( [linkid [, wild]] )
# ******************************************************************************/

void
show_catalogs( linkid = 0, wild = NULL )
	void * linkid;
	const char *wild;
PREINIT:
	dMY_CXT;
	int r;
	MY_CON *con;
PPCODE:
	int _intcb( void *arg, int columns, char **data, char **names ) {
		if( columns > 1 )
			XPUSHs( sv_2mortal( newSVpvn( data[1], strlen( data[1] ) ) ) );
		return 0;
	}
	
	con = (MY_CON *) my_verify_linkid( &MY_CXT, linkid );
	if( con == NULL ) goto error;
	
	r = sqlite3_exec( con->con, "PRAGMA database_list", &_intcb, 0, 0 );
error:
	{}


#/******************************************************************************
# * show_tables( [linkid, [schema [, db [, wild]]]] )
# ******************************************************************************/

void
show_tables( linkid = 0, schema = NULL, db = NULL, wild = NULL )
	void * linkid;
	const char *db;
	const char *schema;
	const char *wild;
PREINIT:
	dMY_CXT;
	MY_CON *con;
	AV *av;
	char sql[256], *p1;
PPCODE:
	// TABLE, SCHEMA, DB, TYPE
	
	int _intcb( void *arg, int columns, char **data, char **names ) {
		/*
		int i;
		for( i = 0; i < columns; i ++ ) {
			printf( "%s => %s ", names[i], data[i] );
		}
		printf( "\n" );
		*/
		av = (AV *) sv_2mortal( (SV *) newAV() );
		av_push( av, newSVpvn( data[2], strlen( data[2] ) ) );
		av_push( av, &PL_sv_undef );
		if( db == NULL )
			av_push( av, newSVpvn( "main", 4 ) );
		else
			av_push( av, newSVpvn( db, strlen( db ) ) );
		av_push( av, newSVpvn( data[0], strlen( data[0] ) ) );
		XPUSHs( newRV( (SV *) av ) );
		return 0;
	}

	con = (MY_CON *) my_verify_linkid( &MY_CXT, linkid );
	if( con == NULL ) goto error;
	
	p1 = my_strcpy( sql, "SELECT * FROM " );
	if( db != NULL ) {
		p1 = my_strcpy( p1, db );
		*p1 ++ = '.';
	}
	p1 = my_strcpy( p1, "SQLITE_MASTER WHERE " );
	if( wild != NULL ) {
		p1 = my_strcpy( p1, "type='" );
		p1 = my_strcpy( p1, wild );
		p1 = my_strcpy( p1, "'" );
	}
	else {
		p1 = my_strcpy( p1, "type='table' or type='view'" );
	}
	sqlite3_exec( con->con, sql, &_intcb, 0, 0 );
error:
	{}


#/******************************************************************************
# * show_fields( [linkid, ] table [, schema [, db [, wild]]]] )
# ******************************************************************************/

void
show_fields( ... )
PREINIT:
	dMY_CXT;
	void *linkid = NULL;
	const char *table;
	const char *schema = NULL;
	const char *db = NULL;
	const char *wild = NULL;
	int itemp = 0;
	MY_CON *con;
	AV *av;
	char *sql, *p1;
PPCODE:
	// COLUMN, NULLABLE, DEFAULT, IS_PRIMARY, IS_UNIQUE, TYPENAME, AUTOINC
	
	int _intcb( void *arg, int columns, char **data, char **names ) {
		// cid|name|type|notnull|dflt_value|pk
		int pk;
		av = (AV *) sv_2mortal( (SV *) newAV() );
		av_push( av, newSVpvn( data[1], strlen( data[1] ) ) );
		av_push( av, newSViv( data[3][0] == '0' ) );
		if( data[4] )
			av_push( av, newSVpvn( data[4], strlen( data[4] ) ) );
		else
			av_push( av, &PL_sv_undef );
		pk = data[5][0] == '1' ? 1 : 0;
		av_push( av, newSViv( pk ) );
		av_push( av, &PL_sv_undef );
		av_push( av, newSVpvn( data[2], strlen( data[2] ) ) );
		av_push( av, newSViv( my_stricmp( data[2], "integer" ) == 0 && pk == 1 ) );
		XPUSHs( newRV( (SV *) av ) );
		return 0;
	}
	
    if( items < ( SvIOK( ST(0) ) ? 2 : 1 ) || items > 5 )
		Perl_croak( aTHX_ "Usage: " __PACKAGE__ "::show_fields(linkid = 0, table, schema = NULL, db = NULL, wild = NULL)" );
	if( SvIOK( ST( itemp ) ) ) {
		linkid = INT2PTR( void *, SvIV( ST( itemp ) ) );
		itemp ++;
	}
	table = (const char *) SvPV_nolen( 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 *) my_verify_linkid( &MY_CXT, linkid );
	if( con == NULL ) goto error;

	New( 1, sql, 23 + strlen( table ), char );
	p1 = my_strcpy( sql, "PRAGMA table_info('" );
	p1 = my_strcpy( p1, table );
	p1 = my_strcpy( p1, "')" );
	sqlite3_exec( con->con, sql, &_intcb, 0, 0 );
	Safefree( sql );
error:
	{}


#/******************************************************************************
# * show_index( [linkid, ] table [, schema [, db]]] )
# ******************************************************************************/

void
show_index( ... )
PREINIT:
	dMY_CXT;
	void *linkid = NULL;
	const char *table;
	const char *schema = NULL;
	const char *db = NULL;
	int itemp = 0;
	MY_CON *con;
	AV *av;
	char *sql, **il_data, *p1;
PPCODE:

	// NAME, COLUMN, TYPE

	int _intcb_ii( void *arg, int columns, char **data, char **names ) {
		// seqno|cid|name
		if( columns < 3 ) return 0;
		av = (AV *) sv_2mortal( (SV *) newAV() );
		av_push( av, newSVpvn( il_data[1], strlen( il_data[1] ) ) );
		av_push( av, newSVpvn( data[2], strlen( data[2] ) ) );
		av_push( av, newSViv( il_data[2][0] == '1' ? 2 : 3 ) );
		XPUSHs( newRV( (SV *) av ) );
		return 0;
	}
	
	int _intcb_il( void *arg, int columns, char **data, char **names ) {
		// seq|name|unique
		char *sql2, *p2;
		if( columns < 3 ) return 0;
		il_data = data;
		New( 1, sql2, 22 + strlen( data[1] ), char );
		p2 = my_strcpy( sql2, "PRAGMA index_info('" );
		p2 = my_strcpy( p2, data[1] );
		p2 = my_strcpy( p2, "')" );
		sqlite3_exec( con->con, sql2, &_intcb_ii, 0, 0 );
		Safefree( sql2 );
		return 0;
	}
	
	int _intcb_ti( void *arg, int columns, char **data, char **names ) {
		// cid|name|type|notnull|dflt_value|pk
		if( columns < 6 ) return 0;
		if( data[5][0] == '1' ) {
			av = (AV *) sv_2mortal( (SV *) newAV() );
			av_push( av, newSVpvn( "PRIMARY", 7 ) );
			av_push( av, newSVpvn( data[1], strlen( data[1] ) ) );
			av_push( av, newSViv( 1 ) );
			XPUSHs( newRV( (SV *) av ) );
		}
		return 0;
	}
	
    if( items < ( SvIOK( ST(0) ) ? 2 : 1 ) || items > 4 )
		Perl_croak( aTHX_ "Usage: " __PACKAGE__ "::show_index(linkid = 0, table, schema = NULL, db = NULL)" );
	if( SvIOK( ST( itemp ) ) ) {
		linkid = INT2PTR( void *, SvIV( ST( itemp ) ) );
		itemp ++;
	}
	table = (const char *) SvPV_nolen( ST( itemp ) );
	itemp ++;
	if( itemp < items ) {
		schema = (const char *) SvPV_nolen( ST( itemp ) );
		itemp ++;
	}
	if( itemp < items )
		db = (const char *) SvPV_nolen( ST( itemp ) );
	con = (MY_CON *) my_verify_linkid( &MY_CXT, linkid );
	if( con == NULL ) goto error;

	New( 1, sql, 23 + strlen( table ), char );
	p1 = my_strcpy( sql, "PRAGMA table_info('" );



( run in 0.483 second using v1.01-cache-2.11-cpan-5511b514fd6 )