Tang Cheng | 37650ea | 2014-10-20 16:14:41 +0800 | [diff] [blame^] | 1 | #ifdef RCSID |
| 2 | static 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 | |
| 65 | static text *username = (text *) "SCOTT"; |
| 66 | static text *password = (text *) "tiger"; |
| 67 | |
| 68 | /* Define SQL statements to be used in program. */ |
| 69 | static text *insert = (text *)"INSERT INTO emp(empno, ename, job, sal, deptno)\ |
| 70 | VALUES (:empno, :ename, :job, :sal, :deptno)"; |
| 71 | static text *seldept = (text *)"SELECT dname FROM dept WHERE deptno = :1"; |
| 72 | static text *maxemp = (text *)"SELECT NVL(MAX(empno), 0) FROM emp"; |
| 73 | static text *selemp = (text *)"SELECT ename, job FROM emp"; |
| 74 | |
| 75 | static OCIEnv *envhp; |
| 76 | static OCIError *errhp; |
| 77 | |
| 78 | static void checkerr(/*_ OCIError *errhp, sword status _*/); |
| 79 | static void cleanup(/*_ void _*/); |
| 80 | static void myfflush(/*_ void _*/); |
| 81 | int main(/*_ int argc, char *argv[] _*/); |
| 82 | |
| 83 | static sword status; |
| 84 | |
| 85 | int main(argc, argv) |
| 86 | int argc; |
| 87 | char *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 | |
| 385 | void checkerr(errhp, status) |
| 386 | OCIError *errhp; |
| 387 | sword 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 | */ |
| 428 | void cleanup() |
| 429 | { |
| 430 | if (envhp) |
| 431 | (void) OCIHandleFree((dvoid *) envhp, OCI_HTYPE_ENV); |
| 432 | return; |
| 433 | } |
| 434 | |
| 435 | |
| 436 | void myfflush() |
| 437 | { |
| 438 | eb1 buf[50]; |
| 439 | |
| 440 | fgets((char *) buf, 50, stdin); |
| 441 | } |
| 442 | |
| 443 | |
| 444 | /* end of file cdemo81.c */ |
| 445 | |