Changeset 364


Ignore:
Timestamp:
Nov 21, 2008, 2:25:27 PM (11 years ago)
Author:
cito
Message:

Support for PQescapeStringConn and PQescapeByteaConn.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/docs/future.txt

    r361 r364  
    77-----
    88
    9 - Support PQescapeStringConn and PQescapeByteaConn
    10   (see also http://www.postgresql.org/docs/techdocs.49).
    119- Use PQescapeStringConn in the _quote() function of pg and pgdb
    1210  (escaping via backslash is not standard and produces warnings
  • trunk/docs/pg.txt

    r334 r364  
    304304  must be escaped to prevent them from being interpreted specially
    305305  by the SQL parser. `escape_string` performs this operation.
     306  Note that there is also a `pgobject` method with the same name
     307  which takes connection properties into account.
    306308
    307309.. caution:: It is especially important to do proper escaping when
     
    335337  As with `escape_string`, this is only used when inserting data directly
    336338  into an SQL command string.
     339  Note that there is also a `pgobject` method with the same name
     340  which takes connection properties into account.
    337341
    338342Example::
     
    966970
    967971Description:
    968   See the module function with the same name.
     972  Similar to the module function with the same name, but the
     973  behavior of this method is adjusted depending on the connection properties
     974  (such as character encoding).
    969975
    970976escape_bytea - escape binary data for use within SQL as type `bytea`
     
    981987
    982988Description:
    983   See the module function with the same name.
     989  Similar to the module function with the same name, but the
     990  behavior of this method is adjusted depending on the connection properties
     991  (in particular, whether standard-conforming strings are enabled).
    984992
    985993unescape_bytea -- unescape `bytea` data that has been retrieved as text
  • trunk/module/pg.py

    r359 r364  
    66# Improved by Christoph Zwerschke
    77#
    8 # $Id: pg.py,v 1.61 2008-11-21 13:10:51 cito Exp $
     8# $Id: pg.py,v 1.62 2008-11-21 19:25:27 cito Exp $
    99#
    1010
     
    189189            raise InternalError('Connection is not valid')
    190190
    191     # For convenience, define some module functions as static methods also:
    192     escape_string, escape_bytea, unescape_bytea = map(staticmethod,
    193         (escape_string, escape_bytea, unescape_bytea))
     191    # escape_string and escape_bytea exist as methods,
     192    # so we define unescape_bytea as a method as well
     193    unescape_bytea = staticmethod(unescape_bytea)
    194194
    195195    def _do_debug(self, s):
  • trunk/module/pgmodule.c

    r363 r364  
    11/*
    2  * $Id: pgmodule.c,v 1.84 2008-11-21 17:25:28 cito Exp $
     2 * $Id: pgmodule.c,v 1.85 2008-11-21 19:25:27 cito Exp $
    33 * PyGres, version 2.2 A Python interface for PostgreSQL database. Written by
    44 * D'Arcy J.M. Cain, (darcy@druid.net).  Based heavily on code written by
     
    27252725}
    27262726
     2727/* escape string */
     2728static char pg_escape_string__doc__[] =
     2729"pg_escape_string(str) -- escape a string for use within SQL.";
     2730
     2731static PyObject *
     2732pg_escape_string(pgobject *self, PyObject *args) {
     2733        char *from; /* our string argument */
     2734        char *to=NULL; /* the result */
     2735        int from_length; /* length of string */
     2736        int to_length; /* length of result */
     2737        PyObject *ret; /* string object to return */
     2738
     2739        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
     2740                return NULL;
     2741        to_length = 2*from_length + 1;
     2742        if (to_length < from_length) { /* overflow */
     2743                to_length = from_length;
     2744                from_length = (from_length - 1)/2;
     2745        }
     2746        to = (char *)malloc(to_length);
     2747        to_length = (int)PQescapeStringConn(self->cnx,
     2748                to, from, (size_t)from_length, NULL);
     2749        ret = Py_BuildValue("s#", to, to_length);
     2750        if (to)
     2751                free(to);
     2752        if (!ret) /* pass on exception */
     2753                return NULL;
     2754        return ret;
     2755}
     2756
     2757/* escape bytea */
     2758static char pg_escape_bytea__doc__[] =
     2759"pg_escape_bytea(data) -- escape binary data for use within SQL as type bytea.";
     2760
     2761static PyObject *
     2762pg_escape_bytea(pgobject *self, PyObject *args) {
     2763        unsigned char *from; /* our string argument */
     2764        unsigned char *to; /* the result */
     2765        int from_length; /* length of string */
     2766        size_t to_length; /* length of result */
     2767        PyObject *ret; /* string object to return */
     2768
     2769        if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
     2770                return NULL;
     2771        to = PQescapeByteaConn(self->cnx, from, (int)from_length, &to_length);
     2772        ret = Py_BuildValue("s", to);
     2773        if (to)
     2774                PQfreemem((void *)to);
     2775        if (!ret) /* pass on exception */
     2776                return NULL;
     2777        return ret;
     2778}
     2779
    27272780#ifdef LARGE_OBJECTS
    27282781/* creates large object */
     
    28212874}
    28222875#endif /* LARGE_OBJECTS */
    2823 
    28242876
    28252877/* connection object methods */
     
    28392891        {"parameter", (PyCFunction) pg_parameter, METH_VARARGS,
    28402892                        pg_parameter__doc__},
     2893        {"escape_string", (PyCFunction) pg_escape_string, METH_VARARGS,
     2894                        pg_escape_string__doc__},
     2895        {"escape_bytea", (PyCFunction) pg_escape_bytea, METH_VARARGS,
     2896                        pg_escape_bytea__doc__},
    28412897
    28422898#ifdef DIRECT_ACCESS
  • trunk/module/test_pg.py

    r358 r364  
    55# Written by Christoph Zwerschke
    66#
    7 # $Id: test_pg.py,v 1.15 2008-11-21 13:00:21 cito Exp $
     7# $Id: test_pg.py,v 1.16 2008-11-21 19:25:27 cito Exp $
    88#
    99
     
    355355
    356356    def testEscapeString(self):
    357         self.assertEqual(pg.escape_string('hello'), 'hello')
     357        self.assertEqual(pg.escape_string('plain'), 'plain')
     358        self.assertEqual(pg.escape_string(
     359            "that's k\xe4se"), "that''s k\xe4se")
    358360        self.assertEqual(pg.escape_string(
    359361            r"It's fine to have a \ inside."),
     
    361363
    362364    def testEscapeBytea(self):
    363         self.assertEqual(pg.escape_bytea('hello'), 'hello')
     365        self.assertEqual(pg.escape_bytea('plain'), 'plain')
     366        self.assertEqual(pg.escape_bytea(
     367            "that's k\xe4se"), "that''s k\\\\344se")
    364368        self.assertEqual(pg.escape_bytea(
    365369            'O\x00ps\xff!'), r'O\\000ps\\377!')
    366370
    367371    def testUnescapeBytea(self):
    368         self.assertEqual(pg.unescape_bytea('hello'), 'hello')
     372        self.assertEqual(pg.unescape_bytea('plain'), 'plain')
     373        self.assertEqual(pg.unescape_bytea(
     374            "that's k\\344se"), "that's k\xe4se")
    369375        self.assertEqual(pg.unescape_bytea(
    370376            r'O\000ps\377!'), 'O\x00ps\xff!')
     
    406412    def testAllConnectMethods(self):
    407413        methods = ['cancel', 'close', 'endcopy',
     414            'escape_bytea', 'escape_string',
    408415            'fileno', 'getline', 'getlo', 'getnotify',
    409416            'inserttable', 'locreate', 'loimport',
     
    412419        connection_methods = [a for a in dir(self.connection)
    413420            if callable(eval("self.connection." + a))]
    414         if 'transaction' not in connection_methods:
    415             # this may be the case for PostgreSQL < 7.4
    416             connection_methods.append('transaction')
    417         if 'parameter' not in connection_methods:
    418             # this may be the case for PostgreSQL < 7.4
    419             connection_methods.append('parameter')
    420421        self.assertEqual(methods, connection_methods)
    421422
     
    696697        db_attributes = [a for a in dir(self.db)
    697698            if not a.startswith('_')]
    698         if 'transaction' not in db_attributes:
    699             # this may be the case for PostgreSQL < 7.4
    700             db_attributes.insert(-4, 'transaction')
    701         if 'parameter' not in db_attributes:
    702             # this may be the case for PostgreSQL < 7.4
    703             db_attributes.insert(-12, 'parameter')
    704699        self.assertEqual(attributes, db_attributes)
    705700
     
    746741
    747742    def testMethodEscapeString(self):
    748         self.assertEqual(self.db.escape_string('hello'), 'hello')
     743        self.assertEqual(self.db.escape_string("plain"), "plain")
     744        self.assertEqual(self.db.escape_string(
     745            "that's k\xe4se"), "that''s k\xe4se")
     746        self.assertEqual(self.db.escape_string(
     747            r"It's fine to have a \ inside."),
     748            r"It''s fine to have a \\ inside.")
    749749
    750750    def testMethodEscapeBytea(self):
    751         self.assertEqual(self.db.escape_bytea('hello'), 'hello')
     751        self.assertEqual(self.db.escape_bytea("plain"), "plain")
     752        self.assertEqual(self.db.escape_bytea(
     753            "that's k\xe4se"), "that''s k\\\\344se")
     754        self.assertEqual(self.db.escape_bytea(
     755            'O\x00ps\xff!'), r'O\\000ps\\377!')
    752756
    753757    def testMethodUnescapeBytea(self):
    754         self.assertEqual(self.db.unescape_bytea('hello'), 'hello')
     758        self.assertEqual(self.db.unescape_bytea("plain"), "plain")
     759        self.assertEqual(self.db.unescape_bytea(
     760            "that's k\\344se"), "that's k\xe4se")
     761        self.assertEqual(pg.unescape_bytea(
     762            r'O\000ps\377!'), 'O\x00ps\xff!')
    755763
    756764    def testMethodQuery(self):
     
    810818
    811819    def testEscapeString(self):
     820        self.assertEqual(self.db.escape_string("plain"), "plain")
     821        self.assertEqual(self.db.escape_string(
     822            "that's k\xe4se"), "that''s k\xe4se")
    812823        self.assertEqual(self.db.escape_string(
    813824            r"It's fine to have a \ inside."),
     
    815826
    816827    def testEscapeBytea(self):
     828        self.assertEqual(self.db.escape_bytea("plain"), "plain")
     829        self.assertEqual(self.db.escape_bytea(
     830            "that's k\xe4se"), "that''s k\\\\344se")
    817831        self.assertEqual(self.db.escape_bytea(
    818832            'O\x00ps\xff!'), r'O\\000ps\\377!')
    819833
    820834    def testUnescapeBytea(self):
     835        self.assertEqual(self.db.unescape_bytea("plain"), "plain")
    821836        self.assertEqual(self.db.unescape_bytea(
     837            "that's k\\344se"), "that's k\xe4se")
     838        self.assertEqual(pg.unescape_bytea(
    822839            r'O\000ps\377!'), 'O\x00ps\xff!')
    823840
Note: See TracChangeset for help on using the changeset viewer.