home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1999 May
/
PCWorld_1999-05_cd.bin
/
software
/
Vyzkuste
/
inprise
/
INTRBASE_55
/
EXAMPLES
/
API
/
DYNFULL.E
< prev
next >
Wrap
Text File
|
1998-10-18
|
7KB
|
380 lines
/*
* Program type: Embedded Dynamic SQL
*
* Description:
* This program prompts for and executes unknown SQL statements.
*/
#include "example.h"
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <ibase.h>
#include "align.h"
#define MAXLEN 1024
#define EOF -1
void process_statement PROTO((XSQLDA **sqlda, char *query));
void print_column PROTO((XSQLVAR *var));
int get_statement PROTO((char *buf));
typedef struct vary {
short vary_length;
char vary_string [1];
} VARY;
EXEC SQL
SET DATABASE db = COMPILETIME "employee.gdb";
int main(ARG(int, argc), ARG(char **, argv))
ARGLIST(int argc)
ARGLIST(char **argv)
{
char query[MAXLEN];
XSQLDA *sqlda;
char db_name[128];
if (argc < 2)
{
printf("Enter the database name: ");
gets(db_name);
}
else
strcpy(db_name, *(++argv));
EXEC SQL
SET TRANSACTION;
EXEC SQL
CONNECT :db_name AS db;
if (SQLCODE)
{
printf("Could not open database %s\n", db_name);
return(1);
}
EXEC SQL
COMMIT;
/*
* Allocate enough space for 20 fields.
* If more fields get selected, re-allocate SQLDA later.
*/
sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (20));
sqlda->sqln = 20;
sqlda->version = 1;
/*
* Process SQL statements.
*/
while (get_statement(query))
{
process_statement(&sqlda, query);
}
EXEC SQL
DISCONNECT db;
return(0);
}
void process_statement(ARG(XSQLDA ISC_FAR * ISC_FAR *, sqldap),
ARG(char ISC_FAR *, query))
ARGLIST(XSQLDA **sqldap)
ARGLIST(char *query)
{
long buffer[MAXLEN];
XSQLVAR *var;
XSQLDA *sqlda;
short num_cols, i;
short length, alignment, type, offset;
sqlda = *sqldap;
EXEC SQL
WHENEVER SQLERROR GO TO Error;
/* Start transaction only when needed. */
if ( !gds__trans )
{
EXEC SQL
SET TRANSACTION;
}
EXEC SQL
PREPARE q INTO SQL DESCRIPTOR sqlda FROM :query;
EXEC SQL
DESCRIBE q INTO SQL DESCRIPTOR sqlda;
/*
* Execute a non-select statement.
*/
if (!sqlda->sqld)
{
EXEC SQL
EXECUTE q;
return ;
}
/*
* Process select statements.
*/
num_cols = sqlda->sqld;
/* Need more room. */
if (sqlda->sqln < num_cols)
{
free(sqlda);
sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH (num_cols));
sqlda->sqln = num_cols;
sqlda->sqld = num_cols;
sqlda->version = 1;
EXEC SQL
DESCRIBE q INTO SQL DESCRIPTOR sqlda;
num_cols = sqlda->sqld;
}
/* Open the cursor. */
EXEC SQL
DECLARE c CURSOR FOR q;
EXEC SQL
OPEN c;
/*
* Set up SQLDA.
*/
for (var = sqlda->sqlvar, offset = 0, i = 0; i < num_cols; var++, i++)
{
length = alignment = var->sqllen;
type = var->sqltype & ~1;
if (type == SQL_TEXT)
alignment = 1;
else if (type == SQL_VARYING)
{
length += sizeof (short);
alignment = sizeof (short);
}
offset = ALIGN (offset, alignment);
var->sqldata = (char*) buffer + offset;
offset += length;
offset = ALIGN (offset, sizeof (short));
var->sqlind = (short*) ((char*) buffer + offset);
offset += sizeof (short);
}
/*
* Print rows.
*/
while (SQLCODE == 0)
{
EXEC SQL
FETCH c USING SQL DESCRIPTOR sqlda;
if (SQLCODE == 100)
break;
for (i = 0; i < num_cols; i++)
{
print_column(&sqlda->sqlvar[i]);
}
printf("\n");
}
EXEC SQL
CLOSE c;
EXEC SQL
COMMIT;
return;
Error:
EXEC SQL
WHENEVER SQLERROR CONTINUE;
printf("Statement failed. SQLCODE = %d\n", SQLCODE);
isc_print_status(gds__status);
}
/*
* Print column's data.
*/
void print_column(ARG(XSQLVAR ISC_FAR *, var))
ARGLIST(XSQLVAR *var)
{
short dtype;
char data[MAXLEN], *p;
char blob_s[20], date_s[20];
VARY *vary;
short len; struct tm times;
ISC_QUAD bid;
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;
break;
case SQL_LONG:
len = 10;
break;
case SQL_FLOAT:
case SQL_DOUBLE:
len = 22;
break;
case SQL_DATE:
len = 10;
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:
vary = (VARY*) var->sqldata;
vary->vary_string[vary->vary_length] = '\0';
sprintf(p, "%-*s ", var->sqllen, vary->vary_string);
break;
case SQL_SHORT:
sprintf(p, "%6d ", *(short *) (var->sqldata));
break;
case SQL_LONG:
#if !(defined __osf__ && defined __alpha)
sprintf(p, "%10d ", *(long *) (var->sqldata));
#else
sprintf(p, "%10d ", *(int *) (var->sqldata));
#endif
break;
case SQL_FLOAT:
sprintf(p, "%22f ", *(float *) (var->sqldata));
break;
case SQL_DOUBLE:
/* Detect numeric/decimal scale and handle format */
if (var->sqlscale)
sprintf(p, "%22.*f ", -var->sqlscale,
*(double *) (var->sqldata));
else
sprintf(p, "%22f ",
*(double *) (var->sqldata));
break;
case SQL_DATE:
isc_decode_date((ISC_QUAD *)var->sqldata, ×);
sprintf(date_s, "%2d/%d/%2d",
times.tm_mday, times.tm_mon+1, times.tm_year);
sprintf(p, "%*s ", 10, date_s);
break;
case SQL_BLOB:
case SQL_ARRAY:
bid = *(ISC_QUAD *) var->sqldata;
sprintf(blob_s, "%x:%x", bid.gds_quad_high, bid.gds_quad_low);
sprintf(p, "%17s ", blob_s);
break;
default:
break;
}
}
while (*p)
{
putchar(*p++);
}
}
/*
* Prompt for and get input.
* Statements are terminated by a semicolon.
*/
int get_statement(ARG(char ISC_FAR *, buf))
ARGLIST(char *buf)
{
short c;
char *p;
int cnt;
p = buf;
cnt = 0;
printf("SQL> ");
for (;;)
{
if ((c = getchar()) == EOF)
return 0;
if (c == '\n')
{
/* accept "quit" or "exit" to terminate application */
if (!strncmp(buf, "exit;", 5))
return 0;
if (!strncmp(buf, "quit;", 5))
return 0;
/* Search back through any white space looking for ';'.*/
while (cnt && isspace(*(p - 1)))
{
p--;
cnt--;
}
if (*(p - 1) == ';')
{
*p++ = '\0';
return 1;
}
*p++ = ' ';
printf("CON> ");
}
else
*p++ = c;
cnt++;
}
}