/* sybintfc.c Execute a Sybase command using a printf-style format for command building MODULE: sybintf FILES: sybintf.c (this one) and sybintf.h. This module contains functions which permit a printf-style format to be used for building and executing Sybase queries. This avoids having the application have to piece the command together from a bunch of little pieces using multiple calls to dbcmd. Note: This package was adapted for the Medline project from the same module in the GenInfo Backbone database project. Some minor changes had to be made to conform to Medline style conventions. Dependencies: voutf.c A package supporting printf-style formats with output directed via function calls instead of to a file or memory buffer. Edit history: 25 July 1991 - Rand S. Huntzinger Moved to Medline project area and adapted the code to meet Medline project requirements. 5 April 1991 - Added a print query debugging option. Original Implementation: 7 Dec 89 - Rand S. Huntzinger. * * * RCS Modification History: * $Log: sybintfc.c,v $ * Revision 6.0 1997/08/25 18:37:05 madden * Revision changed to 6.0 * * Revision 1.2 1995/05/17 17:56:08 epstein * add RCS log revision history * */ #include #include #include "sybintfc.h" #include "voutf.h" /* These global variables are used for debugging. You can set them to cause queries to be written to a file. */ FILE *SybaseQueryPrintFile = stdout; /* Default = standard output */ int SybaseQueryPrintCount = 0; /* Default, don't print! */ /* These variables are used internally by the voutf processing procedure */ static DBPROCESS *dbproc; static RETCODE status; /* build_sybase_command Voutf string collection procedure. This procedure collects the little strings generated by the voutf function in interpreting it's format and directs them into the dbcmd() procedure for insertion into the Sybase command. Assumptions: * The calling program has set the static variable "dbproc" to reference the DBPROCESS to be used for building the command. * The static variable "status" will return the status of the last call to this procedure when voutf exits. If voutf exits with an error, this will contain the error status returned by dbcmd(). Parameters: (defined by voutf protocol) s The string coming in from voutf(). Returns: (defined by voutf protocol) TRUE (non-zero) if the command failed, FALSE (zero) if the command was successful. */ /* * intbuild_sybase_command(chars) */ static int build_sybase_command( char *s ) { /* Add the string to the command */ return( (status = dbcmd( dbproc, s )) != SUCCEED ); } /* * DumpSybaseCommand(DBPROCESSdbproc,FILEfd) */ void DumpSybaseCommand( DBPROCESS *dbproc, FILE *fd ) { char buffer[61]; int len = dbstrlen( dbproc ); char *stub = "Query:"; int index = 0; int copy_count; register char *p; /* Dump the query out to SybaseQueryPrintFile */ while( index < len ) { copy_count = (( len - index ) > (sizeof(buffer) - 1)) ? (sizeof(buffer) - 1) : (len - index); dbstrcpy( dbproc, index, copy_count , buffer ); for(p=buffer; *p; p++) if(isspace(*p)) *p = ' '; fprintf(fd, "%-12.12s || %s ||\n", stub, buffer); stub = ""; index += copy_count; } fprintf(fd, "\n" ); } /* VExtendSybaseCommand Add to a Sybase command from a vector This procedure extends the Sybase command buffer using a format and a argument list pointer (usually passed by a variable argument list calling procedure). Parameters: db The Sybase database process to be used. fmt A printf-style format for generating this piece of the command. args An argument vector containing the arguments which are to be interpreted according to the format to generate this piece of the command string. Returns: Zero if successful, non-zero on an error. */ /* * VExtendSybaseCommand(DBPROCESSdb,charfmt,voidargs) */ RETCODE VExtendSybaseCommand( DBPROCESS *db, char *fmt, void *args ) { /* Load the command into the command buffer */ dbproc = db; (void) voutf( build_sybase_command, fmt, args ); /* Done */ return( status ); } /* VLoadSybaseCommand Load a Sybase command from a vector This procedure loads the Sybase command buffer using a format and a argument list pointer (usually passed by a variable argument list calling procedure). This is identical to the VExtendSybaseCommand procedure except any existing Sybase command is cleared out before loading the new text. Parameters: db The Sybase database process to be used. fmt A printf-style format for generating this piece of the command. args An argument vector containing the arguments which are to be interpreted according to the format to generate this piece of the command string. Returns: Zero if successful, non-zero on an error. */ /* * VLoadSybaseCommand(DBPROCESSdb,charfmt,voidargs) */ RETCODE VLoadSybaseCommand( DBPROCESS *db, char *fmt, void *args ) { RETCODE status; /* Reset the database channel */ dbproc = db; if( (status = dbcancel( dbproc )) != SUCCEED ) return( status ); /* Load the command into the command buffer */ (void) voutf( build_sybase_command, fmt, args ); /* Done */ return( status ); } /* LoadSybaseCommand Load a Sybase command via a format. This procedure loads the Sybase command buffer using a variable argument list containing a format which is used to generate the command using printf-style conversions. Parameters: db The Sybase database process to be used. fmt A printf-style format for generating this piece of the command. ... The remaining arguments are interpreted according to the format (fmt) using printf conventions to generate the string to be loaded into the Sybase command buffer. Returns: Zero if successful, non-zero on an error. */ /* * LoadSybaseCommand(DBPROCESSdbproc,charfmt,...) */ RETCODE LoadSybaseCommand( DBPROCESS *dbproc, char *fmt, ... ) { va_list args; /* Extract the fixed parameters */ va_start( args, char *fmt ); /* Put the command in the buffer */ (void) VLoadSybaseCommand( dbproc, fmt, args ); va_end( args ); /* Done */ return( status ); } /* ExtendSybaseCommand Add to a Sybase command via a format. This procedure extends the Sybase command buffer using a variable argument list containing a format which is used to generate the command using printf-style conversions. This procedure is identical to LaodSybaseCommand execept that the string generated here is appended to the existing Sybase command buffer instead of replacing it. Parameters: db The Sybase database process to be used. fmt A printf-style format for generating this piece of the command. ... The remaining arguments are interpreted according to the format (fmt) using printf conventions to generate the string to be loaded into the Sybase command buffer. Returns: Zero if successful, non-zero on an error. */ /* * ExtendSybaseCommand(DBPROCESSdbproc,charfmt,...) */ RETCODE ExtendSybaseCommand( DBPROCESS *dbproc, char * fmt, ... ) { va_list args; /* Extract the fixed parameters */ va_start( args, fmt ); dbproc = va_arg( args, DBPROCESS * ); fmt = va_arg( args, char * ); /* Put the command in the buffer */ (void) VExtendSybaseCommand( dbproc, fmt, args ); va_end( args ); /* Done */ return( status ); } /* ExecSybaseCommand Execute an existing Sybase command This procedure executes the command in the Sybase command buffer and returns the results of the execution. Parameters: dbproc The Sybase database process pointer. Returns: The return code of dbsqlexec() if it fails; otherwise, the return code of dbresults(). Basically, this should amount to SUCCEED if successful, or FAIL on an error. */ /* * ExecSybaseCommand(dbproc) */ RETCODE ExecSybaseCommand( dbproc ) DBPROCESS *dbproc; { /* Execute the query */ if((status = dbsqlexec( dbproc )) != SUCCEED) return( status ); /* If the query succeeded, see if we want to print it out */ if( SybaseQueryPrintCount != 0 ) { DumpSybaseCommand( dbproc, SybaseQueryPrintFile ); if( SybaseQueryPrintCount > 0 ) SybaseQueryPrintCount--; } /* Load the results of the command */ return( dbresults( dbproc ) ); } /* RunSybase Execute a Sybase command specified using a printf-style format and variable argument list. This procedure permits a printf-style format and variable argument list to be used to build & execute a sybase command. It performs the first three steps of the Sybase command execution process, 1) command construction using dbcmd(), 2) execution using dbseqlexec and 3) the retrieval of results using dbresults(). Parameters: (variable argument list) dbproc A pointer to an open Sybase database process record. (ie. a channel to the database) fmt The format string to be interpreted. ... The remaining arguments are interpreted according to the format given in the "fmt" argument using printf conventions. Returns: The last return code returned from Sybase. If successful, this should be SUCCEED; otherwise, it will be the status of the first step which failed. */ /* * RunSybase(DBPROCESSdbproc,charfmt,...) */ RETCODE RunSybase( DBPROCESS *dbproc, char *fmt, ... ) { va_list args; /* Extract the fixed parameters */ va_start( args, fmt ); /* Load the command */ (void) VLoadSybaseCommand( dbproc, fmt, args ); va_end( args ); if( status != SUCCEED ) return( status ); /* Execute the Sybase command */ return( ExecSybaseCommand( dbproc ) ); } /* RunSybaseCheck Count records returned by a Sybase command Executes a Sybase command and returns the number of records retrieved by the command. The data is not available. Parameters: (variable argument list) dbproc A pointer to an open Sybase database process record. (ie. a channel to the database) fmt The format string to be interpreted. ... The remaining arguments are interpreted according to the format given in the "fmt" argument using printf conventions. Returns: The number of rows retrieved or -1 on an error. */ /* * RunSybaseCheck(DBPROCESSdbproc,charfmt,...) */ int RunSybaseCheck( DBPROCESS *dbproc, char *fmt, ... ) { va_list args; int count; /* Extract the fixed parameters */ va_start( args, fmt ); dbproc = va_arg( args, DBPROCESS * ); fmt = va_arg( args, char * ); /* Load the command */ (void) VLoadSybaseCommand( dbproc, fmt, args ); va_end( args ); if( status != SUCCEED ) return( -1 ); /* Execute the Sybase command */ if( ExecSybaseCommand( dbproc ) != SUCCEED ) return( -1 ); count = DBROWS( dbproc ); (void) dbcancel( dbproc ); return( count ); }