|
22 | 22 | */
|
23 | 23 |
|
24 | 24 | #include "cursor.h"
|
| 25 | +#include "microprotocols.h" |
25 | 26 | #include "module.h"
|
26 | 27 | #include "util.h"
|
27 | 28 |
|
| 29 | +typedef enum { |
| 30 | + TYPE_LONG, |
| 31 | + TYPE_FLOAT, |
| 32 | + TYPE_UNICODE, |
| 33 | + TYPE_BUFFER, |
| 34 | + TYPE_UNKNOWN |
| 35 | +} parameter_type; |
| 36 | + |
28 | 37 | #define clinic_state() (pysqlite_get_state_by_type(Py_TYPE(self)))
|
29 | 38 | #include "clinic/cursor.c.h"
|
30 | 39 | #undef clinic_state
|
@@ -506,6 +515,245 @@ stmt_step(sqlite3_stmt *statement)
|
506 | 515 | return rc;
|
507 | 516 | }
|
508 | 517 |
|
| 518 | +static int |
| 519 | +bind_param(pysqlite_Statement *self, int pos, PyObject *parameter) |
| 520 | +{ |
| 521 | + int rc = SQLITE_OK; |
| 522 | + const char *string; |
| 523 | + Py_ssize_t buflen; |
| 524 | + parameter_type paramtype; |
| 525 | + |
| 526 | + if (parameter == Py_None) { |
| 527 | + rc = sqlite3_bind_null(self->st, pos); |
| 528 | + goto final; |
| 529 | + } |
| 530 | + |
| 531 | + if (PyLong_CheckExact(parameter)) { |
| 532 | + paramtype = TYPE_LONG; |
| 533 | + } else if (PyFloat_CheckExact(parameter)) { |
| 534 | + paramtype = TYPE_FLOAT; |
| 535 | + } else if (PyUnicode_CheckExact(parameter)) { |
| 536 | + paramtype = TYPE_UNICODE; |
| 537 | + } else if (PyLong_Check(parameter)) { |
| 538 | + paramtype = TYPE_LONG; |
| 539 | + } else if (PyFloat_Check(parameter)) { |
| 540 | + paramtype = TYPE_FLOAT; |
| 541 | + } else if (PyUnicode_Check(parameter)) { |
| 542 | + paramtype = TYPE_UNICODE; |
| 543 | + } else if (PyObject_CheckBuffer(parameter)) { |
| 544 | + paramtype = TYPE_BUFFER; |
| 545 | + } else { |
| 546 | + paramtype = TYPE_UNKNOWN; |
| 547 | + } |
| 548 | + |
| 549 | + switch (paramtype) { |
| 550 | + case TYPE_LONG: { |
| 551 | + sqlite_int64 value = _pysqlite_long_as_int64(parameter); |
| 552 | + if (value == -1 && PyErr_Occurred()) |
| 553 | + rc = -1; |
| 554 | + else |
| 555 | + rc = sqlite3_bind_int64(self->st, pos, value); |
| 556 | + break; |
| 557 | + } |
| 558 | + case TYPE_FLOAT: { |
| 559 | + double value = PyFloat_AsDouble(parameter); |
| 560 | + if (value == -1 && PyErr_Occurred()) { |
| 561 | + rc = -1; |
| 562 | + } |
| 563 | + else { |
| 564 | + rc = sqlite3_bind_double(self->st, pos, value); |
| 565 | + } |
| 566 | + break; |
| 567 | + } |
| 568 | + case TYPE_UNICODE: |
| 569 | + string = PyUnicode_AsUTF8AndSize(parameter, &buflen); |
| 570 | + if (string == NULL) |
| 571 | + return -1; |
| 572 | + if (buflen > INT_MAX) { |
| 573 | + PyErr_SetString(PyExc_OverflowError, |
| 574 | + "string longer than INT_MAX bytes"); |
| 575 | + return -1; |
| 576 | + } |
| 577 | + rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT); |
| 578 | + break; |
| 579 | + case TYPE_BUFFER: { |
| 580 | + Py_buffer view; |
| 581 | + if (PyObject_GetBuffer(parameter, &view, PyBUF_SIMPLE) != 0) { |
| 582 | + return -1; |
| 583 | + } |
| 584 | + if (view.len > INT_MAX) { |
| 585 | + PyErr_SetString(PyExc_OverflowError, |
| 586 | + "BLOB longer than INT_MAX bytes"); |
| 587 | + PyBuffer_Release(&view); |
| 588 | + return -1; |
| 589 | + } |
| 590 | + rc = sqlite3_bind_blob(self->st, pos, view.buf, (int)view.len, SQLITE_TRANSIENT); |
| 591 | + PyBuffer_Release(&view); |
| 592 | + break; |
| 593 | + } |
| 594 | + case TYPE_UNKNOWN: |
| 595 | + rc = -1; |
| 596 | + } |
| 597 | + |
| 598 | +final: |
| 599 | + return rc; |
| 600 | +} |
| 601 | + |
| 602 | +/* returns 0 if the object is one of Python's internal ones that don't need to be adapted */ |
| 603 | +static inline int |
| 604 | +need_adapt(pysqlite_state *state, PyObject *obj) |
| 605 | +{ |
| 606 | + if (state->BaseTypeAdapted) { |
| 607 | + return 1; |
| 608 | + } |
| 609 | + |
| 610 | + if (PyLong_CheckExact(obj) || PyFloat_CheckExact(obj) |
| 611 | + || PyUnicode_CheckExact(obj) || PyByteArray_CheckExact(obj)) { |
| 612 | + return 0; |
| 613 | + } else { |
| 614 | + return 1; |
| 615 | + } |
| 616 | +} |
| 617 | + |
| 618 | +static void |
| 619 | +bind_parameters(pysqlite_state *state, pysqlite_Statement *self, |
| 620 | + PyObject *parameters) |
| 621 | +{ |
| 622 | + PyObject* current_param; |
| 623 | + PyObject* adapted; |
| 624 | + const char* binding_name; |
| 625 | + int i; |
| 626 | + int rc; |
| 627 | + int num_params_needed; |
| 628 | + Py_ssize_t num_params; |
| 629 | + |
| 630 | + Py_BEGIN_ALLOW_THREADS |
| 631 | + num_params_needed = sqlite3_bind_parameter_count(self->st); |
| 632 | + Py_END_ALLOW_THREADS |
| 633 | + |
| 634 | + if (PyTuple_CheckExact(parameters) || PyList_CheckExact(parameters) || (!PyDict_Check(parameters) && PySequence_Check(parameters))) { |
| 635 | + /* parameters passed as sequence */ |
| 636 | + if (PyTuple_CheckExact(parameters)) { |
| 637 | + num_params = PyTuple_GET_SIZE(parameters); |
| 638 | + } else if (PyList_CheckExact(parameters)) { |
| 639 | + num_params = PyList_GET_SIZE(parameters); |
| 640 | + } else { |
| 641 | + num_params = PySequence_Size(parameters); |
| 642 | + if (num_params == -1) { |
| 643 | + return; |
| 644 | + } |
| 645 | + } |
| 646 | + if (num_params != num_params_needed) { |
| 647 | + PyErr_Format(state->ProgrammingError, |
| 648 | + "Incorrect number of bindings supplied. The current " |
| 649 | + "statement uses %d, and there are %zd supplied.", |
| 650 | + num_params_needed, num_params); |
| 651 | + return; |
| 652 | + } |
| 653 | + for (i = 0; i < num_params; i++) { |
| 654 | + if (PyTuple_CheckExact(parameters)) { |
| 655 | + PyObject *item = PyTuple_GET_ITEM(parameters, i); |
| 656 | + current_param = Py_NewRef(item); |
| 657 | + } else if (PyList_CheckExact(parameters)) { |
| 658 | + PyObject *item = PyList_GetItem(parameters, i); |
| 659 | + current_param = Py_XNewRef(item); |
| 660 | + } else { |
| 661 | + current_param = PySequence_GetItem(parameters, i); |
| 662 | + } |
| 663 | + if (!current_param) { |
| 664 | + return; |
| 665 | + } |
| 666 | + |
| 667 | + if (!need_adapt(state, current_param)) { |
| 668 | + adapted = current_param; |
| 669 | + } else { |
| 670 | + PyObject *protocol = (PyObject *)state->PrepareProtocolType; |
| 671 | + adapted = pysqlite_microprotocols_adapt(state, current_param, |
| 672 | + protocol, |
| 673 | + current_param); |
| 674 | + Py_DECREF(current_param); |
| 675 | + if (!adapted) { |
| 676 | + return; |
| 677 | + } |
| 678 | + } |
| 679 | + |
| 680 | + rc = bind_param(self, i + 1, adapted); |
| 681 | + Py_DECREF(adapted); |
| 682 | + |
| 683 | + if (rc != SQLITE_OK) { |
| 684 | + if (!PyErr_Occurred()) { |
| 685 | + PyErr_Format(state->InterfaceError, |
| 686 | + "Error binding parameter %d - " |
| 687 | + "probably unsupported type.", i); |
| 688 | + } |
| 689 | + return; |
| 690 | + } |
| 691 | + } |
| 692 | + } else if (PyDict_Check(parameters)) { |
| 693 | + /* parameters passed as dictionary */ |
| 694 | + for (i = 1; i <= num_params_needed; i++) { |
| 695 | + PyObject *binding_name_obj; |
| 696 | + Py_BEGIN_ALLOW_THREADS |
| 697 | + binding_name = sqlite3_bind_parameter_name(self->st, i); |
| 698 | + Py_END_ALLOW_THREADS |
| 699 | + if (!binding_name) { |
| 700 | + PyErr_Format(state->ProgrammingError, |
| 701 | + "Binding %d has no name, but you supplied a " |
| 702 | + "dictionary (which has only names).", i); |
| 703 | + return; |
| 704 | + } |
| 705 | + |
| 706 | + binding_name++; /* skip first char (the colon) */ |
| 707 | + binding_name_obj = PyUnicode_FromString(binding_name); |
| 708 | + if (!binding_name_obj) { |
| 709 | + return; |
| 710 | + } |
| 711 | + if (PyDict_CheckExact(parameters)) { |
| 712 | + PyObject *item = PyDict_GetItemWithError(parameters, binding_name_obj); |
| 713 | + current_param = Py_XNewRef(item); |
| 714 | + } else { |
| 715 | + current_param = PyObject_GetItem(parameters, binding_name_obj); |
| 716 | + } |
| 717 | + Py_DECREF(binding_name_obj); |
| 718 | + if (!current_param) { |
| 719 | + if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { |
| 720 | + PyErr_Format(state->ProgrammingError, |
| 721 | + "You did not supply a value for binding " |
| 722 | + "parameter :%s.", binding_name); |
| 723 | + } |
| 724 | + return; |
| 725 | + } |
| 726 | + |
| 727 | + if (!need_adapt(state, current_param)) { |
| 728 | + adapted = current_param; |
| 729 | + } else { |
| 730 | + PyObject *protocol = (PyObject *)state->PrepareProtocolType; |
| 731 | + adapted = pysqlite_microprotocols_adapt(state, current_param, |
| 732 | + protocol, |
| 733 | + current_param); |
| 734 | + Py_DECREF(current_param); |
| 735 | + if (!adapted) { |
| 736 | + return; |
| 737 | + } |
| 738 | + } |
| 739 | + |
| 740 | + rc = bind_param(self, i, adapted); |
| 741 | + Py_DECREF(adapted); |
| 742 | + |
| 743 | + if (rc != SQLITE_OK) { |
| 744 | + if (!PyErr_Occurred()) { |
| 745 | + PyErr_Format(state->InterfaceError, |
| 746 | + "Error binding parameter :%s - " |
| 747 | + "probably unsupported type.", binding_name); |
| 748 | + } |
| 749 | + return; |
| 750 | + } |
| 751 | + } |
| 752 | + } else { |
| 753 | + PyErr_SetString(PyExc_ValueError, "parameters are of unsupported type"); |
| 754 | + } |
| 755 | +} |
| 756 | + |
509 | 757 | PyObject *
|
510 | 758 | _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation, PyObject* second_argument)
|
511 | 759 | {
|
@@ -617,7 +865,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
|
617 | 865 |
|
618 | 866 | pysqlite_statement_mark_dirty(self->statement);
|
619 | 867 |
|
620 |
| - pysqlite_statement_bind_parameters(state, self->statement, parameters); |
| 868 | + bind_parameters(state, self->statement, parameters); |
621 | 869 | if (PyErr_Occurred()) {
|
622 | 870 | goto error;
|
623 | 871 | }
|
|
0 commit comments