blob: f9db75470c85b5d6f3a9ef20bf4967a2475a46c3 [file] [log] [blame]
Tang Cheng03c0b0a2015-01-12 11:19:45 +08001#ifdef RCSID
2static char *RCSid =
3 "$Header: cdemo81.c 14-apr-2006.10:55:52 lburgess Exp $ ";
4#endif /* RCSID */
5
6/* Copyright (c) 1996, 2006, Oracle. All rights reserved.
7*/
8
9/*
10
11 NAME
12 cdemo81.c - Basic OCI V8 functionality
13
14 DESCRIPTION
15
16 * An example program which adds new employee
17 * records to the personnel data base. Checking
18 * is done to insure the integrity of the data base.
19 * The employee numbers are automatically selected using
20 * the current maximum employee number as the start.
21 *
22 * The program queries the user for data as follows:
23 *
24 * Enter employee name:
25 * Enter employee job:
26 * Enter employee salary:
27 * Enter employee dept:
28 *
29 * The program terminates if return key (CR) is entered
30 * when the employee name is requested.
31 *
32 * If the record is successfully inserted, the following
33 * is printed:
34 *
35 * "ename" added to department "dname" as employee # "empno"
36
37 Demonstrates creating a connection, a session and executing some SQL.
38 Also shows the usage of allocating memory for application use which has the
39 life time of the handle.
40
41 MODIFIED (MM/DD/YY)
42 lburgess 04/14/06 - lowercase passwords
43 aliu 04/21/06 - use OCIEnvCreate and exit if it fails
44 mjaeger 07/14/99 - bug 808870: OCCS: convert tabs, no long lines
45 dchatter 10/14/98 - add the usage of xtrmemsz and usrmempp
46 azhao 06/23/97 - Use OCIBindByPos, OCIBindByName; clean up
47 echen 12/17/96 - OCI beautification
48 dchatter 07/18/96 - delete spurious header files
49 dchatter 07/15/96 - hda is a ub4 array to prevent bus error
50 mgianata 06/17/96 - change ociisc() to OCISessionBegin()
51 aroy 04/26/96 - change OCITransCommitt -> OCITransCommit
52 slari 04/24/96 - use OCITransCommitt
53 aroy 02/21/96 - fix bug in get descriptor handle call
54 lchidamb 02/20/96 - cdemo81.c converted for v8 OCI
55 lchidamb 02/20/96 - Creation
56
57*/
58
59
60#include <stdio.h>
61#include <stdlib.h>
62#include <string.h>
63#include <oci.h>
64
65static text *username = (text *) "SCOTT";
66static text *password = (text *) "tiger";
67
68/* Define SQL statements to be used in program. */
69static text *insert = (text *)"INSERT INTO emp(empno, ename, job, sal, deptno)\
70 VALUES (:empno, :ename, :job, :sal, :deptno)";
71static text *seldept = (text *)"SELECT dname FROM dept WHERE deptno = :1";
72static text *maxemp = (text *)"SELECT NVL(MAX(empno), 0) FROM emp";
73static text *selemp = (text *)"SELECT ename, job FROM emp";
74
75static OCIEnv *envhp;
76static OCIError *errhp;
77
78static void checkerr(/*_ OCIError *errhp, sword status _*/);
79static void cleanup(/*_ void _*/);
80static void myfflush(/*_ void _*/);
81int main(/*_ int argc, char *argv[] _*/);
82
83static sword status;
84
85int main(argc, argv)
86int argc;
87char *argv[];
88{
89
90 sword empno, sal, deptno;
91 sword len, len2, rv, dsize, dsize2;
92 sb4 enamelen = 10;
93 sb4 joblen = 9;
94 sb4 deptlen = 14;
95 sb2 sal_ind, job_ind;
96 sb2 db_type, db2_type;
97 sb1 name_buf[20], name2_buf[20];
98 text *cp, *ename, *job, *dept;
99
100 sb2 ind[2]; /* indicator */
101 ub2 alen[2]; /* actual length */
102 ub2 rlen[2]; /* return length */
103
104 OCIDescribe *dschndl1 = (OCIDescribe *) 0,
105 *dschndl2 = (OCIDescribe *) 0,
106 *dschndl3 = (OCIDescribe *) 0;
107
108 OCISession *authp = (OCISession *) 0;
109 OCIServer *srvhp;
110 OCISvcCtx *svchp;
111 OCIStmt *inserthp,
112 *stmthp,
113 *stmthp1;
114 OCIDefine *defnp = (OCIDefine *) 0;
115
116 OCIBind *bnd1p = (OCIBind *) 0; /* the first bind handle */
117 OCIBind *bnd2p = (OCIBind *) 0; /* the second bind handle */
118 OCIBind *bnd3p = (OCIBind *) 0; /* the third bind handle */
119 OCIBind *bnd4p = (OCIBind *) 0; /* the fourth bind handle */
120 OCIBind *bnd5p = (OCIBind *) 0; /* the fifth bind handle */
121 OCIBind *bnd6p = (OCIBind *) 0; /* the sixth bind handle */
122
123 sword errcode = 0;
124
125 errcode = OCIEnvCreate((OCIEnv **) &envhp, (ub4) OCI_DEFAULT,
126 (dvoid *) 0, (dvoid * (*)(dvoid *,size_t)) 0,
127 (dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
128 (void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0);
129
130 if (errcode != 0) {
131 (void) printf("OCIEnvCreate failed with errcode = %d.\n", errcode);
132 exit(1);
133 }
134
135 (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, OCI_HTYPE_ERROR,
136 (size_t) 0, (dvoid **) 0);
137
138 /* server contexts */
139 (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, OCI_HTYPE_SERVER,
140 (size_t) 0, (dvoid **) 0);
141
142 (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &svchp, OCI_HTYPE_SVCCTX,
143 (size_t) 0, (dvoid **) 0);
144
145 (void) OCIServerAttach( srvhp, errhp, (text *)"", strlen(""), 0);
146
147 /* set attribute server context in the service context */
148 (void) OCIAttrSet( (dvoid *) svchp, OCI_HTYPE_SVCCTX, (dvoid *)srvhp,
149 (ub4) 0, OCI_ATTR_SERVER, (OCIError *) errhp);
150
151 (void) OCIHandleAlloc((dvoid *) envhp, (dvoid **)&authp,
152 (ub4) OCI_HTYPE_SESSION, (size_t) 0, (dvoid **) 0);
153
154 (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
155 (dvoid *) username, (ub4) strlen((char *)username),
156 (ub4) OCI_ATTR_USERNAME, errhp);
157
158 (void) OCIAttrSet((dvoid *) authp, (ub4) OCI_HTYPE_SESSION,
159 (dvoid *) password, (ub4) strlen((char *)password),
160 (ub4) OCI_ATTR_PASSWORD, errhp);
161
162 checkerr(errhp, OCISessionBegin ( svchp, errhp, authp, OCI_CRED_RDBMS,
163 (ub4) OCI_DEFAULT));
164
165 (void) OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX,
166 (dvoid *) authp, (ub4) 0,
167 (ub4) OCI_ATTR_SESSION, errhp);
168
169 checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp,
170 OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
171
172 checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp1,
173 OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0));
174
175 /* Retrieve the current maximum employee number. */
176 checkerr(errhp, OCIStmtPrepare(stmthp, errhp, maxemp,
177 (ub4) strlen((char *) maxemp),
178 (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
179
180 /* bind the input variable */
181 checkerr(errhp, OCIDefineByPos(stmthp, &defnp, errhp, 1, (dvoid *) &empno,
182 (sword) sizeof(sword), SQLT_INT, (dvoid *) 0, (ub2 *)0,
183 (ub2 *)0, OCI_DEFAULT));
184
185 /* execute and fetch */
186 if (status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
187 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT))
188 {
189 if (status == OCI_NO_DATA)
190 empno = 10;
191 else
192 {
193 checkerr(errhp, status);
194 cleanup();
195 return OCI_ERROR;
196 }
197 }
198
199
200 /*
201 * When we bind the insert statement we also need to allocate the storage
202 * of the employee name and the job description.
203 * Since the lifetime of these buffers are the same as the statement, we
204 * will allocate it at the time when the statement handle is allocated; this
205 * will get freed when the statement disappears and there is less
206 * fragmentation.
207 *
208 * sizes required are enamelen+2 and joblen+2 to allow for \n and \0
209 *
210 */
211
212
213 checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &inserthp,
214 OCI_HTYPE_STMT, (size_t) enamelen + 2 + joblen + 2,
215 (dvoid **) &ename));
216 job = (text *) (ename+enamelen+2);
217
218
219 checkerr(errhp, OCIStmtPrepare(stmthp, errhp, insert,
220 (ub4) strlen((char *) insert),
221 (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
222
223 checkerr(errhp, OCIStmtPrepare(stmthp1, errhp, seldept,
224 (ub4) strlen((char *) seldept),
225 (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT));
226
227
228 /* Bind the placeholders in the INSERT statement. */
229 if ((status = OCIBindByName(stmthp, &bnd1p, errhp, (text *) ":ENAME",
230 -1, (dvoid *) ename,
231 enamelen+1, SQLT_STR, (dvoid *) 0,
232 (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
233 (status = OCIBindByName(stmthp, &bnd2p, errhp, (text *) ":JOB",
234 -1, (dvoid *) job,
235 joblen+1, SQLT_STR, (dvoid *) &job_ind,
236 (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
237 (status = OCIBindByName(stmthp, &bnd3p, errhp, (text *) ":SAL",
238 -1, (dvoid *) &sal,
239 (sword) sizeof(sal), SQLT_INT, (dvoid *) &sal_ind,
240 (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
241 (status = OCIBindByName(stmthp, &bnd4p, errhp, (text *) ":DEPTNO",
242 -1, (dvoid *) &deptno,
243 (sword) sizeof(deptno), SQLT_INT, (dvoid *) 0,
244 (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)) ||
245 (status = OCIBindByName(stmthp, &bnd5p, errhp, (text *) ":EMPNO",
246 -1, (dvoid *) &empno,
247 (sword) sizeof(empno), SQLT_INT, (dvoid *) 0,
248 (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT)))
249 {
250 checkerr(errhp, status);
251 cleanup();
252 return OCI_ERROR;
253 }
254
255 /* Bind the placeholder in the "seldept" statement. */
256 if (status = OCIBindByPos(stmthp1, &bnd6p, errhp, 1,
257 (dvoid *) &deptno, (sword) sizeof(deptno),SQLT_INT,
258 (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT))
259 {
260 checkerr(errhp, status);
261 cleanup();
262 return OCI_ERROR;
263 }
264
265 /* Allocate the dept buffer now that you have length. */
266 /* the deptlen should eventually get from dschndl3. */
267 deptlen = 14;
268 dept = (text *) malloc((size_t) deptlen + 1);
269
270 /* Define the output variable for the select-list. */
271 if (status = OCIDefineByPos(stmthp1, &defnp, errhp, 1,
272 (dvoid *) dept, deptlen+1, SQLT_STR,
273 (dvoid *) 0, (ub2 *) 0, (ub2 *) 0, OCI_DEFAULT))
274 {
275 checkerr(errhp, status);
276 cleanup();
277 return OCI_ERROR;
278 }
279
280 for (;;)
281 {
282 /* Prompt for employee name. Break on no name. */
283 printf("\nEnter employee name (or CR to EXIT): ");
284 fgets((char *) ename, (int) enamelen+1, stdin);
285 cp = (text *) strchr((char *) ename, '\n');
286 if (cp == ename)
287 {
288 printf("Exiting... ");
289 cleanup();
290 return OCI_SUCCESS;
291 }
292 if (cp)
293 *cp = '\0';
294 else
295 {
296 printf("Employee name may be truncated.\n");
297 myfflush();
298 }
299 /* Prompt for the employee's job and salary. */
300 printf("Enter employee job: ");
301 job_ind = 0;
302 fgets((char *) job, (int) joblen + 1, stdin);
303 cp = (text *) strchr((char *) job, '\n');
304 if (cp == job)
305 {
306 job_ind = -1; /* make it NULL in table */
307 printf("Job is NULL.\n");/* using indicator variable */
308 }
309 else if (cp == 0)
310 {
311 printf("Job description may be truncated.\n");
312 myfflush();
313 }
314 else
315 *cp = '\0';
316
317 printf("Enter employee salary: ");
318 scanf("%d", &sal);
319 myfflush();
320 sal_ind = (sal <= 0) ? -2 : 0; /* set indicator variable */
321
322 /*
323 * Prompt for the employee's department number, and verify
324 * that the entered department number is valid
325 * by executing and fetching.
326 */
327 do
328 {
329 printf("Enter employee dept: ");
330 scanf("%d", &deptno);
331 myfflush();
332 if ((status = OCIStmtExecute(svchp, stmthp1, errhp, (ub4) 1, (ub4) 0,
333 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT))
334 && (status != OCI_NO_DATA))
335 {
336 checkerr(errhp, status);
337 cleanup();
338 return OCI_ERROR;
339 }
340 if (status == OCI_NO_DATA)
341 printf("The dept you entered doesn't exist.\n");
342 } while (status == OCI_NO_DATA);
343
344 /*
345 * Increment empno by 10, and execute the INSERT
346 * statement. If the return code is 1 (duplicate
347 * value in index), then generate the next
348 * employee number.
349 */
350 empno += 10;
351 if ((status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
352 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT))
353 && status != 1)
354 {
355 checkerr(errhp, status);
356 cleanup();
357 return OCI_ERROR;
358 }
359 while (status == 1)
360 {
361 empno += 10;
362 if ((status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
363 (CONST OCISnapshot *) NULL, (OCISnapshot *) NULL, OCI_DEFAULT))
364 && status != 1)
365 {
366 checkerr(errhp, status);
367 cleanup();
368 return OCI_ERROR;
369 }
370 } /* end for (;;) */
371
372 /* Commit the change. */
373 if (status = OCITransCommit(svchp, errhp, 0))
374 {
375 checkerr(errhp, status);
376 cleanup();
377 return OCI_ERROR;
378 }
379 printf("\n\n%s added to the %s department as employee number %d\n",
380 ename, dept, empno);
381 }
382}
383
384
385void checkerr(errhp, status)
386OCIError *errhp;
387sword status;
388{
389 text errbuf[512];
390 sb4 errcode = 0;
391
392 switch (status)
393 {
394 case OCI_SUCCESS:
395 break;
396 case OCI_SUCCESS_WITH_INFO:
397 (void) printf("Error - OCI_SUCCESS_WITH_INFO\n");
398 break;
399 case OCI_NEED_DATA:
400 (void) printf("Error - OCI_NEED_DATA\n");
401 break;
402 case OCI_NO_DATA:
403 (void) printf("Error - OCI_NODATA\n");
404 break;
405 case OCI_ERROR:
406 (void) OCIErrorGet((dvoid *)errhp, (ub4) 1, (text *) NULL, &errcode,
407 errbuf, (ub4) sizeof(errbuf), OCI_HTYPE_ERROR);
408 (void) printf("Error - %.*s\n", 512, errbuf);
409 break;
410 case OCI_INVALID_HANDLE:
411 (void) printf("Error - OCI_INVALID_HANDLE\n");
412 break;
413 case OCI_STILL_EXECUTING:
414 (void) printf("Error - OCI_STILL_EXECUTE\n");
415 break;
416 case OCI_CONTINUE:
417 (void) printf("Error - OCI_CONTINUE\n");
418 break;
419 default:
420 break;
421 }
422}
423
424
425/*
426 * Exit program with an exit code.
427 */
428void cleanup()
429{
430 if (envhp)
431 (void) OCIHandleFree((dvoid *) envhp, OCI_HTYPE_ENV);
432 return;
433}
434
435
436void myfflush()
437{
438 eb1 buf[50];
439
440 fgets((char *) buf, 50, stdin);
441}
442
443
444/* end of file cdemo81.c */
445