1c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter/* microprotocols.c - minimalist and non-validating protocols implementation
2c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *
3c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
4c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *
5c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * This file is part of psycopg and was adapted for pysqlite. Federico Di
6c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * Gregorio gave the permission to use it within pysqlite under the following
7c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * license:
8c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *
9c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * This software is provided 'as-is', without any express or implied
10c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * warranty.  In no event will the authors be held liable for any damages
11c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * arising from the use of this software.
12c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *
13c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * Permission is granted to anyone to use this software for any purpose,
14c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * including commercial applications, and to alter it and redistribute it
15c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * freely, subject to the following restrictions:
16c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *
17c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * 1. The origin of this software must not be misrepresented; you must not
18c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *    claim that you wrote the original software. If you use this software
19c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *    in a product, an acknowledgment in the product documentation would be
20c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *    appreciated but is not required.
21c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * 2. Altered source versions must be plainly marked as such, and must not be
22c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter *    misrepresented as being the original software.
23c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter * 3. This notice may not be removed or altered from any source distribution.
24c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter */
25c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
26c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter#include <Python.h>
27c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter#include <structmember.h>
28c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
29c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter#include "cursor.h"
30c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter#include "microprotocols.h"
31c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter#include "prepare_protocol.h"
32c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
33c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
34c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter/** the adapters registry **/
35c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
36c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony BaxterPyObject *psyco_adapters;
37c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
386e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häring/* pysqlite_microprotocols_init - initialize the adapters dictionary */
39c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
40c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxterint
416e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häringpysqlite_microprotocols_init(PyObject *dict)
42c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter{
43c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* create adapters dictionary and put it in module namespace */
44c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    if ((psyco_adapters = PyDict_New()) == NULL) {
45c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        return -1;
46c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    }
47c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
4872289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter    return PyDict_SetItemString(dict, "adapters", psyco_adapters);
49c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter}
50c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
51c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
526e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häring/* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */
53c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
54c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxterint
556e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häringpysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast)
56c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter{
57c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    PyObject* key;
588e7b4908901e30f594e52d5fdcdc8b4e2d274ff1Anthony Baxter    int rc;
59c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
600741a60ca7b332b755d8a6b3328da414f963f7b4Gerhard Häring    if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType;
61c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
62c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    key = Py_BuildValue("(OO)", (PyObject*)type, proto);
6372289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter    if (!key) {
6472289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter        return -1;
6572289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter    }
6672289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter
678e7b4908901e30f594e52d5fdcdc8b4e2d274ff1Anthony Baxter    rc = PyDict_SetItem(psyco_adapters, key, cast);
68c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    Py_DECREF(key);
69c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
708e7b4908901e30f594e52d5fdcdc8b4e2d274ff1Anthony Baxter    return rc;
71c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter}
72c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
736e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häring/* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */
74c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
75c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony BaxterPyObject *
766e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häringpysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt)
77c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter{
78c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    PyObject *adapter, *key;
79c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
80c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* we don't check for exact type conformance as specified in PEP 246
810741a60ca7b332b755d8a6b3328da414f963f7b4Gerhard Häring       because the pysqlite_PrepareProtocolType type is abstract and there is no
82c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter       way to get a quotable object to be its instance */
83c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
84c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* look for an adapter in the registry */
85c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto);
8672289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter    if (!key) {
8772289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter        return NULL;
8872289a616c90949f7a2d3b2af12cd1044e64717dAnthony Baxter    }
89c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    adapter = PyDict_GetItem(psyco_adapters, key);
90c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    Py_DECREF(key);
91c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    if (adapter) {
92c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL);
93c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        return adapted;
94c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    }
95c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
96c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* try to have the protocol adapt this object*/
97c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    if (PyObject_HasAttrString(proto, "__adapt__")) {
98c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj);
99c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        if (adapted) {
100c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            if (adapted != Py_None) {
101c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter                return adapted;
102c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            } else {
103c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter                Py_DECREF(adapted);
104c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            }
105c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        }
106c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
107c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError))
108c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            return NULL;
109c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    }
110c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
111c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* and finally try to have the object adapt itself */
112c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    if (PyObject_HasAttrString(obj, "__conform__")) {
113c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto);
114c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        if (adapted) {
115c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            if (adapted != Py_None) {
116c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter                return adapted;
117c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            } else {
118c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter                Py_DECREF(adapted);
119c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            }
120c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        }
121c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
122c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) {
123c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter            return NULL;
124c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter        }
125c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    }
126c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
127c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    /* else set the right exception and return NULL */
1280741a60ca7b332b755d8a6b3328da414f963f7b4Gerhard Häring    PyErr_SetString(pysqlite_ProgrammingError, "can't adapt");
129c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    return NULL;
130c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter}
131c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
132c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter/** module-level functions **/
133c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
134c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony BaxterPyObject *
1356e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häringpysqlite_adapt(pysqlite_Cursor *self, PyObject *args)
136c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter{
137c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    PyObject *obj, *alt = NULL;
1380741a60ca7b332b755d8a6b3328da414f963f7b4Gerhard Häring    PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType;
139c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter
140c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter    if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL;
1416e1afcf9883f13bdf8808dc528e381f5c90a131bGerhard Häring    return pysqlite_microprotocols_adapt(obj, proto, alt);
142c51ee69b27a35bb45e501766dd33674eae7ddb30Anthony Baxter}
143