1 /*
2 	sybbind.c	High level Sybase row loading and binding support
3 
4 	MODULE:	sybbind
5 	FILES:	sybbind.c (this one) and sybbind.h.
6 
7 	This module provides a high-level interface to the Sybase procedures
8 	for binding rows to C variables and for loading rows in form the
9 	database.  These procedures permit a single procedure call to bind
10 	many variables in a single call.  The SybaseLoad procedure call
11 	adds row retrieval as well.  This reduce the amounts of coding
12 	detail required by lumping the dbbind() and dbnextresults() calls
13 	into a single call with only a single return code to check.
14 
15 	Note:	This module was adapted from the module of the same
16 		name from the GenInfo Backbone database project.  It
17 		had to be slightly modified to meet Medline project
18 		coding conventions.  (module nomenclature)
19 
20 	Edit History:
21 	    25 July 1991 - Rand S. Huntzinger, NLM/NCBI
22 		Modified to comply with Medline project coding conventions.
23 
24 	Original version: circa 1989-1990, Rand S. Huntzinger, NLM/NCBI
25 *
26 *
27 * RCS Modification History:
28 * $Log: sybbind.c,v $
29 * Revision 6.0  1997/08/25 18:37:01  madden
30 * Revision changed to 6.0
31 *
32 * Revision 1.2  1995/05/17 17:56:03  epstein
33 * add RCS log revision history
34 *
35 */
36 
37 #include <stdarg.h>
38 #include "sybase.h"
39 #include "sybbind.h"
40 
41 /*
42 	VSybaseBind		Bind Sybase Fields to Variables (from vector)
43 
44 	This procedure takes a vector of arguments which originated
45 	from a variable argument list from a calling procedure and uses
46 	it to call dbbind() several times to bind variables for loading
47 	from a Sybase database on the next dbgetnextrow() call.
48 
49 	Interpretation of the argument vector:
50 
51 	The argument vector contains groups of four parameters defined
52 	as the last four parameters in the Sybase dbbind procedure.  These
53 	parameters are:
54 
55 	    Field		Contents
56 	    =====		========
57 	    field_no		The field number.  This must be a positive
58 				integer.  When this value is zero, we
59 				assume we've reached the end of the list.
60 
61 	    type		The binding type of the field (see dbdind()
62 				documentation for valid values).
63 
64 	    length		The length of the field.  Zero can be used
65 				if the length is implied by the type or
66 				the buffer used to hold the input is known
67 				to be long enough to hold the data.
68 
69 	    varptr		A pointer to the location where the data
70 				retrieved from the database is to be
71 				stored.  It must be at least length bytes
72 				long, or long enough to hold this type.
73 
74 	Note that we terminate processing when field_no is set to zero.
75 	Thus, the calling program should make sure that a zero argument
76 	is passed after the last valid group.
77 
78 	Parameters:
79 
80 	    dbproc		A pointer to the Sybase database process.
81 
82 	    args		The argument vector which is interpreted
83 				as given above.
84 
85 	Returns:
86 
87 	    SUCCEED if all binds are successful, or the return code of
88 	    first dbbind() call which does not return SUCCEED (ie. which
89 	    fails).
90 */
91 
92 /*
93 *		VSybaseBind(dbproc,args)
94 */
VSybaseBind(dbproc,args)95 RETCODE	VSybaseBind( dbproc, args )
96 	DBPROCESS	*dbproc;
97 	va_list		 args;
98 {
99     int		 field_no;
100     int		 type;
101     int		 length;
102     char	*varptr;
103     RETCODE	 status;
104 
105     /* Assume sets of field#, type, length, variable */
106 
107     for( status = SUCCEED; status == SUCCEED; )
108     {
109 	/* When we get to a zero field code, we're at the end of
110 	   the variable length input list */
111 
112 	field_no = va_arg( args, int );
113 	if( field_no == 0 ) break;
114 
115 	/* Load the other arguments */
116 
117 	type = va_arg( args, int );
118 	length = va_arg( args, int );
119 	varptr = va_arg( args, char *);	/* Must be a pointer! */
120 
121 	/* Bind us up */
122 
123 	status = dbbind(dbproc, field_no, type, length, varptr );
124     }
125 
126     /* Done */
127 
128    return( status );
129 }
130 
131 
132 /*
133 	SybaseBind		Bind Sybase Fields to Variables
134 
135 	This is a variable argument list procedure which repeatedly
136 	calls the Sybase dbbind() procedure to bind sets of parameters
137 	coded in it's variable argument list.  A single zero parameter
138 	following the last valid group terminates the list of arguments.
139 
140 	Normally, the argument list of this function is coded as a
141 	table, with arguments for a single bind on each row, and the
142 	parameters for each bind in the columns.  This simply provides
143 	a neater way of coding the binds.
144 
145 	Interpretation of the argument list:
146 
147 	The first argument passed is a pointer to the Sybase database
148 	process where the binding is to be done.  The remaining parameters
149 	are grouped in sets of four, which are interpreted as follows:
150 
151 	    Field		Contents
152 	    =====		========
153 	    field_no		The field number.  This must be a positive
154 				integer.  When this value is zero, we
155 				assume we've reached the end of the list.
156 
157 	    type		The binding type of the field (see dbdind()
158 				documentation for valid values).
159 
160 	    length		The length of the field.  Zero can be used
161 				if the length is implied by the type or
162 				the buffer used to hold the input is known
163 				to be long enough to hold the data.
164 
165 	    varptr		A pointer to the location where the data
166 				retrieved from the database is to be
167 				stored.  It must be at least length bytes
168 				long, or long enough to hold this type.
169 
170 	A single zero parameter following the last valid group (which
171 	ends up as field_no == 0, terminates the argument list.
172 
173 	[NOTE:	This is simply a variable argument list wrapper for
174 		the VSybaseBind() procedure.]
175 
176 	Returns:
177 
178 	    SUCCEED if all binds are successful, or the return code of
179 	    first dbbind() call which does not return SUCCEED (ie. which
180 	    fails).
181 */
182 
183 /*
184 *		SybaseBind(DBPROCESSdbproc,...)
185 */
SybaseBind(DBPROCESS * dbproc,...)186 RETCODE	SybaseBind( DBPROCESS *dbproc, ... )
187 {
188     va_list	 args;
189     RETCODE	 status;
190 
191     /* Extract the argument */
192 
193     va_start( args, dbproc );
194 
195     /* Use the vector routine to handle everything else */
196 
197     status = VSybaseBind( dbproc, args );
198     va_end( args );
199 
200     /* Done */
201 
202    return( status );
203 
204 }
205 
206 
207 /*
208 	SybaseLoad	Bind Sybase fields to data and Load a Record
209 
210 	This procedure is identical to Sybase bind except that the
211 	dbnextrow() procedure is called after binding to load the
212 	bound variables from a row in the database.
213 
214 	Parameters:
215 
216 	    Identical to SybaseBind, see the comment on that procedure
217 	    (above) for details.
218 
219 	Returns:
220 
221 	    Identical to Sybase bind except that the return code is
222 	    the value returned from the dbnextrow() call unless one of
223 	    the bind operations fail.  In that case, the return code
224 	    is the value returned by the failed bind (should be FAIL).
225 */
226 
227 /*
228 *		SybaseLoad(DBPROCESSdbproc,...)
229 */
SybaseLoad(DBPROCESS * dbproc,...)230 RETCODE	SybaseLoad( DBPROCESS *dbproc, ... )
231 {
232     va_list	 args;
233     RETCODE	 status;
234 
235     /* Extract the 'dbproc' argument */
236 
237     va_start( args, dbproc );
238 
239     /* Use the vector routine to handle everything else */
240 
241     status = VSybaseBind( dbproc, args );
242     va_end( args );
243     if( status != SUCCEED ) return( status );
244 
245     /* Load a row from the database and exit */
246 
247    return( dbnextrow( dbproc ) );
248 
249 }
250