#ifdef RCSID static char *RCSid = "$Header: cdemocor1.c 14-jul-99.12:59:24 mjaeger Exp $ "; #endif /* RCSID */ /* Copyright (c) 1995, 1999, Oracle Corporation. All rights reserved. */ /* NAME cdemocor1.c DESCRIPTION Demo COR user interface. Run cdemocor.sql bfirst. COR is a prefetching mechanism which allows for prefetching objects related to the root object in one network roundtrip thereby improving performance. This demo shows how you can use COR to improve the performance of your application. Since it may not be easy for you to track the actual network roundtrips you can turn VERIFY_COR to TRUE which lets you verify that the pin calls find the prefetched objects in the object cache and thus do not incur a n/w roundtrip. By setting VERIFY_COR to TRUE, you modify the data corresponding to the prefetched objects (in the object cache) in the server. When you access these prefetched objects on the client side, you get the ones locally cached in the object cache (and not the new modified ones in the server). MODIFIED (MM/DD/YY) mjaeger 07/14/99 - bug 808870: OCCS: convert tabs, no long lines svedala 09/09/98 - lines longer than 79 chars reformatted - bug 722491 svedala 07/02/98 - no handlealloc required for define handles tanguyen 08/19/97 - echen 06/04/97 - fix warning mesg echen 05/31/97 - Creation */ #ifndef CDEMOCOR_ORACLE #include #endif /* In order to verify that COR works set VERIFY_COR to TRUE. The code enclosed within the ifdef VERIFY_COR macro acts in the following way. Initially, we perform a complex object retrieval which should have prefetched the root object and all objects that the root object contains refs to. The code guarded by the macro is then executed. This updates the objects that were prefetched in the server. We then try to pin these objects using the PIN_ANY option. If COR had worked then the objects should already have been in the cache and therefore, would not be fetched from the server and thus should not see the changes made by the code enclosed in the VERIFY_COR macro */ #define VERIFY_COR FALSE static const text *const selref = (text *) "SELECT REF(po) from po_table po where po.po_number = 1"; static const text *const selall = (text *) "SELECT REF(po) from po_table po"; static const text *sch_name_arr[] = {(const text *)0, (const text *)0}; static ub4 sch_name_len_arr[] = {(ub4)0, (ub4)0}; static const text *type_name_arr[] = {(const text *)"PURCHASE_ORDER", (const text *)"CUSTOMER"}; static ub4 type_name_len_arr[] = {(ub4)14, (ub4)8}; static const text *version_arr[] = {(const text *)0, (const text *)0}; static ub4 version_len_arr[] = {(ub4)0, (ub4)0}; /****************************************************************************/ /* checkerr1 - checks and displays errors nested in the error handle */ void checkerr1(errhp, status, file, line) OCIError *errhp; sword status; const char *file; int line; { text errbuf[512]; sword errcode; switch (status) { case OCI_SUCCESS: break; case OCI_SUCCESS_WITH_INFO: (void) printf("Error - OCI_SUCCESS_WITH_INFO\n"); break; case OCI_NEED_DATA: (void) printf("Error - OCI_NEED_DATA\n"); break; case OCI_NO_DATA: (void) printf("Error - OCI_NO_DATA\n"); break; case OCI_ERROR: (void) OCIErrorGet ((dvoid *) errhp, (ub4) 1, (text *) NULL, (sb4 *) &errcode, errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR); (void) printf("Error - %s, file %s, line %d\n", errbuf, file, line); break; case OCI_INVALID_HANDLE: (void) printf("Error - OCI_INVALID_HANDLE\n"); break; case OCI_STILL_EXECUTING: (void) printf("Error - OCI_STILL_EXECUTE\n"); break; case OCI_CONTINUE: (void) printf("Error - OCI_CONTINUE\n"); break; default: break; } } /* COR demonstration using COR descriptors. COR descriptors contain the information about what type of refs should be followed to prefetch the objects pointed to from the root object and the depth level i.e the objects reachable from the root object by traversing l ( where l <= the depth level) number of refs */ static void demo_cor_1(envhp, svchp, stmthp, errhp) OCIEnv *envhp; OCISvcCtx *svchp; OCIStmt *stmthp; OCIError *errhp; { OCIRef *poref = (OCIRef *)0; OCIIter *itr; boolean eoc; purchase_order *po = (purchase_order *)0; purchase_order *related_po = (purchase_order *)0; customer *cust = (customer *)0; OCIDefine *defnp; OCIComplexObject *corhp, *corhp3; OCIComplexObjectComp *cordp1, *cordp3; OCIType *custtdo, *custtdo2; OCIRef *custref = (OCIRef *)0; OCIComplexObjectComp *cordp2; OCIType *po_tdo; ub4 po_size; OCIRef *po_ref = (OCIRef *)0; ub4 level = 0; ub4 mylevel; dvoid *tdo_arr[2]; dvoid *tmp; sword status = OCI_SUCCESS; OCIParam *parmp; int age, po_num; address *addr = (address *) 0; sb4 index; boolean exist; #ifdef VERIFY_COR text *stmt11 = (text *) "update cust_table set name = 'Anil' where name = 'JOHN'"; text *stmt12 = (text *) "update cust_table set name = 'Chin' where name = 'MIKE'"; text *stmt13 = (text *) "insert into the (select addr from cust_table where name='Anil') \ select 'ca', '90417', ref(x) from person_table x where name='JOHN2'"; text *stmt14 = (text *) "insert into the (select addr from cust_table where name='Chin') \ select 'ca', '90417', ref(x) from person_table x where name='JOHN2'"; #endif /* select ref to purchase order number 1 */ checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) selref, (ub4) strlen((const char *) selref), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); /* get type of purchase_order and customer to set in COR descriptor */ checkerr(errhp, OCITypeArrayByName(envhp, errhp, svchp, 2, (text **) sch_name_arr, sch_name_len_arr, (text **) type_name_arr, type_name_len_arr, (text **) version_arr, version_len_arr, OCI_DURATION_SESSION, OCI_TYPEGET_ALL, (OCIType **) tdo_arr)); po_tdo = (OCIType *)tdo_arr[0]; custtdo = (OCIType *)tdo_arr[1]; /* define purchase order REF (poref) */ checkerr(errhp, OCIDefineByPos(stmthp, &defnp, errhp, (ub4) 1, (dvoid *) 0, (sb4) 0, SQLT_REF, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIDefineObject(defnp, errhp, po_tdo, (dvoid **) &poref, &po_size, (dvoid **) 0, (ub4 *) 0)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 0, (ub4) 0, (OCISnapshot *)NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtFetch(stmthp, errhp, (ub4) 1, (ub4) OCI_FETCH_NEXT, (ub4) OCI_DEFAULT)); /*---------------------------- C O R --------------------------------*/ /* allocate COR Handle */ checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&corhp, (ub4)OCI_HTYPE_COMPLEXOBJECT, 0, (dvoid **)0)); /*---------------------------- put customer -------------------------*/ /* allocate COR descriptor for specifying prefetch */ checkerr(errhp, OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&cordp1, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, 0, (dvoid **)0)); /* specify type of objects to be prefetched; in this case 'customer' */ checkerr(errhp, OCIAttrSet((dvoid *)cordp1, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, (dvoid *)custtdo, (ub4)sizeof(dvoid *), (ub4)OCI_ATTR_COMPLEXOBJECTCOMP_TYPE, (OCIError *)errhp)); /* specify depth level for 'customer' */ level = 2; checkerr(errhp, OCIAttrSet((dvoid *)cordp1, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, (dvoid *)&level, (ub4)sizeof(ub4), (ub4)OCI_ATTR_COMPLEXOBJECTCOMP_TYPE_LEVEL, (OCIError *)errhp)); /* put COR descriptor in COR handle */ checkerr(errhp, OCIParamSet(corhp, OCI_HTYPE_COMPLEXOBJECT, errhp, cordp1, OCI_DTYPE_COMPLEXOBJECTCOMP, 1)); /*------------------------- put purchase_order ------------------------*/ /* allocate COR descriptor for specifying prefetch */ checkerr(errhp, OCIDescriptorAlloc((dvoid *)envhp, (dvoid **)&cordp2, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, 0, (dvoid **)0)); /* specify type of objects to be prefetched; in this case 'purchase order' */ checkerr(errhp, OCIAttrSet((dvoid *)cordp2, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, (dvoid *)po_tdo, (ub4)sizeof(dvoid *), (ub4)OCI_ATTR_COMPLEXOBJECTCOMP_TYPE, (OCIError *)errhp)); /* set depth level for purchase order in COR descriptor */ level = 2; checkerr(errhp, OCIAttrSet((dvoid *)cordp2, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP, (dvoid *)&level, (ub4)sizeof(ub4), (ub4)OCI_ATTR_COMPLEXOBJECTCOMP_TYPE_LEVEL, (OCIError *)errhp)); /* put COR descriptor in COR handle */ checkerr(errhp, OCIParamSet(corhp, OCI_HTYPE_COMPLEXOBJECT, errhp, cordp2, OCI_DTYPE_COMPLEXOBJECTCOMP, 2)); /* pin the purchase order - complex object retrieval should take place since we are passing in the instruction using the cor handle pointer ( corhp) */ checkerr(errhp, OCIObjectPin(envhp, errhp, poref, corhp, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&po)); /* convert the purchase order number from OCINumber to int for printing */ checkerr(errhp, OCINumberToInt(errhp, &po->po_number, sizeof(po_num), OCI_NUMBER_SIGNED, (dvoid *) &po_num)); (void) printf(" The po number is %d\n", po_num); #ifdef VERIFY_COR /* Modify the data in the server */ checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt11, (ub4) strlen((const char *) stmt11), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt12, (ub4) strlen((const char *) stmt12), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt13, (ub4) strlen((const char *) stmt13), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt14, (ub4) strlen((const char *) stmt14), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); #endif /* pin the customer (shouldn't go over the n/w since we did cor) */ /* you should see MIKE and JOHN and should not see newly inserted records if VERIFY_COR was set to true */ checkerr(errhp, OCIObjectPin(envhp, errhp, po->cust, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&cust)); (void) printf("The name is %s\n", OCIStringPtr(envhp, cust->name)); checkerr(errhp, OCINumberToInt(errhp, &cust->age, sizeof(age), OCI_NUMBER_SIGNED, (dvoid *) &age)); (void) printf(" The age is %d\n", age); (void) printf("\n---> Dump the table from the top to the bottom.\n"); /* go to the first element and print out the index */ checkerr(errhp, OCITableFirst(envhp, errhp, cust->addr, &index)); (void) printf(" The index of the first element is : %d.\n", index); /* get the first element of the collection and print out the element */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &addr, (dvoid **) 0)); (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); /* keep getting the indices of the elements and the elements themselves */ for(;!OCITableNext(envhp, errhp, index, cust->addr, &index, &exist) && exist;) { (void) printf(" The index of the next element is : %d.\n", index); /* get the next element and print it out */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &addr, (dvoid **) 0)); (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); } /* now repeat the process of getting the related purchase orders and printing them out */ /* pin the related purchase_order (shouldn't go over the n/w) */ checkerr(errhp, OCIObjectPin(envhp, errhp, po->related_orders, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&related_po)); /* pin the customer (shouldn't go over the n/w) */ checkerr(errhp, OCIObjectPin(envhp, errhp, related_po->cust, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&cust)); (void) printf("The name is %s\n", OCIStringPtr(envhp, cust->name)); checkerr(errhp, OCINumberToInt(errhp, &cust->age, sizeof(age), OCI_NUMBER_SIGNED, (dvoid *) &age)); (void) printf(" The age is %d\n", age); (void) printf("\n---> Dump the table from the top to the bottom.\n"); /* go to the first element and print out the index */ checkerr(errhp, OCITableFirst(envhp, errhp, cust->addr, &index)); (void) printf(" The index of the first element is : %d.\n", index); /* print out the element */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &addr, (dvoid **) 0)); (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); for(;!OCITableNext(envhp, errhp, index, cust->addr, &index, &exist) && exist;) { (void) printf(" The index of the next element is : %d.\n", index); /* print out the element */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &addr, (dvoid **) 0)); (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); } /* We do not need anything in the cache anymore, so free the cache. This will unpin and free all objects */ checkerr(errhp, OCICacheFree(envhp, errhp, svchp)); /* free COR descriptor and COR handle */ checkerr(errhp, OCIDescriptorFree((dvoid *)cordp1, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP)); checkerr(errhp, OCIDescriptorFree((dvoid *)cordp2, (ub4)OCI_DTYPE_COMPLEXOBJECTCOMP)); checkerr(errhp, OCIHandleFree((dvoid *)corhp, (ub4)OCI_HTYPE_COMPLEXOBJECT)); } /* COR demonstration that sets the collection out of line parameter in the COR descriptor to indicate that the collection need not be brought in its entirety but only a locator is brought in. The collection can be brought in on demand later on using the locator. */ static void demo_cor_3(envhp, svchp, stmthp, errhp) OCIEnv *envhp; OCISvcCtx *svchp; OCIStmt *stmthp; OCIError *errhp; { OCIType *po_tdo; ub4 po_size; OCIRef *poref = (OCIRef *)0; purchase_order *po = (purchase_order *)0; purchase_order *related_po = (purchase_order *)0; customer *cust = (customer *)0; OCIDefine *defnp; OCIComplexObject *corhp; ub1 outofline = TRUE; dvoid *tmp; sword status = OCI_SUCCESS; dvoid *elem = (dvoid *)0; dvoid *elemind = (dvoid *)0; sb4 collsiz; boolean exist; address *addr = (address *) 0; null_address *null_addr = (null_address *) 0; sb4 index = 0, counter = 0; OCIDescribe *dschp = (OCIDescribe *) 0; OCIParam *parmp; OCIRef *type_ref = (OCIRef *) 0; #ifdef VERIFY_COR text *stmt11 = (text *) "update cust_table set name = 'Anil' where name = 'JOHN'"; text *stmt12 = (text *) "update cust_table set name = 'Chin' where name = 'MIKE'"; text *stmt13 = (text *) "insert into the (select addr from cust_table where name='Anil') \ select NULL, '90419', ref(x) from person_table x where name='MIKE1'"; text *stmt14 = (text *) "insert into the (select addr from cust_table where name='Chin') \ select NULL, '90419', ref(x) from person_table x where name='MIKE1'"; #endif /*-------------------------- get po ref -----------------------------*/ checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) selref, (ub4) strlen((const char *) selref), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIDefineByPos(stmthp, &defnp, errhp, (ub4) 1, (dvoid *) 0, (sb4) 0, SQLT_REF, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIHandleAlloc((dvoid *) envhp, (dvoid **) &dschp, (ub4) OCI_HTYPE_DESCRIBE, (size_t) 0, (dvoid **) 0)); checkerr(errhp, OCIDescribeAny(svchp, errhp, (text *)"PURCHASE_ORDER", (ub4) strlen("PURCHASE_ORDER"), OCI_OTYPE_NAME, (ub1)1, (ub1) OCI_PTYPE_TYPE, dschp)); checkerr(errhp, OCIAttrGet((dvoid *) dschp, (ub4) OCI_HTYPE_DESCRIBE, (dvoid *)&parmp, (ub4 *)0, (ub4)OCI_ATTR_PARAM, errhp)); checkerr(errhp, OCIAttrGet((dvoid*) parmp, (ub4) OCI_DTYPE_PARAM, (dvoid*) &type_ref, (ub4 *) 0, (ub4) OCI_ATTR_REF_TDO, (OCIError *) errhp)); /* get type of purchase_order to set in COR descriptor */ checkerr(errhp, OCIObjectPin(envhp, errhp, type_ref, (OCIComplexObject *) 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&po_tdo)); checkerr(errhp, OCIDefineObject(defnp, errhp, po_tdo, (dvoid **) &poref, &po_size, (dvoid **) 0, (ub4 *) 0)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 0, (ub4) 0, (OCISnapshot *)NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtFetch(stmthp, errhp, (ub4) 1, (ub4) OCI_FETCH_NEXT, (ub4) OCI_DEFAULT)); /*---------------------------- C O R --------------------------------*/ /* get COR Handle */ checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&corhp, (ub4)OCI_HTYPE_COMPLEXOBJECT, 0, (dvoid **)0)); /* pin the purchase order - no COR done here */ checkerr(errhp, OCIObjectPin(envhp, errhp, poref, (OCIComplexObject *)0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&po)); /* By default collections are brought in along with the containing object (inline). By setting the attribute OCI_ATTR_COMPLEXOBJECT_COLL_OUTOFLINE to TRUE we indicate that we do not want it to be fetched along with the containing object, but will fetch it separately on demand (out-of-line) */ checkerr(errhp, OCIAttrSet((dvoid *)corhp, (ub4)OCI_HTYPE_COMPLEXOBJECT, (dvoid *)&outofline, (ub4)sizeof(ub1), (ub4)OCI_ATTR_COMPLEXOBJECT_COLL_OUTOFLINE, (OCIError *)errhp)); /* pin the customer (should go over the n/w) */ checkerr(errhp, OCIObjectPin(envhp, errhp, po->cust, corhp, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, (dvoid **)&cust)); #ifdef VERIFY_COR /* Modify the data */ checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt11, (ub4) strlen((const char *) stmt11), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt12, (ub4) strlen((const char *) stmt12), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); /* add new records */ checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt13, (ub4) strlen((const char *) stmt13), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); checkerr(errhp, OCIStmtPrepare(stmthp, errhp, (text *) stmt14, (ub4) strlen((const char *) stmt14), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0, (OCISnapshot *) NULL, (OCISnapshot *) NULL, (ub4) OCI_DEFAULT)); checkerr(errhp, OCITransCommit(svchp, errhp, (ub4) 0)); #endif /* should see the new records */ (void) printf("\n---> Dump the table from the top to the bottom.\n"); /* go to the first element and print out the index */ checkerr(errhp, OCITableFirst(envhp, errhp, cust->addr, &index)); (void) printf(" The index of the first element is : %d.\n", index); /* print out the element */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &elem, &elemind)); addr = (address *)elem; null_addr = (null_address *)elemind; (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); (void) printf(" atomic null indicator is %d\n", null_addr->null_address); (void) printf(" zip null indicator is %d\n", null_addr->null_zip); (void) printf(" state null indicator is %d\n", null_addr->null_state); for(;!OCITableNext(envhp, errhp, index, cust->addr, &index, &exist) && exist;) { (void) printf(" The index of the next element is : %d.\n", index); /* print out the element */ checkerr(errhp, OCICollGetElem(envhp, errhp, (OCIColl *) cust->addr, index, &exist, (void **) &elem, &elemind)); addr = (address *)elem; null_addr = (null_address *)elemind; (void) printf(" address.state = %.2s address.zip = %.10s\n", OCIStringPtr(envhp, addr->state), OCIStringPtr(envhp, addr->zip)); (void) printf(" atomic null indicator is %d\n", null_addr->null_address); (void) printf(" zip null indicator is %d\n", null_addr->null_zip); (void) printf(" state null indicator is %d\n", null_addr->null_state); } checkerr(errhp, OCICacheFree(envhp, errhp, svchp)); /* free COR handle */ checkerr(errhp, OCIHandleFree((dvoid *)corhp, (ub4)OCI_HTYPE_COMPLEXOBJECT)); } int main(int argc, char *argv[]) { OCIEnv *envhp; OCISvcCtx *svchp; OCIError *errhp; OCIServer *srvhp; OCISession *usrhp; OCIStmt *stmthp; sword status = OCI_SUCCESS; dvoid *tmp = (dvoid *) 0; (void) OCIInitialize((ub4) OCI_OBJECT | OCI_DEFAULT, (dvoid *)0, (dvoid * (*)()) 0, (dvoid * (*)()) 0, (void (*)()) 0 ); (void) OCIEnvInit( &envhp, (ub4) OCI_DEFAULT, 21, (dvoid **) &tmp ); (void) OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &errhp, (ub4) OCI_HTYPE_ERROR, 52, (dvoid **) &tmp); checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &srvhp, (ub4) OCI_HTYPE_SERVER, 52, (dvoid **) &tmp)); checkerr(errhp, OCIServerAttach( srvhp, errhp, (text *) "", (sb4) strlen(""), (ub4) OCI_DEFAULT)); checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &svchp, (ub4) OCI_HTYPE_SVCCTX, 52, (dvoid **) &tmp)); /* set attribute server context in the service context */ checkerr(errhp, OCIAttrSet( (dvoid *) svchp, (ub4) OCI_HTYPE_SVCCTX, (dvoid *) srvhp, (ub4) 0, (ub4) OCI_ATTR_SERVER, (OCIError *) errhp)); checkerr(errhp, OCIHandleAlloc((dvoid *)envhp, (dvoid **)&usrhp, (ub4)OCI_HTYPE_SESSION, 0, (dvoid **)0)); checkerr(errhp, OCIAttrSet((dvoid *) usrhp, (ub4)OCI_HTYPE_SESSION, (dvoid *)"cdemocor", (ub4)strlen("cdemocor"), (ub4)OCI_ATTR_USERNAME, errhp)); checkerr(errhp, OCIAttrSet((dvoid *) usrhp, (ub4)OCI_HTYPE_SESSION, (dvoid *)"cdemocor", (ub4)strlen("cdemocor"), (ub4)OCI_ATTR_PASSWORD, errhp)); checkerr(errhp, OCISessionBegin (svchp, errhp, usrhp, (ub4) OCI_CRED_RDBMS, (ub4) OCI_DEFAULT)); checkerr(errhp, OCIAttrSet((dvoid *)svchp, (ub4)OCI_HTYPE_SVCCTX, (dvoid *)usrhp, (ub4)0, (ub4)OCI_ATTR_SESSION, errhp)); /*-------------------------- get po ref -----------------------------*/ checkerr(errhp, OCIHandleAlloc( (dvoid *) envhp, (dvoid **) &stmthp, (ub4) OCI_HTYPE_STMT, 50, (dvoid **) &tmp)); (void) printf("Complex object retrieval demo # 1\n"); (void) printf(" --> Set level in COR descriptor\n"); demo_cor_1(envhp, svchp, stmthp, errhp); demo_cor_3(envhp, svchp, stmthp, errhp); OCIDescriptorFree((dvoid *)envhp, (ub4)OCI_HTYPE_ENV); }