PAB3-DB-Driver-Sqlite3
view release on metacpan or search on metacpan
# * 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:
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 )