Mercurial > forge
comparison main/database/src/pq_connection.cc @ 12718:1af86934c14e octave-forge
Make compatible with Octaves new exception-based error handling.
Retain compatibility with Octaves old error handling based on
error_state.
* src/error_helpers.[h,cc]: Added.
* src/Makefile.in: Integrate error-helpers.[h,cc].
* src/config.h.in: Added.
* configure.ac, src/config.h.in: Test presence of 'error_state' and
presence of 'verror (octave_execution_exception&, const char *,
va_list)'.
* src/__pq_connect__.cc, src/command.cc, src/command.h,
src/converters.cc, src/converters_arr_comp.cc, src/pq_connection.cc,
src/pq_conninfo.cc, src/pq_exec.cc, src/pq_lo.cc,
src/pq_update_types.cc: If necessary, include error-helpers.h, replace
error() with c_verror(), set and check a different error indicator
than error_state, use CHECK_ERROR or SET_ERR, explicitely check for
errors instead of relying on Octave checking error_state when
returning to the prompt.
author | i7tiol |
---|---|
date | Sat, 27 Feb 2016 11:11:04 +0000 |
parents | 2257648e8ce1 |
children | 52ca082757c2 |
comparison
equal
deleted
inserted
replaced
12717:87989220360f | 12718:1af86934c14e |
---|---|
17 | 17 |
18 */ | 18 */ |
19 | 19 |
20 #include "pq_connection.h" | 20 #include "pq_connection.h" |
21 #include "command.h" | 21 #include "command.h" |
22 #include "error-helpers.h" | |
22 | 23 |
23 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_pq_connection, "PGconn", "PGconn") | 24 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_pq_connection, "PGconn", "PGconn") |
24 | 25 |
25 std::string &pq_basetype_prefix (void) | 26 std::string &pq_basetype_prefix (void) |
26 { | 27 { |
55 | 56 |
56 if (! conn || PQstatus (conn) == CONNECTION_BAD) | 57 if (! conn || PQstatus (conn) == CONNECTION_BAD) |
57 { | 58 { |
58 if (conn) | 59 if (conn) |
59 { | 60 { |
60 error ("%s", PQerrorMessage (conn)); | 61 c_verror ("%s", PQerrorMessage (conn)); |
61 | 62 |
62 PGconn *t_conn = conn; | 63 PGconn *t_conn = conn; |
63 | 64 |
64 conn = NULL; | 65 conn = NULL; |
65 | 66 |
66 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 67 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
67 PQfinish (t_conn); | 68 PQfinish (t_conn); |
68 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 69 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
69 } | 70 } |
70 | 71 |
71 error ("PQ connection attempt failed"); | 72 c_verror ("PQ connection attempt failed"); |
72 } | 73 } |
73 else | 74 else |
74 { | 75 { |
75 // init name converter-map (kind of "bootstrapping") | 76 // init name converter-map (kind of "bootstrapping") |
76 for (int i = 0; i < OCT_PQ_NUM_CONVERTERS; i++) | 77 for (int i = 0; i < OCT_PQ_NUM_CONVERTERS; i++) |
92 | 93 |
93 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 94 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
94 PQfinish (t_conn); | 95 PQfinish (t_conn); |
95 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 96 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
96 | 97 |
97 error ("could not read types"); | 98 c_verror ("could not read types"); |
98 } | 99 } |
99 else | 100 else |
100 { | 101 { |
101 if (strcmp (PQparameterStatus (conn, "integer_datetimes"), "on")) | 102 if (strcmp (PQparameterStatus (conn, "integer_datetimes"), "on")) |
102 integer_datetimes = false; | 103 integer_datetimes = false; |
131 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 132 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
132 | 133 |
133 octave_pq_delete_non_constant_types (); | 134 octave_pq_delete_non_constant_types (); |
134 } | 135 } |
135 else | 136 else |
137 // deliberately left the 'error' call here, since | |
138 // 'octave_pq_close()' is only called by 'pq_close' immediately | |
139 // before returning | |
136 error ("PGconn object not open"); | 140 error ("PGconn object not open"); |
137 } | 141 } |
138 | 142 |
139 void octave_pq_connection_rep::octave_pq_delete_non_constant_types (void) | 143 void octave_pq_connection_rep::octave_pq_delete_non_constant_types (void) |
140 { | 144 { |
187 caller ("octave_pq_get_postgres_oid"); | 191 caller ("octave_pq_get_postgres_oid"); |
188 | 192 |
189 command c (*this, cmd, p, pt, rt, caller); | 193 command c (*this, cmd, p, pt, rt, caller); |
190 if (! c.good ()) | 194 if (! c.good ()) |
191 { | 195 { |
192 error ("could not read pg_roles"); | 196 c_verror ("could not read pg_roles"); |
193 return 1; | 197 return 1; |
194 } | 198 } |
195 | 199 |
196 octave_value res = c.process_single_result (); | 200 octave_value res = c.process_single_result (); |
197 if (error_state) | 201 if (! c.good ()) |
198 return 1; | 202 return 1; |
199 | 203 |
200 postgres = res.scalar_map_value ().contents ("data").cell_value ()(0). | 204 bool err; |
201 int_value (); | 205 SET_ERR (postgres = res.scalar_map_value ().contents ("data").cell_value ()(0).int_value (), err); |
202 if (error_state) | 206 if (err) |
203 return 1; | 207 return 1; |
204 | 208 |
205 return 0; | 209 return 0; |
206 } | 210 } |
207 | 211 |
221 caller ("octave_pq_fill_base_types"); | 225 caller ("octave_pq_fill_base_types"); |
222 | 226 |
223 command c (*this, cmd, p, pt, rt, caller); | 227 command c (*this, cmd, p, pt, rt, caller); |
224 if (! c.good ()) | 228 if (! c.good ()) |
225 { | 229 { |
226 error ("octave_pq_fill_base_types: could not read pg_type"); | 230 c_verror ("octave_pq_fill_base_types: could not read pg_type"); |
227 return 1; | 231 return 1; |
228 } | 232 } |
229 | 233 |
230 octave_value res = c.process_single_result (); | 234 octave_value res = c.process_single_result (); |
231 if (error_state) | 235 if (! c.good ()) |
232 return 1; | 236 return 1; |
233 | 237 |
234 Cell tpls = res.scalar_map_value ().contents ("data").cell_value (); | 238 Cell tpls; |
235 if (error_state) | 239 bool err; |
236 { | 240 SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (), |
237 error | 241 err); |
242 if (err) | |
243 { | |
244 c_verror | |
238 ("octave_pq_fill_base_types: could not convert result data to cell"); | 245 ("octave_pq_fill_base_types: could not convert result data to cell"); |
239 return 1; | 246 return 1; |
240 } | 247 } |
241 | 248 |
242 // make a temporary map of server base types (cell row numbers) for searching | 249 // make a temporary map of server base types (cell row numbers) for searching |
243 typedef std::map<std::string, int, bool (*) (const std::string &, | 250 typedef std::map<std::string, int, bool (*) (const std::string &, |
244 const std::string &)> | 251 const std::string &)> |
245 bt_map_t; | 252 bt_map_t; |
246 bt_map_t bt_map (&map_string_cmp); | 253 bt_map_t bt_map (&map_string_cmp); |
247 for (int i = 0; i < tpls.rows (); i++) | 254 for (int i = 0; i < tpls.rows (); i++) |
248 bt_map[tpls(i, 1).string_value ()] = i; | 255 { |
249 if (error_state) | 256 SET_ERR (bt_map[tpls(i, 1).string_value ()] = i, err); |
250 { | 257 if (err) |
251 error ("octave_pq_fill_base_types: could not read returned result"); | 258 break; |
259 } | |
260 if (err) | |
261 { | |
262 c_verror ("octave_pq_fill_base_types: could not read returned result"); | |
252 return 1; | 263 return 1; |
253 } | 264 } |
254 | 265 |
255 for (int i = 0; i < OCT_PQ_NUM_CONVERTERS; i++) | 266 for (int i = 0; i < OCT_PQ_NUM_CONVERTERS; i++) |
256 { | 267 { |
257 bt_map_t::iterator bt_it; | 268 bt_map_t::iterator bt_it; |
258 if ((bt_it = bt_map.find (conv_ptrs[i]->name.c_str () + pq_bpl)) == | 269 if ((bt_it = bt_map.find (conv_ptrs[i]->name.c_str () + pq_bpl)) == |
259 bt_map.end ()) | 270 bt_map.end ()) |
260 { | 271 { |
261 error ("octave_pq_fill_base_types: type %s not found in pg_type", | 272 c_verror ("octave_pq_fill_base_types: type %s not found in pg_type", |
262 conv_ptrs[i]->name.c_str () + pq_bpl); | 273 conv_ptrs[i]->name.c_str () + pq_bpl); |
263 return 1; | 274 return 1; |
264 } | 275 } |
265 // fill in oid and aoid into static records of converters | 276 // fill in oid and aoid into static records of converters |
266 conv_ptrs[i]->oid = tpls(bt_it->second, 0).int_value (); | 277 SET_ERR (conv_ptrs[i]->oid = tpls(bt_it->second, 0).int_value (), err); |
267 conv_ptrs[i]->aoid = tpls(bt_it->second, 2).int_value (); | 278 if (! err) |
279 { | |
280 SET_ERR (conv_ptrs[i]->aoid = tpls(bt_it->second, 2).int_value (), | |
281 err); | |
282 } | |
283 if (err) | |
284 break; | |
268 | 285 |
269 // fill in map of converters over oid with oid and, if not zero, | 286 // fill in map of converters over oid with oid and, if not zero, |
270 // also with aoid | 287 // also with aoid |
271 conv_map[conv_ptrs[i]->oid] = conv_ptrs[i]; | 288 conv_map[conv_ptrs[i]->oid] = conv_ptrs[i]; |
272 if (conv_ptrs[i]->aoid != 0) | 289 if (conv_ptrs[i]->aoid != 0) |
273 conv_map[conv_ptrs[i]->aoid] = conv_ptrs[i]; | 290 conv_map[conv_ptrs[i]->aoid] = conv_ptrs[i]; |
274 } | 291 } |
275 if (error_state) | 292 if (err) |
276 { | 293 { |
277 error ("octave_pq_fill_base_types: could not read returned result"); | 294 c_verror ("octave_pq_fill_base_types: could not read returned result"); |
278 return 1; | 295 return 1; |
279 } | 296 } |
280 | 297 |
281 return 0; | 298 return 0; |
282 } | 299 } |
289 caller ("octave_pq_get_composite_types"); | 306 caller ("octave_pq_get_composite_types"); |
290 | 307 |
291 command c (*this, cmd, p, pt, rt, caller); | 308 command c (*this, cmd, p, pt, rt, caller); |
292 if (! c.good ()) | 309 if (! c.good ()) |
293 { | 310 { |
294 error ("octave_pq_get_composite_types: could not read pg_type"); | 311 c_verror ("octave_pq_get_composite_types: could not read pg_type"); |
295 return 1; | 312 return 1; |
296 } | 313 } |
297 | 314 |
298 octave_value res = c.process_single_result (); | 315 octave_value res = c.process_single_result (); |
299 if (error_state) | 316 if (! c.good ()) |
300 return 1; | 317 return 1; |
301 | 318 |
302 Cell tpls = res.scalar_map_value ().contents ("data").cell_value (); | 319 Cell tpls; |
303 if (error_state) | 320 bool err; |
304 { | 321 SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (), |
305 error ("octave_pq_get_composite_types: could not convert result data to cell"); | 322 err) |
323 if (err) | |
324 { | |
325 c_verror ("octave_pq_get_composite_types: could not convert result data to cell"); | |
306 return 1; | 326 return 1; |
307 } | 327 } |
308 | 328 |
309 for (int i = 0; i < tpls.rows (); i++) | 329 for (int i = 0; i < tpls.rows (); i++) |
310 { | 330 { |
311 Oid oid = tpls(i, 0).uint_value (); | 331 Oid oid; |
312 Oid aoid = tpls(i, 2).uint_value (); | 332 SET_ERR (oid = tpls(i, 0).uint_value (), err); |
313 std::string name = tpls(i, 1).string_value (); | 333 Oid aoid; |
314 std::string nspace = tpls(i, 3).string_value (); | 334 if (! err) |
315 bool visible = tpls(i, 4).bool_value (); | 335 { |
316 Cell r_el_oids = | 336 SET_ERR (aoid = tpls(i, 2).uint_value (), err); |
317 tpls(i, 5).scalar_map_value ().contents ("data").cell_value (); | 337 } |
318 Cell r_el_pos = | 338 std::string name; |
319 tpls(i, 6).scalar_map_value ().contents ("data").cell_value (); | 339 if (! err) |
320 if (error_state) | 340 { |
321 { | 341 SET_ERR (name = tpls(i, 1).string_value (), err); |
322 error ("octave_pq_get_composite_types: could not read returned result"); | 342 } |
343 std::string nspace; | |
344 if (! err) | |
345 { | |
346 SET_ERR (nspace = tpls(i, 3).string_value (), err); | |
347 } | |
348 bool visible; | |
349 if (! err) | |
350 { | |
351 SET_ERR (visible = tpls(i, 4).bool_value (), err); | |
352 } | |
353 Cell r_el_oids; | |
354 if (! err) | |
355 { | |
356 SET_ERR (r_el_oids = tpls(i, 5).scalar_map_value () | |
357 .contents ("data").cell_value (), err); | |
358 } | |
359 Cell r_el_pos; | |
360 if (! err) | |
361 { | |
362 SET_ERR (r_el_pos = tpls(i, 6).scalar_map_value () | |
363 .contents ("data").cell_value (), err); | |
364 } | |
365 if (err) | |
366 { | |
367 c_verror ("octave_pq_get_composite_types: could not read returned result"); | |
323 return 1; | 368 return 1; |
324 } | 369 } |
325 octave_idx_type nel = r_el_oids.numel (); | 370 octave_idx_type nel = r_el_oids.numel (); |
326 if (nel != r_el_pos.numel ()) | 371 if (nel != r_el_pos.numel ()) |
327 { | 372 { |
328 error ("octave_pq_get_composite_types: internal error, inconsistent content of pg_attribute?"); | 373 c_verror ("octave_pq_get_composite_types: internal error, inconsistent content of pg_attribute?"); |
329 | 374 |
330 return 1; | 375 return 1; |
331 } | 376 } |
332 oct_pq_el_oids_t el_oids; | 377 oct_pq_el_oids_t el_oids; |
333 el_oids.resize (nel); | 378 el_oids.resize (nel); |
334 oct_pq_conv_cache_t conv_cache; | 379 oct_pq_conv_cache_t conv_cache; |
335 conv_cache.resize (nel); | 380 conv_cache.resize (nel); |
336 for (octave_idx_type i = 0; i < nel; i++) | 381 for (octave_idx_type i = 0; i < nel; i++) |
337 { | 382 { |
383 octave_idx_type pos; | |
338 // "column" number (attnum) is one-based, so subtract 1 | 384 // "column" number (attnum) is one-based, so subtract 1 |
339 octave_idx_type pos = r_el_pos(i).idx_type_value () - 1; | 385 SET_ERR (pos = r_el_pos(i).idx_type_value () - 1, err); |
340 if (! error_state) | 386 if (! err) |
341 { | 387 { |
342 if (pos >= nel) | 388 if (pos >= nel) |
343 { | 389 { |
344 error ("octave_pq_get_composite_types: internal error (?system catalog erroneous?): column position %i greater than ncols %i for type %s, namespace %s", | 390 c_verror ("octave_pq_get_composite_types: internal error (?system catalog erroneous?): column position %i greater than ncols %i for type %s, namespace %s", |
345 pos, nel, name.c_str (), nspace.c_str ()); | 391 pos, nel, name.c_str (), nspace.c_str ()); |
346 return 1; | 392 return 1; |
347 } | 393 } |
348 | 394 |
349 el_oids[pos] = r_el_oids(i).uint_value (); | 395 SET_ERR (el_oids[pos] = r_el_oids(i).uint_value (), err); |
350 | 396 |
351 conv_cache[pos] = NULL; | 397 conv_cache[pos] = NULL; |
352 } | 398 } |
353 } | 399 if (err) |
354 if (error_state) | 400 { |
355 { | 401 c_verror ("octave_pq_get_composite_types: could not fill in element oids."); |
356 error ("octave_pq_get_composite_types: could not fill in element oids."); | 402 |
357 | 403 return 1; |
358 return 1; | 404 } |
359 } | 405 } |
360 | 406 |
361 // must be allocated and filled before creating the name map | 407 // must be allocated and filled before creating the name map |
362 // entry, to get a remaining location for the c-string used as | 408 // entry, to get a remaining location for the c-string used as |
363 // key | 409 // key |
377 | 423 |
378 oct_pq_conv_t *&by_oid = conv_map[oid], | 424 oct_pq_conv_t *&by_oid = conv_map[oid], |
379 *&by_name = name_conv_map[t_conv->name.c_str ()]; | 425 *&by_name = name_conv_map[t_conv->name.c_str ()]; |
380 if (by_oid || by_name) | 426 if (by_oid || by_name) |
381 { | 427 { |
382 error ("octave_pq_get_composite_types: internal error, key already in typemap (by_oid: %u/%li, by name: %s/%li)", | 428 c_verror ("octave_pq_get_composite_types: internal error, key already in typemap (by_oid: %u/%li, by name: %s/%li)", |
383 oid, by_oid, t_conv->name.c_str (), by_name); | 429 oid, by_oid, t_conv->name.c_str (), by_name); |
384 if (! by_oid) conv_map.erase (oid); | 430 if (! by_oid) conv_map.erase (oid); |
385 if (! by_name) name_conv_map.erase (t_conv->name.c_str ()); | 431 if (! by_name) name_conv_map.erase (t_conv->name.c_str ()); |
386 delete t_conv; | 432 delete t_conv; |
387 return 1; | 433 return 1; |
408 if (aoid) | 454 if (aoid) |
409 { | 455 { |
410 oct_pq_conv_t *&by_aoid = conv_map[aoid]; | 456 oct_pq_conv_t *&by_aoid = conv_map[aoid]; |
411 if (by_aoid) | 457 if (by_aoid) |
412 { | 458 { |
413 error ("octave_pq_get_composite_types: internal error, aoid key %u already in typemap", aoid); | 459 c_verror ("octave_pq_get_composite_types: internal error, aoid key %u already in typemap", aoid); |
414 conv_map.erase (oid); | 460 conv_map.erase (oid); |
415 name_conv_map.erase (t_conv->name.c_str ()); | 461 name_conv_map.erase (t_conv->name.c_str ()); |
416 delete t_conv; | 462 delete t_conv; |
417 if (visible) | 463 if (visible) |
418 { | 464 { |
438 caller ("octave_pq_get_enum_types"); | 484 caller ("octave_pq_get_enum_types"); |
439 | 485 |
440 command c (*this, cmd, p, pt, rt, caller); | 486 command c (*this, cmd, p, pt, rt, caller); |
441 if (! c.good ()) | 487 if (! c.good ()) |
442 { | 488 { |
443 error ("octave_pq_get_enum_types: could not read pg_type"); | 489 c_verror ("octave_pq_get_enum_types: could not read pg_type"); |
444 return 1; | 490 return 1; |
445 } | 491 } |
446 | 492 |
447 octave_value res = c.process_single_result (); | 493 octave_value res = c.process_single_result (); |
448 if (error_state) | 494 if (! c.good ()) |
449 return 1; | 495 return 1; |
450 | 496 |
451 Cell tpls = res.scalar_map_value ().contents ("data").cell_value (); | 497 Cell tpls; |
452 if (error_state) | 498 bool err; |
453 { | 499 SET_ERR (tpls = res.scalar_map_value ().contents ("data").cell_value (), |
454 error ("octave_pq_get_enum_types: could not convert result data to cell"); | 500 err); |
501 if (err) | |
502 { | |
503 c_verror ("octave_pq_get_enum_types: could not convert result data to cell"); | |
455 return 1; | 504 return 1; |
456 } | 505 } |
457 | 506 |
458 for (int i = 0; i < tpls.rows (); i++) | 507 for (int i = 0; i < tpls.rows (); i++) |
459 { | 508 { |
460 Oid oid = tpls(i, 0).uint_value (); | 509 Oid oid; |
461 Oid aoid = tpls(i, 2).uint_value (); | 510 SET_ERR (oid = tpls(i, 0).uint_value (), err); |
462 std::string name = tpls(i, 1).string_value (); | 511 Oid aoid; |
463 std::string nspace = tpls(i, 3).string_value (); | 512 if (! err) |
464 bool visible = tpls(i, 4).bool_value (); | 513 { |
465 if (error_state) | 514 SET_ERR (aoid = tpls(i, 2).uint_value (), err); |
466 { | 515 } |
467 error ("octave_pq_get_enum_types: could not read returned result"); | 516 std::string name; |
517 if (! err) | |
518 { | |
519 SET_ERR (name = tpls(i, 1).string_value (), err); | |
520 } | |
521 std::string nspace; | |
522 if (! err) | |
523 { | |
524 SET_ERR (nspace = tpls(i, 3).string_value (), err); | |
525 } | |
526 bool visible; | |
527 if (! err) | |
528 { | |
529 SET_ERR (visible = tpls(i, 4).bool_value (), err); | |
530 } | |
531 if (err) | |
532 { | |
533 c_verror ("octave_pq_get_enum_types: could not read returned result"); | |
468 return 1; | 534 return 1; |
469 } | 535 } |
470 | 536 |
471 // must be allocated and filled before creating the name map | 537 // must be allocated and filled before creating the name map |
472 // entry, to get a remaining location for the c-string used as | 538 // entry, to get a remaining location for the c-string used as |
488 // we trust there is always an array type in the table | 554 // we trust there is always an array type in the table |
489 oct_pq_conv_t *&by_oid = conv_map[oid], *&by_aoid = conv_map[aoid], | 555 oct_pq_conv_t *&by_oid = conv_map[oid], *&by_aoid = conv_map[aoid], |
490 *&by_name = name_conv_map[t_conv->name.c_str ()]; | 556 *&by_name = name_conv_map[t_conv->name.c_str ()]; |
491 if (by_oid || by_aoid || by_name) | 557 if (by_oid || by_aoid || by_name) |
492 { | 558 { |
493 error ("octave_pq_get_enum_types: internal error, key already in typemap"); | 559 c_verror ("octave_pq_get_enum_types: internal error, key already in typemap"); |
494 if (! by_oid) conv_map.erase (oid); | 560 if (! by_oid) conv_map.erase (oid); |
495 if (! by_aoid) conv_map.erase (aoid); | 561 if (! by_aoid) conv_map.erase (aoid); |
496 if (! by_name) name_conv_map.erase (t_conv->name.c_str ()); | 562 if (! by_name) name_conv_map.erase (t_conv->name.c_str ()); |
497 delete t_conv; | 563 delete t_conv; |
498 return 1; | 564 return 1; |
537 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 603 BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
538 PQfinish (t_conn); | 604 PQfinish (t_conn); |
539 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; | 605 END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; |
540 } | 606 } |
541 | 607 |
542 error ("octave_pq_refresh_types: could not read types"); | 608 c_verror ("octave_pq_refresh_types: could not read types"); |
543 return 1; | 609 return 1; |
544 } | 610 } |
545 else | 611 else |
546 return 0; | 612 return 0; |
547 } | 613 } |