PageRenderTime 33ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/src/front/embed/libq/iidathdl.c

https://github.com/jansepar/Ingres
C | 436 lines | 219 code | 33 blank | 184 comment | 50 complexity | 5db20e5b24d453bdd89612b5648e935c MD5 | raw file
  1. /*
  2. ** Copyright (c) 2004 Ingres Corporation
  3. */
  4. # include <compat.h>
  5. # include <gl.h>
  6. # include <sl.h>
  7. # include <cv.h>
  8. # include <iicommon.h>
  9. # include <cm.h>
  10. # include <st.h>
  11. # include <gca.h>
  12. # include <adf.h>
  13. # include <adp.h>
  14. # include <iicgca.h>
  15. # include <iirowdsc.h>
  16. # include <iisqlca.h>
  17. # include <iilibq.h>
  18. # include <erlq.h>
  19. # include <er.h>
  20. # include <generr.h>
  21. /* {
  22. ** Name: iilodata.c - Process the DATAHANDLER clause for Large Objects (BLOBS).
  23. **
  24. ** Description:
  25. ** This module contains the routines to invoke user defined datahandlers.
  26. **
  27. ** Defines:
  28. ** IILQldh_LoDataHandler - Call user defined data handler to process
  29. ** Large Object.
  30. ** IILQlcd_LoColDesc - Get column descriptor of large object.
  31. ** IILQlcc_LoCbClear - Clear LIBQ control block large object struct.
  32. **
  33. ** History:
  34. ** 05-oct-1992 (kathryn)
  35. ** Written.
  36. ** 21-jan-1993 (sandyd)
  37. ** Latest version of <adp.h> now requires <adf.h> to be included first.
  38. ** 25-Aug-1993 (fredv)
  39. ** Needed to include <st.h>.
  40. ** 15-feb-1994 (mgw) Bug #58294
  41. ** prevent reference through null pointer in IILQldh_LoDataHandler
  42. ** 06-may-1994 (teresal)
  43. ** Make IILQldh_LoDataHandler define the handler function as
  44. ** returning an i4 - this is the way we document it to
  45. ** users and this will make it consistent with the other
  46. ** user-defined handlers. Bug 63202.
  47. ** 18-Dec-97 (gordy)
  48. ** Added support for multi-threaded applications.
  49. ** 21-jan-1999 (hanch04)
  50. ** replace nat and longnat with i4
  51. ** 31-aug-2000 (hanch04)
  52. ** cross change to main
  53. ** replace nat and longnat with i4
  54. ** aug-2009 (stephenb)
  55. ** Prototyping front-ends
  56. */
  57. # define IIGETHDLR 1
  58. # define IIPUTHDLR 2
  59. /* {
  60. ** Name: IILQldh_LoDataHandler -- Call user defined data handler to process
  61. ** Large Object.
  62. **
  63. ** Description:
  64. ** This routine is called when an application uses the DATAHANDLER
  65. ** clause for retrieving or inserting a large object into the database.
  66. ** EX:
  67. ** EXEC SQL SELECT column_name
  68. ** INTO DATAHANDLER(user_func,arg):null_indicator
  69. ** FROM table_name;
  70. ** OR
  71. ** EXEC SQL INSERT INTO table_name (column_name)
  72. ** VALUES (DATAHANDLER(user_func,arg):null_indicator);
  73. **
  74. ** The DATAHANDLER clause will generate:
  75. ** IILQldh_LoDataHandler(type,indvar,datahdlr,hdlr_arg)
  76. ** rather than the normal IIgetdomio or IIputdomio.
  77. **
  78. ** If the large object data is not NULL, this routine sets up the local
  79. ** LIBQ control block large object structure and invokes the datahandler.
  80. ** It is the repsonsiblity of the datahandler to loop on GET/PUT DATA
  81. ** statements until the entire large object is transmitted.
  82. **
  83. ** Input:
  84. ** type - Datahandler type
  85. ** 1: GET handler - generated from retrieve query.
  86. ** 2: PUT handler - generated from insert query.
  87. ** indvar - Null Indicator Variable.
  88. ** datahdlr - Pointer to datahandler - user defined function to invoke.
  89. ** hdlr_arg - User specified pointer argument to pass to handler when
  90. ** it is invoked.
  91. **
  92. ** Outputs:
  93. ** None.
  94. ** Returns:
  95. ** void.
  96. ** Errors:
  97. ** E_LQ00E0_NODATAHDLR - Datahandler function pointer is null.
  98. ** E_LQ00E1_DATHDLRTYPE - Invalid datatype for datahandler.
  99. ** E_LQ00E4_NOENDDATA - Get handler returned before getting all data.
  100. ** E_LQ00E7_NODATEND - Put handler did not issued DATAEND param.
  101. **
  102. **
  103. ** Side Effects:
  104. **
  105. ** History:
  106. ** 05-oct-1992 (kathryn) Written.
  107. ** 01-mar-1993 (kathryn)
  108. ** Added changes for COPY to call datahandlers for BLOBS.
  109. ** 01-apr-1993 (kathryn)
  110. ** Added changes to use lodata->db_datatype set by COPY, and
  111. ** ensure that null indicator variable gets set correctly.
  112. ** 25-jun-1993 (kathryn)
  113. ** Set II_LO_ISNULL flag when value is NULL.
  114. ** 20-jul-1993 (kathryn) Bug 53472
  115. ** Send DB_NUL_TYPE to IIputdomio for NULL value BLOB with datahandler.
  116. ** 01-oct-1993 (kathryn)
  117. ** Issue IIbreak() when error occurrs within PUT datahandler.
  118. ** 01-oct-1993 (kathryn) 55775
  119. ** Issue an error message when get handler receives a null value
  120. ** but no null indicator has been supplied.
  121. ** 15-feb-1994 (mgw) Bug #58294
  122. ** prevent referencing through a null pointer in case of IIGETHDLR
  123. ** with no indicator variable and non-null value.
  124. ** 06-may-1994 (teresal) Bug #63202
  125. ** Make the handler return a i4 not a long.
  126. */
  127. void
  128. IILQldh_LoDataHandler(type, indvar, datahdlr, hdlr_arg)
  129. i4 type;
  130. i2 *indvar;
  131. i4 (*datahdlr)();
  132. PTR hdlr_arg;
  133. {
  134. II_THR_CB *thr_cb = IILQthThread();
  135. II_LBQ_CB *IIlbqcb = thr_cb->ii_th_session;
  136. i4 resval;
  137. i4 *col_num;
  138. char ebuf1[20], ebuf2[20];
  139. bool isnull;
  140. i4 locerr;
  141. STATUS stat = OK;
  142. IICGC_MSG *msg;
  143. ADP_PERIPHERAL tmp_adp;
  144. ADP_PERIPHERAL *adp_per;
  145. DB_DATA_VALUE *dbv;
  146. IILQ_LODATA *lodata;
  147. if (IIlbqcb->ii_lq_curqry & II_Q_QERR)
  148. return;
  149. if (datahdlr == NULL)
  150. {
  151. IIlocerr(GE_SYNTAX_ERROR, E_LQ00E0_NODATAHDLR, II_ERR, 0, (char *)0);
  152. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  153. return;
  154. }
  155. adp_per = &tmp_adp;
  156. isnull = FALSE;
  157. lodata = &IIlbqcb->ii_lq_lodata;
  158. if (IIlbqcb->ii_lq_flags & II_L_COPY)
  159. lodata->ii_lo_msgtype = GCA_CDATA;
  160. else
  161. lodata->ii_lo_msgtype = GCA_TUPLES;
  162. /*
  163. ** The datahandler specified is for retrieving data from the database.
  164. ** Read the ADP_PERIPHERAL header and the first segment indicator. If the
  165. ** segment indicator is zero, then the large object value is null, so
  166. ** just set the null indicator variable and return.
  167. */
  168. if (type == IIGETHDLR)
  169. {
  170. msg = &IIlbqcb->ii_lq_gca->cgc_result_msg;
  171. /* Cursor or Select Loop - Check number of columns - Set DBV */
  172. if ((stat = IILQlcd_LoColDesc( thr_cb, &col_num, &dbv )) != OK)
  173. {
  174. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  175. return;
  176. }
  177. lodata->ii_lo_datatype = dbv->db_datatype;
  178. /* We are not retreiving a large object - may not use datahandler */
  179. if (!IIDB_LONGTYPE_MACRO(dbv))
  180. {
  181. IIlocerr(GE_SYNTAX_ERROR, E_LQ00E1_DATHDLRTYPE, II_ERR,0,(char *)0);
  182. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  183. stat = FAIL;
  184. }
  185. else if ((stat = IILQlag_LoAdpGet( IIlbqcb, (PTR)adp_per )) == OK)
  186. {
  187. if ((stat = IILQlmg_LoMoreGet( IIlbqcb )) == OK)
  188. {
  189. isnull = (lodata->ii_lo_flags & II_LO_ISNULL);
  190. if (isnull)
  191. {
  192. if (indvar != (i2 *)0)
  193. *indvar = DB_EMB_NULL;
  194. else if (isnull)
  195. {
  196. CVna(*col_num + 1, ebuf1);
  197. locerr = E_LQ000E_EMBIND;
  198. IIlocerr(GE_DATA_EXCEPTION + GESC_NEED_IND, locerr,
  199. II_ERR, 1, ebuf1);
  200. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  201. stat = FAIL;
  202. }
  203. }
  204. else
  205. {
  206. if (indvar != (i2 *)0) /* for bug 58294 */
  207. *indvar = 0;
  208. lodata->ii_lo_flags |= II_LO_GETHDLR;
  209. }
  210. } /* MoreGet OK */
  211. } /* AdpGet OK */
  212. } /* GetHandler */
  213. /*
  214. ** The datahandler specified is for sending data to the dbms.
  215. ** If the data is not null, then set the II_LO_START flag and invoke the
  216. ** datahandler. We won't know the datatype (cannot send anything) until
  217. ** the datahandler is called and we have the segment type (char/byte).
  218. ** If the data is null then just send a null-valued DB_LTXT_TYPE, and
  219. ** return. A null DB_LTXT_TYPE is coercible to any datatype.
  220. ** For COPY, the datatypes have already been negotiated between FE and
  221. ** DBMS, so for a null value we must send a null large object. The
  222. ** the ii_lq_lodata field of the local control block has been set correctly
  223. ** by the internal COPY code.
  224. */
  225. else if (type == IIPUTHDLR)
  226. {
  227. if (indvar != (i2 *)0)
  228. {
  229. if (*indvar == DB_EMB_NULL)
  230. {
  231. isnull = TRUE;
  232. if (lodata->ii_lo_msgtype == GCA_CDATA)
  233. {
  234. lodata->ii_lo_flags |= II_LO_ISNULL;
  235. IILQlap_LoAdpPut( IIlbqcb );
  236. IILQlmp_LoMorePut( IIlbqcb, 0 );
  237. }
  238. else
  239. {
  240. IIputdomio(indvar, 1, DB_NUL_TYPE, 0, (char *)0);
  241. }
  242. }
  243. }
  244. if (!isnull)
  245. {
  246. lodata->ii_lo_flags |= II_LO_PUTHDLR;
  247. lodata->ii_lo_flags |= II_LO_START;
  248. }
  249. }
  250. /* No errors, and the large object is not null - Invoke the Datahandler.*/
  251. if (!isnull && (stat == OK))
  252. {
  253. IIlbqcb->ii_lq_flags |= II_L_DATAHDLR;
  254. if (hdlr_arg != NULL)
  255. (void)(*datahdlr)(hdlr_arg);
  256. else
  257. (void)(*datahdlr)();
  258. if (!(lodata->ii_lo_flags & II_LO_END))
  259. {
  260. /* The caller returned from the datahandler prematurely. Either
  261. ** from a GET handler without issuing and ENDDATA statement,
  262. ** OR, from a PUT handler without setting the DATAEND parameter on
  263. ** the PUT DATA statement. Issue the Error, set the error flag.
  264. */
  265. if (type == IIGETHDLR)
  266. {
  267. locerr = E_LQ00E4_NOENDDATA;
  268. }
  269. else
  270. {
  271. locerr = E_LQ00E7_NODATAEND;
  272. IIbreak();
  273. }
  274. IIlocerr(GE_SYNTAX_ERROR, locerr, II_ERR, 0, (char *)0);
  275. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  276. }
  277. }
  278. /* We have completed the tranmission of this large object.
  279. ** Clear the large object state information from the LIBQ control block.
  280. */
  281. IILQlcc_LoCbClear( IIlbqcb );
  282. if (type == IIGETHDLR)
  283. *col_num += 1;
  284. IIlbqcb->ii_lq_flags &= ~II_L_DATAHDLR;
  285. }
  286. /* {
  287. ** Name: IILQlcd_LoColDesc - Get column descriptor.
  288. **
  289. ** Description:
  290. ** Determine the correct row desciptor from the current query in
  291. ** process (SELECT/FETCH) and return the address of the row descriptor
  292. ** DB_DATA_VALUE and the address of the current column number.
  293. ** This routine is called from IILQldh_LoDataHandler.
  294. **
  295. ** Input:
  296. ** thr_cb Thread-local-storage control block.
  297. **
  298. ** Outputs:
  299. **
  300. ** Side Effects:
  301. **
  302. ** History:
  303. ** 01-nov-1992 (kathryn)
  304. ** Written.
  305. ** 10-dec-1992 (kathryn)
  306. ** Corrected check for columname.
  307. ** 01-mar-1993 (kathryn)
  308. ** Added check for COPY row descriptor (II_L_COPY).
  309. ** 26-Aug-2009 (kschendel) b121804
  310. ** Fix column number CVna call in error path.
  311. */
  312. STATUS
  313. IILQlcd_LoColDesc( II_THR_CB *thr_cb, i4 **col_num, DB_DATA_VALUE **dbv )
  314. {
  315. II_LBQ_CB *IIlbqcb = thr_cb->ii_th_session;
  316. u_i4 col_nmlen;
  317. II_RET_DESC *rd;
  318. IICS_STATE *csr_cur;
  319. ROW_DESC *row_desc;
  320. ROW_COLNAME *col_name;
  321. IILQ_LODATA *lodata;
  322. char csrname[ GCA_MAXNAME +1];
  323. char ebuf1[20], ebuf2[20];
  324. lodata = &IIlbqcb->ii_lq_lodata;
  325. if (IIlbqcb->ii_lq_flags &
  326. (II_L_DYNSEL | II_L_SINGLE | II_L_RETRIEVE | II_L_COPY))
  327. {
  328. rd = &IIlbqcb->ii_lq_retdesc;
  329. *col_num = &rd->ii_rd_colnum;
  330. row_desc = &rd->ii_rd_desc;
  331. if (**col_num >= row_desc->rd_numcols)
  332. {
  333. CVna(row_desc->rd_numcols, ebuf1); /* i4 */
  334. CVna(**col_num+1, ebuf2); /* i4 */
  335. IIlocerr(GE_CARDINALITY, E_LQ003C_RETCOLS, II_ERR, 2, ebuf1, ebuf2);
  336. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  337. if (IISQ_SQLCA_MACRO(IIlbqcb))
  338. IIsqWarn( thr_cb, 3 ); /* Status information for SQLCA */
  339. return FAIL;
  340. }
  341. *dbv = &rd->ii_rd_desc.RD_DBVS_MACRO(rd->ii_rd_colnum);
  342. }
  343. else
  344. {
  345. csr_cur = IIlbqcb->ii_lq_csr.css_cur;
  346. row_desc = &csr_cur->css_cdesc;
  347. *col_num = &csr_cur->css_colcount;
  348. if (**col_num >= csr_cur->css_cdesc.rd_numcols)
  349. {
  350. STlcopy( csr_cur->css_name.gca_name, csrname, GCA_MAXNAME );
  351. STtrmwhite( csrname );
  352. IIlocerr(GE_CARDINALITY, E_LQ005B_CSXCOLS, II_ERR, 2,
  353. ERx("fetch"), csrname);
  354. IIlbqcb->ii_lq_curqry |= II_Q_QERR;
  355. if (IISQ_SQLCA_MACRO(IIlbqcb))
  356. IIsqWarn( thr_cb, 3 ); /* Status information for SQLCA */
  357. return FAIL;
  358. }
  359. *dbv = &csr_cur->css_cdesc.RD_DBVS_MACRO(csr_cur->css_colcount);
  360. }
  361. /* Save the column name for INQUIRE_SQL */
  362. if ((row_desc->rd_flags & RD_NAMES) && row_desc->rd_names != NULL
  363. && (**col_num < row_desc->rd_numcols))
  364. {
  365. col_name = &row_desc->rd_names[**col_num];
  366. col_nmlen = col_name->rd_nmlen;
  367. CMcopy(col_name->rd_nmbuf, col_nmlen, lodata->ii_lo_name);
  368. }
  369. return OK;
  370. }
  371. /* {
  372. ** Name: IILQlcc_LoCbClear - Clear the local control block large object struct.
  373. **
  374. ** Description:
  375. ** This routine clears the LIBQ local control block large object
  376. ** structure. It should be called prior to sending/retrieving a large
  377. ** object from the DBMS. This structure maintains the information
  378. ** about a large object between invocations of GET/PUT DATA statements.
  379. **
  380. ** This routine also clears the LIBQ control block datahandler flag.
  381. **
  382. ** Input:
  383. ** IIlbqcb Current session control block.
  384. **
  385. ** Output:
  386. ** None.
  387. **
  388. ** History:
  389. ** 20-apr-1993 (kathryn) Written.
  390. **
  391. */
  392. void
  393. IILQlcc_LoCbClear( II_LBQ_CB *IIlbqcb )
  394. {
  395. IILQ_LODATA *lodata;
  396. IIlbqcb->ii_lq_flags &= ~II_L_DATAHDLR;
  397. lodata = &IIlbqcb->ii_lq_lodata;
  398. lodata->ii_lo_maxseglen = (i4)0;
  399. lodata->ii_lo_name[0] = EOS;
  400. lodata->ii_lo_flags = (i4)0;
  401. lodata->ii_lo_msgtype = (i4)0;
  402. lodata->ii_lo_datatype = (DB_DT_ID)0;
  403. }