1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901
|
/* KInterbasDB Python Package - Implementation of SQL Statement Execution, etc.
**
** Version 3.1
**
** The following contributors hold Copyright (C) over their respective
** portions of code (see license.txt for details):
**
** [Original Author (maintained through version 2.0-0.3.1):]
** 1998-2001 [alex] Alexander Kuznetsov <alexan@users.sourceforge.net>
** [Maintainers (after version 2.0-0.3.1):]
** 2001-2002 [maz] Marek Isalski <kinterbasdb@maz.nu>
** 2002-2004 [dsr] David Rushby <woodsplitter@rocketmail.com>
** [Contributors:]
** 2001 [eac] Evgeny A. Cherkashin <eugeneai@icc.ru>
** 2001-2002 [janez] Janez Jere <janez.jere@void.si>
*/
/****************** "PRIVATE" DECLARATIONS:BEGIN *******************/
static int _prepare_statement_if_necessary(CursorObject *cursor, PyObject *sql);
static boolean _check_statement_length(long length);
static int determine_statement_type(
isc_stmt_handle *statementHandle, ISC_STATUS statusVector[]
);
/****************** "PRIVATE" DECLARATIONS:END *******************/
/* For an explanation of this function's purpose, see the documentation for
** Python function kinterbasdb.create_database. */
static PyObject *pyob_create_database( PyObject *self, PyObject *args ) {
ConnectionObject *con;
char *sql = NULL;
int sql_len = -1;
short dialect = 0;
if ( !PyArg_ParseTuple(args, "s#|h", &sql, &sql_len, &dialect) ) {
return NULL;
}
if (!_check_statement_length(sql_len)) {
return NULL;
}
/* A negative value for the dialect is not acceptable because the IB/FB API
** requires an UNSIGNED SHORT. */
if (dialect < 0) {
raise_exception(ProgrammingError, "con dialect must be > 0");
return NULL;
}
con = new_connection();
if (con == NULL) {
/* The new_connection function will already have set an exception. */
return NULL;
}
/* conn->dialect is set to a default value in the new_connection
** function, so we only need to change it if we received a dialect argument
** to this function. */
if (dialect > 0) {
con->dialect = (unsigned short) dialect;
}
assert (con->dialect > 0);
ENTER_DB
isc_dsql_execute_immediate(
con->status_vector,
/* 2003.04.27: CREATE DATABASE will never be issued from a distributed
** transaction, so we do not use CON_GET_TRANS_HANDLE_ADDR below. */
&con->db_handle,
&con->trans_handle,
(unsigned short) sql_len,
sql,
con->dialect,
NULL
);
LEAVE_DB
if ( DB_API_ERROR(con->status_vector) ) {
raise_sql_exception(ProgrammingError, "pyob_create_database: ",
con->status_vector
);
pyob_connection_del( (PyObject *) con );
return NULL;
} else {
con->_state = CONNECTION_STATE_OPEN;
return (PyObject *) con;
}
} /* pyob_create_database */
/* For an explanation of this function's purpose, see the documentation for
** Python function kinterbasdb.drop_database. */
static PyObject *pyob_drop_database( PyObject *self, PyObject *args ) {
ConnectionObject *con;
if ( !PyArg_ParseTuple(args, "O!", &ConnectionType, &con) ) {
return NULL;
}
CONN_REQUIRE_OPEN(con);
/* CONN_REQUIRE_OPEN should enforce non-null db_handle, but assert anyway: */
assert (con->db_handle != NULL);
/* Already enforced at Python level: */
assert (con->group == NULL);
/* If there's an unresolved transaction, roll it back before dropping the
** database. Otherwise, the database would be dropped and then the
** connection would attempt to roll back the transaction in close_connection
** (called by the destructor delete_connection), resulting in subtle memory
** corruption. */
if (OP_RESULT_OK !=
rollback_transaction(con->trans_handle, FALSE, TRUE, con->status_vector)
)
{
return NULL;
}
con->trans_handle = NULL; /* 2003.10.14 */
/* 2003.10.15: begin block */
/* Normally, free_field_precision_cache will involve calls to
** isc_dsql_free_statement, so it *must* be performed before the database
** handle is invalidated. */
#ifdef DETERMINE_FIELD_PRECISION
free_field_precision_cache( con->desc_cache,
TRUE, /* Yes, it *should* try to free the statement handles. */
con->status_vector
);
con->desc_cache = NULL;
#endif
/* 2003.10.15: end block */
ENTER_DB
isc_drop_database( con->status_vector, &(con->db_handle) );
LEAVE_DB
if ( DB_API_ERROR(con->status_vector) ) {
raise_sql_exception(OperationalError, "pyob_drop_database: ",
con->status_vector);
return NULL;
}
con->db_handle = NULL; /* 2003.10.08 */
con->_state = CONNECTION_STATE_CLOSED; /* 2003.10.14 */
RETURN_PY_NONE;
} /* pyob_drop_database */
/* 2002.02.25:
** execute_immediate in the context of a con.
** Like isc_dsql_execute_immediate (which it wraps), this function cannot
** execute SQL statements that return result sets.
**
** It would be easy to separately wrap isc_dsql_exec_immed2, which can return
** up to one row of output, but I don't see the point. Note that
** isc_dsql_exec_immed2 would have to be SEPARATELY wrapped, because here
** (unlike in pyob_execute), we don't have a prepared representation of
** the query, and therefore CANNOT do a similar dynamic selection of execution
** function, for we don't know the statement type. */
static PyObject *pyob_execute_immediate (
PyObject *self, PyObject *args
) {
ConnectionObject *con;
char *sql = NULL;
int sql_len = -1;
if ( !PyArg_ParseTuple( args, "O!s#", &ConnectionType, &con, &sql, &sql_len ) ) {
return NULL;
}
CONN_REQUIRE_OPEN(con);
/* 2003.02.17b: */
if (CON_GET_TRANS_HANDLE(con) == NULL) { /* 2003.10.15a:OK */
/* The Python layer of kinterbasdb should have prevented this from happening. */
raise_exception(InternalError, "pyob_execute_immediate: null transaction");
return NULL;
}
if (!_check_statement_length(sql_len)) {
return NULL;
}
{
/* 2003.10.15a: Don't call CON_GET_TRANS_HANDLE[_ADDR] without GIL. */
isc_tr_handle *trans_handle_addr = CON_GET_TRANS_HANDLE_ADDR(con);
ENTER_DB
isc_dsql_execute_immediate( con->status_vector,
&con->db_handle,
trans_handle_addr,
(unsigned short) sql_len,
sql,
con->dialect,
NULL
);
LEAVE_DB
}
if ( DB_API_ERROR(con->status_vector) ) {
raise_sql_exception( ProgrammingError,
"isc_dsql_execute_immediate: ", con->status_vector
);
return NULL;
}
RETURN_PY_NONE;
} /* pyob_execute_immediate */
static PyObject *pyob_execute( PyObject *self, PyObject *args ) {
/* This function returns a Python DB API description tuple upon successful
** execution of a result-set-returning statement (that is, a query), or
** None upon successful execution of any other statement. It sets a
** Python exception and returns NULL in case of failure. */
PyObject *cursor_description;
CursorObject *cursor;
ConnectionObject *conn; /* Just a lookup cache. */
PyObject *sql = NULL; /* Either PyString or PyUnicode. */
PyObject *params = NULL;
int statementType;
if ( !PyArg_ParseTuple( args, "O!OO", &CursorType, &cursor, &sql, ¶ms ) ) {
return NULL;
}
CUR_REQUIRE_OPEN(cursor);
conn = cursor->connection;
/* For $params, accept any sequence except a string. */
if ( !PySequence_Check(params) ) {
raise_exception( InterfaceError, "input parameter container is not a sequence" );
return NULL;
}
if ( PyString_Check(params) ) {
raise_exception( InterfaceError, "input parameter sequence cannot be a string" );
return NULL;
}
#ifdef KIDB_DEBUGGERING /* 2003.09.06 */
{
PyObject *sql_str = PyObject_Str(sql);
PyObject *params_str = PyObject_Str(params);
fprintf(stderr, "{SQL TRACE:\n [%s]\n with params\n %s\n}\n",
PyString_AS_STRING(sql_str), PyString_AS_STRING(params_str)
);
Py_DECREF(sql_str);
Py_DECREF(params_str);
}
#endif /* KIDB_DEBUGGERING */
/* If this cursor was associated with a previous statement,
** "freshen" it up so that it can deal can deal with another statement
** execution (possibly of the same SQL statement, with different input
** parameters) and perhaps also retrieve another result set. */
clear_cursor(cursor, sql);
/* 2003.02.17b: */
if (CON_GET_TRANS_HANDLE(conn) == NULL) { /* 2003.10.15a:OK */
/* The Python layer of kinterbasdb should have prevented this from happening. */
raise_exception(InternalError, "pyob_execute: null transaction");
return NULL;
}
if ( 0 != _prepare_statement_if_necessary(cursor, sql) ) {
/* Note that this cleanup route excludes the
** free_XSQLVAR_dynamically_allocated_memory call. */
goto EXECUTE_ERROR_CLEANUP_EXCEPT_DYNVARALLOC;
}
/* Convert the Python input arguments to their XSQLVAR equivalents. */
if ( PyObject2XSQLDA(cursor, cursor->in_sqlda, params) < 0 ) {
goto EXECUTE_ERROR_CLEANUP;
}
/* 2002.08.19: allocate_output_buffer call was originally here; I moved
** it to within _prepare_statement_if_necessary. */
/* 2002.01.01:
** It looks like the original author was dealing with some similar
** EXECUTE PROCEDURE troubles, but they weren't the same as the one I'm
** here to fix.
**
** The fact that there are output fields (that is,
** cursors[cur].in_sqlda->sqld is >= 1) does not guarantee that the
** statement is compatible with a standard SELECT-fetch approach; it
** could be an EXECUTE on a stored procedure with output params.
**
** Special case:
** The cursor's statement type is isc_info_sql_stmt_exec_procedure
** and it has at least one output parameter.
**
** Unlike a SELECT statement whose target is a stored procedure, an
** EXECUTE PROCEDURE statement must not return more than one row.
** This is because such a procedure must be executed with
** isc_dsql_execute2, which returns its results immediately and is
** therefore not compatible with a standard execute-fetch approach.
**
** However, I later (2002.02.21) imposed the "appearance of execute-fetch"
** on even this special case by caching the results in the cursor object
** and returning the ONE *cached* row if/when fetch is called.
** This behavior was set up in order to satisfy the Python DB API spec.
**
** kinterbasdb up to and including version 2.0-0.3.1 would choke with an
** exception instead of behaving in the standard way. It did so because
** it tried to execute the procedure in this special case with
** isc_dsql_execute rather than isc_dsql_execute2. That appeared to work
** fine during the execution step, but gagged if/when fetch was
** subsequently called.
*/
/* 2003.01.26: The statement type is now cached by the cursor; it need not
** be recomputed every time. */
statementType = cursor->statement_type;
assert (statementType != NULL_STATEMENT_TYPE);
debug_printf1( "[in pyob_execute] STATEMENT TYPE: %d\n", statementType );
if ( statementType == isc_info_sql_stmt_exec_procedure
&& cursor->out_sqlda->sqld > 0
)
{
/* 2002.01.01:
** The crucial difference between isc_dsql_execute and
** isc_dsql_execute2 is that the latter loads information about the
** first output row into the output structures immediately, without
** waiting for a call to isc_dsql_fetch(). It is IMPORTANT to prevent
** isc_dsql_fetch from being called on a cursor that has been executed
** with isc_dsql_execute2.
** 2002.02.21:
** Although it is true that isc_dsql_fetch must not be called on a cursor
** that has been executed with isc_dsql_execute2, we must impose the
** appearance of that behavior in order to satisfy the Python DB API
** Specification 2.0, which does not allow a direct return of stored
** procedure results unless they are output parameters or
** input/output parameters (in the sense that a client variables is passed
** in and its memory space if filled with the output value). IB and FB
** lack such "shared memory space" parameters, so even though we have
** the result row immediately after calling isc_dsql_execute2, we do not
** return it directly but instead save it and wait for a possible fetch
** call at some later point.
** The current implementation caches the single result row from
** isc_dsql_execute2 in cursor->exec_proc_results. */
{
/* 2003.10.15a: Don't call CON_GET_TRANS_HANDLE[_ADDR] without GIL. */
isc_tr_handle *trans_handle_addr = CON_GET_TRANS_HANDLE_ADDR(conn);
ENTER_DB
isc_dsql_execute2( cursor->status_vector,
trans_handle_addr,
&(cursor->stmt_handle),
conn->dialect,
cursor->in_sqlda,
cursor->out_sqlda
);
LEAVE_DB
}
debug_dump_status_vector(cursor->status_vector);
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( ProgrammingError,
"isc_dsql_execute2: ", cursor->status_vector
);
goto EXECUTE_ERROR_CLEANUP;
}
/* First, cache the result of the procedure call so that it is available
** if and when fetch is called in the future. */
cursor->exec_proc_results = XSQLDA2Tuple(cursor, cursor->out_sqlda);
if (cursor->exec_proc_results == NULL) {
goto EXECUTE_ERROR_CLEANUP;
}
/* Next, return the description (but not the results, as the initial
** fix from circa 2002.01.01 was doing), just as would be done in the
** case of a normal result-returning query (which we are crudely
** simulating via the cursor->exec_proc_results cache variable). */
cursor_description = XSQLDA2Description(cursor->out_sqlda, cursor);
if (cursor_description == NULL) goto EXECUTE_ERROR_CLEANUP;
return cursor_description;
} else { /* Everything except the special case(s) defined above. */
{
/* 2003.10.15a: Don't call CON_GET_TRANS_HANDLE[_ADDR] without GIL. */
isc_tr_handle *trans_handle_addr = CON_GET_TRANS_HANDLE_ADDR(conn);
ENTER_DB
isc_dsql_execute( cursor->status_vector, trans_handle_addr,
&cursor->stmt_handle, conn->dialect, cursor->in_sqlda
);
LEAVE_DB
}
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( ProgrammingError, "isc_dsql_execute: ",
cursor->status_vector
);
goto EXECUTE_ERROR_CLEANUP;
}
}
assert ( DB_API_ERROR(cursor->status_vector) == FALSE );
/* YYY:2002.02.21:
** (as part of fix for bug #520793)
** Conceptually, there should be an error in the status vector at this
** point in cases where
** a SELECT statement whose target is
** a stored procedure
** that raises an IB user-defined EXCEPTION
** has just been executed. However, said exception is present ONLY
** conceptually, not really.
**
** Apparently, the IB API only "realizes" that a user-defined EXCEPTION has
** been raised when it tries to fetch the first row of output from the
** stored procedure in question. Because of the way IB stored procedures
** work (generate... suspend; generate... suspend;), I can understand why
** the IB API works the way it does.
**
** This quirk explains why the branch of this function that uses
** isc_dsql_execute2 works as it conceptually should (i.e., it "realizes"
** that a user-defined exception has been raised as soon as it is
** conceptually raised), and why the branch that uses isc_dsql_execute--
** the variant that does not immediately fetch the first row of output--
** does not raise an error until fetch is called (and fetch may never be
** called!).
**
** Here is the basic problem: suppose a user executes a statement like:
** SELECT * FROM PROCEDURE_THAT_RAISES_EXCEPTION
** , but the user happens not to call fetch (i.e., decides to ignore the
** result set). In such a case, the user would never know that an
** exception had been raised, because the IB API itself would never
** register the fact that an exception had taken place.
**
** I've searched extensively for a way to fix this, but haven't found one.
*/
if (cursor->out_sqlda->sqld == 0) {
/* The DB API spec says of Cursor.description: "This attribute will be
** None for operations that do not return rows...". */
Py_INCREF(Py_None);
cursor_description = Py_None;
} else {
cursor_description = XSQLDA2Description(cursor->out_sqlda, cursor);
if (cursor_description == NULL) goto EXECUTE_ERROR_CLEANUP;
}
/* In case of success, deliberately fall through into EXECUTE_NORMAL_RETURN. */
/* EXECUTE_NORMAL_RETURN: */
if ( free_XSQLVAR_dynamically_allocated_memory(cursor) != 0 ) {
goto EXECUTE_ERROR_CLEANUP_EXCEPT_DYNVARALLOC;
}
return cursor_description;
EXECUTE_ERROR_CLEANUP:
free_XSQLVAR_dynamically_allocated_memory(cursor);
EXECUTE_ERROR_CLEANUP_EXCEPT_DYNVARALLOC:
/* Note that the cursor is closed AFTER the call to
** free_XSQLVAR_dynamically_allocated_memory. */
close_cursor_with_error(cursor); /* 2003.02.17c: */
return NULL;
} /* pyob_execute */
static int _prepare_statement_if_necessary(
CursorObject *cursor, PyObject *sql
)
{
ConnectionObject *conn = cursor->connection;
assert (CON_GET_TRANS_HANDLE(conn) != NULL); /* 2003.10.15a:OK */
assert (cursor->_state == CURSOR_STATE_CLOSED);
/* If this is another execution of the previous statement, no new preparation
** is necessary. */
{
PyObject *prev_sql = cursor->previous_sql;
if (prev_sql != NULL) {
/* If the PyObject pointers point to the same memory location, the two
** objects are certainly equal--in fact, they're IDentical
** (id(prev_sql) == id(sql)). If the pointers refer to different memory
** locations, the two objects are still equal if their contents match. */
if (sql == prev_sql || PyObject_Compare(sql, prev_sql) == 0) {
cursor->_state = CURSOR_STATE_OPEN;
return 0;
}
}
}
if ( !( PyString_Check(sql) || PyUnicode_Check(sql) ) ) {
raise_exception(PyExc_TypeError, "SQL must be string or unicode object.");
return -1;
}
/* Free the old statement (if any) and any resources the cursor was caching
** in association with the old statement, including its output buffer. */
close_cursor(cursor);
/* Moved statement allocation here from new_cursor in order to defer it.
** (The deferment makes cursor cleanup code much cleaner.) */
/* Allocate new statement handle. */
assert(cursor->stmt_handle == NULL);
ENTER_DB
isc_dsql_allocate_statement( cursor->status_vector,
&(conn->db_handle),
&(cursor->stmt_handle)
);
LEAVE_DB
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( OperationalError,
"pyob_execute.isc_dsql_allocate_statement: ", cursor->status_vector
);
return -1;
}
assert(cursor->stmt_handle != NULL);
{
/* translated_sql will only become non-NULL if $sql is a Unicode object
** rather than a string (and therefore must be translated to ASCII before
** being passed to isc_dsql_prepare).
** Since translated_sql, when non-NULL, refers to a *new* PyStringObject, it
** is unconditionally Py_XDECREFed at the end of this block. */
PyObject *translated_sql = NULL;
char *sql_raw_buffer = NULL;
int sql_len = -1;
if ( PyString_Check(sql) ) {
sql_raw_buffer = PyString_AS_STRING(sql);
sql_len = PyString_GET_SIZE(sql);
} else {
/* At this point, $sql is certain to be a unicode object, because its
** type was constrained to either string or unicode at the beginning of
** this function. */
/* 2003.10.14:
** Ideally, we would pass the database engine's C API the incoming SQL
** statement without converting it to ASCII (i.e., via
** PyUnicode_AsWideChar or something similar), but it seems that the C
** API doesn't accept anything but ASCII. */
/* PyUnicode_AsASCIIString creates a *new* PyStringObject. */
translated_sql = PyUnicode_AsASCIIString(sql);
if (translated_sql == NULL) {
return -1;
}
sql_raw_buffer = PyString_AS_STRING(translated_sql);
sql_len = PyString_GET_SIZE(translated_sql);
}
assert (sql_raw_buffer != NULL && sql_len >= 0);
if (!_check_statement_length(sql_len)) {
Py_XDECREF(translated_sql);
return -1;
}
/* Ask the database engine to compile the statement. */
{
/* 2003.10.15a: Don't call CON_GET_TRANS_HANDLE[_ADDR] without GIL. */
isc_tr_handle *trans_handle_addr = CON_GET_TRANS_HANDLE_ADDR(conn);
ENTER_DB
isc_dsql_prepare( cursor->status_vector,
trans_handle_addr,
&(cursor->stmt_handle),
(unsigned short) sql_len,
sql_raw_buffer,
conn->dialect,
cursor->out_sqlda
);
LEAVE_DB
}
Py_XDECREF(translated_sql);
} /* Ends block in which sql_raw_buffer is dealt with. */
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( ProgrammingError,
"isc_dsql_prepare: ", cursor->status_vector
);
return -1;
}
/* Ensure that the output XSQLDA has enough XSQLVAR slots for the statement's
** output variables. */
if ( reallocate_sqlda( &(cursor->out_sqlda), FALSE ) >= 0 ) {
/* Reallocation succeeded, so bind information about the OUTput XSQLDA's
** variables. */
ENTER_DB
isc_dsql_describe( cursor->status_vector,
&(cursor->stmt_handle),
conn->dialect,
cursor->out_sqlda /* OUTPUT */
);
LEAVE_DB
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( OperationalError,
"isc_dsql_describe for output params: ", cursor->status_vector
);
return -1;
}
} else {
/* Reallocation failed. */
return -1;
}
/* Bind information about the INput XSQLDA's variables. */
ENTER_DB
isc_dsql_describe_bind( cursor->status_vector,
&(cursor->stmt_handle),
conn->dialect,
cursor->in_sqlda /* INPUT */
);
LEAVE_DB
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( OperationalError,
"isc_dsql_describe_bind for input params: ", cursor->status_vector
);
return -1;
}
{
int input_sqlda_reallocation_result = reallocate_sqlda( &(cursor->in_sqlda), TRUE );
#ifdef KIDB_DEBUGGERING
printf("[in _prepare_statement_if_necessary] XSQLDA has: %d; needs: %d;"
" reallocation result: %d\n",
cursor->in_sqlda->sqln, cursor->in_sqlda->sqld, input_sqlda_reallocation_result
);
#endif
if (input_sqlda_reallocation_result == 0) {
/* No actual reallocation was necessary, so there's no need to rebind. */
} else if (input_sqlda_reallocation_result == 1) {
/* Reallocation was necessary, so the XSQLDA's parameter information must
** be rebound. */
ENTER_DB
isc_dsql_describe_bind( cursor->status_vector,
&(cursor->stmt_handle),
conn->dialect,
cursor->in_sqlda /* INPUT */
);
LEAVE_DB
if ( DB_API_ERROR(cursor->status_vector) ) {
raise_sql_exception( OperationalError,
"isc_dsql_describe_bind[2] for input params: ", cursor->status_vector
);
return -1;
}
} else {
/* Reallocation failed. */
return -1;
}
}
/* The statement needed to be prepared anew, so we must now update the
** cursor's cache.
** IMPORTANT: The cache is not updated until this point, near the END of
** this function, because all of the compilation preliminaries must first be
** hashed out.
*/
free_cursor_cache(cursor);
{
XSQLVAR *sqlvar;
OriginalXSQLVARSpecificationCache *spec_cache;
short var_no, column_count;
column_count = cursor->in_sqlda->sqld;
/* 2003.03.31: */
cursor->in_var_orig_spec = kimem_plain_malloc(
sizeof(OriginalXSQLVARSpecificationCache) * column_count
);
for ( sqlvar = cursor->in_sqlda->sqlvar, var_no = 0,
spec_cache = cursor->in_var_orig_spec;
var_no < column_count;
sqlvar++, var_no++, spec_cache++
)
{
spec_cache->sqltype = sqlvar->sqltype;
spec_cache->sqllen = sqlvar->sqllen;
}
}
Py_XDECREF(cursor->previous_sql); /* 2003.02.13 */
Py_INCREF(sql);
cursor->previous_sql = sql;
/* 2003.01.26: Determine the database API's internal type code for this
** statement and cache that code in the cursor. */
cursor->statement_type = determine_statement_type(
&(cursor->stmt_handle), cursor->status_vector
);
/* If this is a query statement, allocate a buffer for the output values.
** Ensure that this function freed the output buffer (via close_cursor)
** before it prepared the new statement. */
assert (cursor->out_buffer == NULL);
if (cursor->out_sqlda->sqld > 0) {
cursor->out_buffer = allocate_output_buffer(cursor->out_sqlda);
if (cursor->out_buffer == NULL) {
return -1;
}
}
/* Done updating cursor's cache. */
/* The cursor was closed before we prepared the new statement; it is now
** open, and must be flagged accordingly. */
cursor->_state = CURSOR_STATE_OPEN;
return 0;
} /* _prepare_statement_if_necessary */
static int determine_statement_type(
isc_stmt_handle *statementHandle, ISC_STATUS statusVector[]
)
{
/* Dynamically determine the statement type. Follows p. 343 of IB Beta 6
** API Guide and IB example apifull.c. */
int statementType;
int statementTypeLength;
static char sqlInfoStatementTypeRequest[] = { isc_info_sql_stmt_type };
char sqlInfoResultBuffer[ ISC_INFO_BUFFER_SIZE ];
ENTER_DB
isc_dsql_sql_info( statusVector, statementHandle,
sizeof(sqlInfoStatementTypeRequest),
sqlInfoStatementTypeRequest,
sizeof(sqlInfoResultBuffer),
sqlInfoResultBuffer
);
/* Next two lines follow the Interbase example apifull.c rather than the
** API Guide. */
statementTypeLength = (short)(
isc_vax_integer( (char *) sqlInfoResultBuffer + 1, 2 )
);
statementType = (int) (
isc_vax_integer( (char *) sqlInfoResultBuffer + 3,
(short)statementTypeLength
)
);
LEAVE_DB
return statementType;
} /* determine_statement_type */
/* 2003.05.15: */
static PyObject *pyob_rowcount( PyObject *self, PyObject *args ) {
CursorObject *cur;
int cursor_stmt_type;
char request_params[] = {isc_info_sql_records, isc_info_end};
/* YYY: The fixed size of res_buf introduces the possibility of a buffer
** overflow, but it's extremely unlikely because we know quite a bit about
** the size requirements (they're not affected by input from the client
** programmer, or anything like that). */
char res_buf[256];
char *res_walk;
long cur_count = -1;
char cur_count_type; /* What type of statement does this count concern? */
short length_of_cur_count_in_buffer;
if ( !PyArg_ParseTuple( args, "O!", &CursorType, &cur ) ) {
return NULL;
}
cursor_stmt_type = cur->statement_type;
if (cursor_stmt_type == NULL_STATEMENT_TYPE) {
/* Python DB API Spec requires us to return -1 rather than raise exception. */
return PyInt_FromLong(-1);
}
assert(cur->stmt_handle != NULL);
if ( cursor_stmt_type != isc_info_sql_stmt_select
&& cursor_stmt_type != isc_info_sql_stmt_insert
&& cursor_stmt_type != isc_info_sql_stmt_update
&& cursor_stmt_type != isc_info_sql_stmt_delete
)
{
/* Python DB API Spec requires us to return -1 rather than raise exception. */
return PyInt_FromLong(-1);
}
ENTER_DB
isc_dsql_sql_info( cur->status_vector,
&cur->stmt_handle,
sizeof(request_params), request_params,
sizeof(res_buf), res_buf
);
LEAVE_DB
if ( DB_API_ERROR(cur->status_vector) ) {
raise_sql_exception(OperationalError, "pyob_rowcount: ", cur->status_vector);
return NULL;
}
/* res_buf[0] indicates what type of information is being returned (in this
** situation, it never varies). */
assert (res_buf[0] == isc_info_sql_records);
/* Start res_walk after the first 3 bytes, which are infrastructural. */
res_walk = res_buf + 3;
while ( (cur_count_type = *res_walk) != isc_info_end ) {
res_walk += 1;
length_of_cur_count_in_buffer = (short) isc_vax_integer(res_walk, sizeof(short));
res_walk += sizeof(short);
cur_count = isc_vax_integer(res_walk, length_of_cur_count_in_buffer);
res_walk += length_of_cur_count_in_buffer;
/* If the count that we've just extracted from the result buffer concerns
** the same statement type as the last statement executed by the cursor,
** immediately return that count to the Python level.
** All temporary storage in this function is allocated on the stack, so
** there's nothing for us to manually release. */
if (
( cur_count_type == isc_info_req_select_count
&& cursor_stmt_type == isc_info_sql_stmt_select
) || (
cur_count_type == isc_info_req_insert_count
&& cursor_stmt_type == isc_info_sql_stmt_insert
) || (
cur_count_type == isc_info_req_update_count
&& cursor_stmt_type == isc_info_sql_stmt_update
) || (
cur_count_type == isc_info_req_delete_count
&& cursor_stmt_type == isc_info_sql_stmt_delete
)
)
{
return PyInt_FromLong(cur_count);
}
} /* end of "while not at end of result buffer..." loop */
/* Because of the "guards" near the beginning of this function, it is not
** expected that this code will ever be reached. However, a future version
** of the database engine may throw a curveball at us, so we'll behave as
** the Python DB API requires us to behave in cases where the row count
** cannot be determined (that is, return -1). */
return PyInt_FromLong(-1);
} /* pyob_rowcount */
/* 2003.02.20: Although the sql-statement-length parameter to such Firebird
** API functions as isc_dsql_prepare and isc_dsql_execute_immediate is an
** unsigned short, the documentation says that the length can be left zero for
** null-terminated strings, in which case the database engine will figure out
** the length itself.
** As of 2003.02.13, Firebird cannot handle SQL statements longer than the
** maximum value of an unsigned short even if zero is passed as the length. */
static boolean _check_statement_length(long length) {
/* Test the length and raise an exception if it's too long for safe passage
** to isc_* functions. Return TRUE if OK; FALSE otherwise. */
if (length > (long) USHRT_MAX) {
char *err_msg = NULL;
#if PYTHON_2_2_OR_LATER
PyObject *buffer = PyString_FromFormat(
"SQL statement of %ld bytes is too long (max %d allowed). Consider"
" using parameters to shorten the SQL code, rather than passing large"
" values as part of the SQL string.",
length, USHRT_MAX
);
if (buffer == NULL) {
return FALSE;
}
err_msg = PyString_AS_STRING(buffer);
#else
err_msg = "Length of SQL statement must be <= USHRT_MAX";
#endif /* PYTHON_2_2_OR_LATER */
assert (err_msg != NULL);
raise_exception(ProgrammingError, err_msg);
#if PYTHON_2_2_OR_LATER
Py_DECREF(buffer);
#endif
return FALSE;
}
return TRUE;
} /* _validate_statement_length */
|