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 }