* Makefile
* config/*
* contrib/*
* doc/*
* extras/*
* include/*
* lib/*
* package/*
* src/*
* tests/*
* utils/*
* removed empty lines left after removed '$' + 'Id' + '$' identifiers
424 lines
11 KiB
C
424 lines
11 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <ibase.h>
|
|
#include <iberror.h>
|
|
|
|
#ifndef ISC_INT64_FORMAT
|
|
|
|
#if ( defined( _MSC_VER ) && defined( WIN32 ) ) || ( defined( __BORLANDC__ ) && defined( __WIN32__ ) )
|
|
#define ISC_INT64_FORMAT "I64"
|
|
#else
|
|
#define ISC_INT64_FORMAT "ll"
|
|
#endif
|
|
#endif
|
|
|
|
#define USER "sysdba"
|
|
#define PASSWORD "masterkey"
|
|
#define DATABASE "127.0.0.1:d:\\fontes\\lixo\\test.gdb"
|
|
#define ERREXIT( status, rc ) { isc_print_status( status ); return rc; }
|
|
#define MAX_BUFFER 1024
|
|
|
|
int execute( char * exec_str );
|
|
int query( char * sel_str );
|
|
int fetch( void );
|
|
int qclose( void );
|
|
char * getdata( int pos );
|
|
|
|
|
|
isc_db_handle db = NULL;
|
|
int dialect = 1;
|
|
XSQLDA ISC_FAR * sqlda;
|
|
isc_stmt_handle stmt = NULL;
|
|
isc_tr_handle trans = NULL;
|
|
|
|
int main()
|
|
{
|
|
char dpb[ 48 ];
|
|
int i = 0, len;
|
|
long status[ 20 ];
|
|
|
|
dpb[ i++ ] = isc_dpb_version1;
|
|
|
|
dpb[ i++ ] = isc_dpb_user_name;
|
|
len = strlen( USER );
|
|
dpb[ i++ ] = ( char ) len;
|
|
strncpy( &( dpb[ i ] ), USER, len );
|
|
i += len;
|
|
|
|
dpb[ i++ ] = isc_dpb_password;
|
|
len = strlen( PASSWORD );
|
|
dpb[ i++ ] = len;
|
|
strncpy( &( dpb[ i ] ), PASSWORD, len );
|
|
i += len;
|
|
|
|
if( isc_attach_database( status, 0, DATABASE, &db, i, dpb ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
execute( "DROP TABLE TESTE" );
|
|
|
|
execute( "CREATE TABLE TESTE (code smallint)" );
|
|
|
|
execute( "INSERT INTO TESTE (code) VALUES (100)" );
|
|
|
|
query( "SELECT * FROM TESTE" );
|
|
while( fetch() == 0 )
|
|
printf( "%s\n", getdata( 0 ) );
|
|
qclose();
|
|
|
|
|
|
if( isc_detach_database( status, &db ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int execute( char * exec_str )
|
|
{
|
|
isc_tr_handle trans = NULL;
|
|
long status[ 20 ];
|
|
|
|
if( isc_start_transaction( status, &trans, 1, &db, 0, NULL ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
if( isc_dsql_execute_immediate( status, &db, &trans, 0, exec_str, dialect, NULL ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
if( isc_commit_transaction( status, &trans ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
return 1;
|
|
}
|
|
|
|
int query( char * sel_str )
|
|
{
|
|
ISC_STATUS status[ 20 ];
|
|
XSQLVAR * var;
|
|
|
|
int n, i, dtype;
|
|
|
|
if( isc_start_transaction( status, &trans, 1, &db, 0, NULL ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
/* Allocate an output SQLDA. Just to check number of columns */
|
|
sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH( 1 ) );
|
|
sqlda->sqln = 1;
|
|
sqlda->version = 1;
|
|
|
|
/* Allocate a statement */
|
|
if( isc_dsql_allocate_statement( status, &db, &stmt ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
/* Prepare the statement. */
|
|
if( isc_dsql_prepare( status, &trans, &stmt, 0, sel_str, dialect, sqlda ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
/* Describe sql contents */
|
|
if( isc_dsql_describe( status, &stmt, dialect, sqlda ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
/* Relocate necessary number of columns */
|
|
if( sqlda->sqld > sqlda->sqln )
|
|
{
|
|
free( sqlda );
|
|
n = sqlda->sqld;
|
|
sqlda = ( XSQLDA * ) malloc( XSQLDA_LENGTH( n ) );
|
|
sqlda->sqln = n;
|
|
sqlda->version = 1;
|
|
|
|
if( isc_dsql_describe( status, &stmt, dialect, sqlda ) )
|
|
ERREXIT( status, 1 );
|
|
}
|
|
|
|
for( i = 0, var = sqlda->sqlvar; i < sqlda->sqld; i++, var++ )
|
|
{
|
|
dtype = ( var->sqltype & ~1 );
|
|
switch( dtype )
|
|
{
|
|
case SQL_VARYING:
|
|
var->sqltype = SQL_TEXT;
|
|
var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen + 2 );
|
|
break;
|
|
case SQL_TEXT:
|
|
var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen + 2 );
|
|
break;
|
|
case SQL_LONG:
|
|
var->sqltype = SQL_LONG;
|
|
var->sqldata = ( char * ) malloc( sizeof( long ) );
|
|
break;
|
|
default:
|
|
var->sqldata = ( char * ) malloc( sizeof( char ) * var->sqllen );
|
|
break;
|
|
}
|
|
if( var->sqltype & 1 )
|
|
{
|
|
var->sqlind = ( short * ) malloc( sizeof( short ) );
|
|
}
|
|
}
|
|
|
|
if( ! sqlda->sqld )
|
|
{
|
|
/* Execute and commit non-select querys */
|
|
if( isc_dsql_execute( status, &trans, &stmt, dialect, NULL ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
if( isc_commit_transaction( status, &trans ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
trans = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
if( isc_dsql_execute( status, &trans, &stmt, dialect, sqlda ) )
|
|
ERREXIT( status, 1 );
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int fetch( void )
|
|
{
|
|
long fetch_stat;
|
|
long status[ 20 ];
|
|
|
|
fetch_stat = isc_dsql_fetch( status, &stmt, dialect, sqlda );
|
|
|
|
if( fetch_stat != 100L )
|
|
ERREXIT( status, 1 );
|
|
|
|
return fetch_stat;
|
|
}
|
|
|
|
int qclose( void )
|
|
{
|
|
long status[ 20 ];
|
|
|
|
if( isc_dsql_free_statement( status, &stmt, DSQL_drop ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
if( trans )
|
|
if( isc_commit_transaction( status, &trans ) )
|
|
ERREXIT( status, 1 );
|
|
|
|
if( sqlda )
|
|
free( sqlda );
|
|
|
|
return 1;
|
|
}
|
|
|
|
char * getdata( int pos )
|
|
{
|
|
short dtype;
|
|
char data[ MAX_BUFFER ], * p;
|
|
char blob_s[ 20 ], date_s[ 25 ];
|
|
short len;
|
|
long status[ 20 ];
|
|
|
|
struct tm times;
|
|
ISC_QUAD bid;
|
|
XSQLVAR * var;
|
|
|
|
if( ( pos + 1 ) > sqlda->sqln )
|
|
return "error";
|
|
|
|
var = sqlda->sqlvar;
|
|
|
|
var += pos;
|
|
|
|
dtype = var->sqltype & ~1;
|
|
p = data;
|
|
|
|
if( ( var->sqltype & 1 ) && ( *var->sqlind < 0 ) )
|
|
{
|
|
switch( dtype )
|
|
{
|
|
case SQL_TEXT:
|
|
case SQL_VARYING:
|
|
len = var->sqllen;
|
|
break;
|
|
case SQL_SHORT:
|
|
len = 6;
|
|
if( var->sqlscale > 0 )
|
|
len += var->sqlscale;
|
|
break;
|
|
case SQL_LONG:
|
|
len = 11;
|
|
if( var->sqlscale > 0 )
|
|
len += var->sqlscale;
|
|
break;
|
|
case SQL_INT64:
|
|
len = 21;
|
|
if( var->sqlscale > 0 )
|
|
len += var->sqlscale;
|
|
break;
|
|
case SQL_FLOAT:
|
|
len = 15;
|
|
break;
|
|
case SQL_DOUBLE:
|
|
len = 24;
|
|
break;
|
|
case SQL_TIMESTAMP:
|
|
len = 24;
|
|
break;
|
|
case SQL_TYPE_DATE:
|
|
len = 10;
|
|
break;
|
|
case SQL_TYPE_TIME:
|
|
len = 13;
|
|
break;
|
|
case SQL_BLOB:
|
|
case SQL_ARRAY:
|
|
default:
|
|
len = 17;
|
|
break;
|
|
}
|
|
if( ( dtype == SQL_TEXT ) || ( dtype == SQL_VARYING ) )
|
|
sprintf( p, "%-*s ", len, "NULL" );
|
|
else
|
|
sprintf( p, "%*s ", len, "NULL" );
|
|
}
|
|
else
|
|
{
|
|
switch( dtype )
|
|
{
|
|
case SQL_TEXT:
|
|
sprintf( p, "%.*s ", var->sqllen, var->sqldata );
|
|
break;
|
|
|
|
case SQL_VARYING:
|
|
sprintf( p, "%.*s ", var->sqllen, var->sqldata );
|
|
break;
|
|
|
|
case SQL_SHORT:
|
|
case SQL_LONG:
|
|
case SQL_INT64:
|
|
{
|
|
ISC_INT64 value = 0;
|
|
short field_width = 0;
|
|
short dscale;
|
|
|
|
switch( dtype )
|
|
{
|
|
case SQL_SHORT:
|
|
value = ( ISC_INT64 ) *( short ISC_FAR * ) var->sqldata;
|
|
field_width = 6;
|
|
break;
|
|
case SQL_LONG:
|
|
value = ( ISC_INT64 ) *( long ISC_FAR * ) var->sqldata;
|
|
field_width = 11;
|
|
break;
|
|
case SQL_INT64:
|
|
value = ( ISC_INT64 ) *( ISC_INT64 ISC_FAR * ) var->sqldata;
|
|
field_width = 21;
|
|
break;
|
|
}
|
|
dscale = var->sqlscale;
|
|
if( dscale < 0 )
|
|
{
|
|
ISC_INT64 tens;
|
|
short i;
|
|
|
|
tens = 1;
|
|
for( i = 0; i > dscale; i-- )
|
|
{
|
|
tens *= 10;
|
|
|
|
if( value >= 0 )
|
|
{
|
|
|
|
sprintf( p,
|
|
"%*" ISC_INT64_FORMAT "d.%0*"
|
|
ISC_INT64_FORMAT "d",
|
|
field_width - 1 + dscale,
|
|
( ISC_INT64 ) ( value / tens ), -dscale,
|
|
( ISC_INT64 ) ( value % tens ) );
|
|
}
|
|
else if( ( value / tens ) != 0 )
|
|
{
|
|
|
|
sprintf( p,
|
|
"%*" ISC_INT64_FORMAT "d.%0*"
|
|
ISC_INT64_FORMAT "d",
|
|
field_width - 1 + dscale,
|
|
( ISC_INT64 ) ( value / tens ), -dscale,
|
|
( ISC_INT64 ) -( value % tens ) );
|
|
}
|
|
else
|
|
{
|
|
|
|
sprintf( p, "%*s.%0*" ISC_INT64_FORMAT "d",
|
|
field_width - 1 + dscale,
|
|
"-0", -dscale,
|
|
( ISC_INT64 ) -( value % tens ) );
|
|
}
|
|
}
|
|
}
|
|
else if( dscale )
|
|
{
|
|
sprintf( p, "%*" ISC_INT64_FORMAT "d%0*d",
|
|
field_width, ( ISC_INT64 ) value, dscale, 0 );
|
|
}
|
|
else
|
|
{
|
|
sprintf( p, "%*" ISC_INT64_FORMAT "d",
|
|
field_width, ( ISC_INT64 ) value );
|
|
}
|
|
};
|
|
break;
|
|
|
|
case SQL_FLOAT:
|
|
sprintf( p, "%15g ", *( float ISC_FAR * ) ( var->sqldata ) );
|
|
break;
|
|
|
|
case SQL_DOUBLE:
|
|
sprintf( p, "%24f ", *( double ISC_FAR * ) ( var->sqldata ) );
|
|
break;
|
|
|
|
case SQL_TIMESTAMP:
|
|
isc_decode_timestamp( ( ISC_TIMESTAMP ISC_FAR * ) var->sqldata, × );
|
|
sprintf( date_s, "%04d-%02d-%02d %02d:%02d:%02d.%04lui",
|
|
times.tm_year + 1900,
|
|
times.tm_mon + 1,
|
|
times.tm_mday,
|
|
times.tm_hour,
|
|
times.tm_min,
|
|
times.tm_sec,
|
|
( ( ISC_TIMESTAMP * ) var->sqldata )->timestamp_time % 10000 );
|
|
sprintf( p, "%*s ", 24, date_s );
|
|
break;
|
|
|
|
case SQL_TYPE_DATE:
|
|
isc_decode_sql_date( ( ISC_DATE ISC_FAR * ) var->sqldata, × );
|
|
sprintf( date_s, "%04d-%02d-%02d",
|
|
times.tm_year + 1900, times.tm_mon + 1, times.tm_mday );
|
|
sprintf( p, "%*s ", 10, date_s );
|
|
break;
|
|
|
|
case SQL_TYPE_TIME:
|
|
isc_decode_sql_time( ( ISC_TIME ISC_FAR * ) var->sqldata, × );
|
|
sprintf( date_s, "%02d:%02d:%02d.%04lui",
|
|
times.tm_hour,
|
|
times.tm_min,
|
|
times.tm_sec, ( *( ( ISC_TIME * ) var->sqldata ) ) % 10000 );
|
|
sprintf( p, "%*s ", 13, date_s );
|
|
break;
|
|
|
|
case SQL_BLOB:
|
|
case SQL_ARRAY:
|
|
/* Print the blob id on blobs or arrays */
|
|
bid = *( ISC_QUAD ISC_FAR * ) var->sqldata;
|
|
sprintf( blob_s, "%08x:%08x", ( unsigned int ) bid.gds_quad_high,
|
|
( unsigned int ) bid.gds_quad_low );
|
|
sprintf( p, "%17s ", blob_s );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|