Changeset 629 for trunk


Ignore:
Timestamp:
Nov 26, 2015, 1:33:35 AM (4 years ago)
Author:
cito
Message:

Improve unicode support, particularly for pgdb

The pgdb source object now accepts unicode queries and returns results
decoded with the proper encoding from the connection.
Proper handling of binary objects, particularly accept inner NUL bytes.
The escape/unescape methods now also encode and decode with the proper
encoding; before they had assumed utf8 in Python3 and ascii in Python2.

Also some more whitespace and code cleanup.

Location:
trunk/module
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/module/TEST_PyGreSQL_classic.py

    r624 r629  
    11#! /usr/bin/python
     2# -*- coding: utf-8 -*-
    23
    34from __future__ import print_function
  • trunk/module/TEST_PyGreSQL_classic_connection.py

    r628 r629  
    15321532        f = pg.escape_string
    15331533        r = f(b'plain')
    1534         self.assertIsInstance(r, str)
    1535         self.assertEqual(r, 'plain')
     1534        self.assertIsInstance(r, bytes)
     1535        self.assertEqual(r, b'plain')
    15361536        r = f(u'plain')
    1537         self.assertIsInstance(r, str)
    1538         self.assertEqual(r, 'plain')
     1537        self.assertIsInstance(r, unicode)
     1538        self.assertEqual(r, u'plain')
    15391539        r = f(u"das is' kÀse".encode('utf-8'))
    1540         self.assertIsInstance(r, str)
    1541         self.assertEqual(r, "das is'' kÀse")
    1542         if unicode_strings:
    1543             r = f("das is' kÀse")
    1544             self.assertIsInstance(r, str)
    1545             self.assertEqual(r, "das is'' kÀse")
     1540        self.assertIsInstance(r, bytes)
     1541        self.assertEqual(r, u"das is'' kÀse".encode('utf-8'))
     1542        r = f(u"that's cheesy")
     1543        self.assertIsInstance(r, unicode)
     1544        self.assertEqual(r, u"that''s cheesy")
    15461545        r = f(r"It's bad to have a \ inside.")
    15471546        self.assertEqual(r, r"It''s bad to have a \\ inside.")
     
    15501549        f = pg.escape_bytea
    15511550        r = f(b'plain')
    1552         self.assertIsInstance(r, str)
    1553         self.assertEqual(r, 'plain')
     1551        self.assertIsInstance(r, bytes)
     1552        self.assertEqual(r, b'plain')
    15541553        r = f(u'plain')
    1555         self.assertIsInstance(r, str)
    1556         self.assertEqual(r, 'plain')
     1554        self.assertIsInstance(r, unicode)
     1555        self.assertEqual(r, u'plain')
    15571556        r = f(u"das is' kÀse".encode('utf-8'))
    1558         self.assertIsInstance(r, str)
    1559         self.assertEqual(r, r"das is'' k\\303\\244se")
    1560         if unicode_strings:
    1561             r = f("das is' kÀse")
    1562             self.assertIsInstance(r, str)
    1563             self.assertEqual(r, r"das is'' k\\303\\244se")
     1557        self.assertIsInstance(r, bytes)
     1558        self.assertEqual(r, b"das is'' k\\\\303\\\\244se")
     1559        r = f(u"that's cheesy")
     1560        self.assertIsInstance(r, unicode)
     1561        self.assertEqual(r, u"that''s cheesy")
    15641562        r = f(b'O\x00ps\xff!')
    1565         self.assertEqual(r, r'O\\000ps\\377!')
     1563        self.assertEqual(r, b'O\\\\000ps\\\\377!')
    15661564
    15671565
  • trunk/module/TEST_PyGreSQL_classic_dbwrapper.py

    r607 r629  
    4040except NameError:  # Python >= 3.0
    4141    long = int
     42
     43try:
     44    unicode
     45except NameError:  # Python >= 3.0
     46    unicode = str
    4247
    4348windows = os.name == 'nt'
     
    213218
    214219    def testMethodUnescapeBytea(self):
    215         self.assertEqual(self.db.unescape_bytea(''), '')
     220        self.assertEqual(self.db.unescape_bytea(''), b'')
    216221
    217222    def testMethodQuery(self):
     
    314319    def testEscapeLiteral(self):
    315320        f = self.db.escape_literal
    316         self.assertEqual(f("plain"), "'plain'")
    317         self.assertEqual(f("that's k\xe4se"), "'that''s k\xe4se'")
     321        r = f(b"plain")
     322        self.assertIsInstance(r, bytes)
     323        self.assertEqual(r, b"'plain'")
     324        r = f(u"plain")
     325        self.assertIsInstance(r, unicode)
     326        self.assertEqual(r, u"'plain'")
     327        r = f(u"that's kÀse".encode('utf-8'))
     328        self.assertIsInstance(r, bytes)
     329        self.assertEqual(r, u"'that''s kÀse'".encode('utf-8'))
     330        r = f(u"that's kÀse")
     331        self.assertIsInstance(r, unicode)
     332        self.assertEqual(r, u"'that''s kÀse'")
    318333        self.assertEqual(f(r"It's fine to have a \ inside."),
    319334            r" E'It''s fine to have a \\ inside.'")
     
    323338    def testEscapeIdentifier(self):
    324339        f = self.db.escape_identifier
    325         self.assertEqual(f("plain"), '"plain"')
    326         self.assertEqual(f("that's k\xe4se"), '"that\'s k\xe4se"')
     340        r = f(b"plain")
     341        self.assertIsInstance(r, bytes)
     342        self.assertEqual(r, b'"plain"')
     343        r = f(u"plain")
     344        self.assertIsInstance(r, unicode)
     345        self.assertEqual(r, u'"plain"')
     346        r = f(u"that's kÀse".encode('utf-8'))
     347        self.assertIsInstance(r, bytes)
     348        self.assertEqual(r, u'"that\'s kÀse"'.encode('utf-8'))
     349        r = f(u"that's kÀse")
     350        self.assertIsInstance(r, unicode)
     351        self.assertEqual(r, u'"that\'s kÀse"')
    327352        self.assertEqual(f(r"It's fine to have a \ inside."),
    328353            '"It\'s fine to have a \\ inside."')
     
    332357    def testEscapeString(self):
    333358        f = self.db.escape_string
    334         self.assertEqual(f("plain"), "plain")
    335         self.assertEqual(f("that's k\xe4se"), "that''s k\xe4se")
     359        r = f(b"plain")
     360        self.assertIsInstance(r, bytes)
     361        self.assertEqual(r, b"plain")
     362        r = f(u"plain")
     363        self.assertIsInstance(r, unicode)
     364        self.assertEqual(r, u"plain")
     365        r = f(u"that's kÀse".encode('utf-8'))
     366        self.assertIsInstance(r, bytes)
     367        self.assertEqual(r, u"that''s kÀse".encode('utf-8'))
     368        r = f(u"that's kÀse")
     369        self.assertIsInstance(r, unicode)
     370        self.assertEqual(r, u"that''s kÀse")
    336371        self.assertEqual(f(r"It's fine to have a \ inside."),
    337372            r"It''s fine to have a \ inside.")
     
    342377        # regardless of the bytea_output setting
    343378        r = f(b'plain')
    344         self.assertIsInstance(r, str)
    345         self.assertEqual(r, r'\x706c61696e')
     379        self.assertIsInstance(r, bytes)
     380        self.assertEqual(r, b'\\x706c61696e')
    346381        r = f(u'plain')
    347         self.assertIsInstance(r, str)
    348         self.assertEqual(r, r'\x706c61696e')
     382        self.assertIsInstance(r, unicode)
     383        self.assertEqual(r, u'\\x706c61696e')
    349384        r = f(u"das is' kÀse".encode('utf-8'))
    350         self.assertIsInstance(r, str)
    351         self.assertEqual(r, r'\x64617320697327206bc3a47365')
    352         r = f("das is' kÀse")
    353         self.assertIsInstance(r, str)
    354         self.assertEqual(r, r'\x64617320697327206bc3a47365')
    355         self.assertEqual(f(b'O\x00ps\xff!'), r'\x4f007073ff21')
     385        self.assertIsInstance(r, bytes)
     386        self.assertEqual(r, b'\\x64617320697327206bc3a47365')
     387        r = f(u"das is' kÀse")
     388        self.assertIsInstance(r, unicode)
     389        self.assertEqual(r, u'\\x64617320697327206bc3a47365')
     390        self.assertEqual(f(b'O\x00ps\xff!'), b'\\x4f007073ff21')
    356391
    357392    def testUnescapeBytea(self):
    358393        f = self.db.unescape_bytea
    359394        r = f(b'plain')
    360         self.assertIsInstance(r, str)
    361         self.assertEqual(r, 'plain')
     395        self.assertIsInstance(r, bytes)
     396        self.assertEqual(r, b'plain')
    362397        r = f(u'plain')
    363         self.assertIsInstance(r, str)
    364         self.assertEqual(r, 'plain')
     398        self.assertIsInstance(r, bytes)
     399        self.assertEqual(r, b'plain')
    365400        r = f(b"das is' k\\303\\244se")
    366         self.assertIsInstance(r, str)
    367         self.assertEqual(r, "das is' kÀse")
     401        self.assertIsInstance(r, bytes)
     402        self.assertEqual(r, u"das is' kÀse".encode('utf8'))
    368403        r = f(u"das is' k\\303\\244se")
    369         self.assertIsInstance(r, str)
    370         self.assertEqual(r, "das is' kÀse")
    371         self.assertEqual(f(r'O\\000ps\\377!'), r'O\000ps\377!')
    372         self.assertEqual(f(r'\\x706c61696e'), r'\x706c61696e')
     404        self.assertIsInstance(r, bytes)
     405        self.assertEqual(r, u"das is' kÀse".encode('utf8'))
     406        self.assertEqual(f(r'O\\000ps\\377!'), b'O\\000ps\\377!')
     407        self.assertEqual(f(r'\\x706c61696e'), b'\\x706c61696e')
    373408        self.assertEqual(f(r'\\x746861742773206be47365'),
    374             r'\x746861742773206be47365')
    375         self.assertEqual(f(r'\\x4f007073ff21'), r'\x4f007073ff21')
     409            b'\\x746861742773206be47365')
     410        self.assertEqual(f(r'\\x4f007073ff21'), b'\\x4f007073ff21')
    376411
    377412    def testQuote(self):
     
    10351070        query('create table bytea_test ('
    10361071            'data bytea)')
    1037         s = "It's all \\ kinds \x00 of\r nasty \xff stuff!\n"
     1072        s = b"It's all \\ kinds \x00 of\r nasty \xff stuff!\n"
    10381073        r = self.db.escape_bytea(s)
    1039         query('insert into bytea_test values('
    1040             "'%s')" % r)
     1074        query('insert into bytea_test values($1)', (r,))
    10411075        r = query('select * from bytea_test').getresult()
    10421076        self.assertTrue(len(r) == 1)
     
    10451079        r = r[0]
    10461080        r = self.db.unescape_bytea(r)
     1081        self.assertIsInstance(r, bytes)
    10471082        self.assertEqual(r, s)
    10481083        query('drop table bytea_test')
  • trunk/module/TEST_PyGreSQL_classic_functions.py

    r603 r629  
    2727    long = int
    2828
    29 unicode_strings = str is not bytes
     29try:
     30    unicode
     31except NameError:  # Python >= 3.0
     32    unicode = str
    3033
    3134
     
    275278        f = pg.escape_string
    276279        r = f(b'plain')
    277         self.assertIsInstance(r, str)
    278         self.assertEqual(r, 'plain')
     280        self.assertIsInstance(r, bytes)
     281        self.assertEqual(r, b'plain')
    279282        r = f(u'plain')
    280         self.assertIsInstance(r, str)
    281         self.assertEqual(r, 'plain')
     283        self.assertIsInstance(r, unicode)
     284        self.assertEqual(r, u'plain')
    282285        r = f("that's cheese")
    283286        self.assertIsInstance(r, str)
     
    287290        f = pg.escape_bytea
    288291        r = f(b'plain')
    289         self.assertIsInstance(r, str)
    290         self.assertEqual(r, 'plain')
     292        self.assertIsInstance(r, bytes)
     293        self.assertEqual(r, b'plain')
    291294        r = f(u'plain')
    292         self.assertIsInstance(r, str)
    293         self.assertEqual(r, 'plain')
     295        self.assertIsInstance(r, unicode)
     296        self.assertEqual(r, u'plain')
    294297        r = f("that's cheese")
    295298        self.assertIsInstance(r, str)
     
    299302        f = pg.unescape_bytea
    300303        r = f(b'plain')
    301         self.assertIsInstance(r, str)
    302         self.assertEqual(r, 'plain')
     304        self.assertIsInstance(r, bytes)
     305        self.assertEqual(r, b'plain')
    303306        r = f(u'plain')
    304         self.assertIsInstance(r, str)
    305         self.assertEqual(r, 'plain')
     307        self.assertIsInstance(r, bytes)
     308        self.assertEqual(r, b'plain')
    306309        r = f(b"das is' k\\303\\244se")
    307         self.assertIsInstance(r, str)
    308         self.assertEqual(r, "das is' kÀse")
     310        self.assertIsInstance(r, bytes)
     311        self.assertEqual(r, u"das is' kÀse".encode('utf-8'))
    309312        r = f(u"das is' k\\303\\244se")
    310         self.assertIsInstance(r, str)
    311         self.assertEqual(r, "das is' kÀse")
    312         r = f(r'O\\000ps\\377!')
    313         self.assertEqual(r, r'O\000ps\377!')
     313        self.assertIsInstance(r, bytes)
     314        self.assertEqual(r, u"das is' kÀse".encode('utf-8'))
     315        r = f(b'O\\000ps\\377!')
     316        self.assertEqual(r, b'O\x00ps\xff!')
     317        r = f(u'O\\000ps\\377!')
     318        self.assertEqual(r, b'O\x00ps\xff!')
    314319
    315320
  • trunk/module/TEST_PyGreSQL_dbapi20.py

    r612 r629  
    11#! /usr/bin/python
     2# -*- coding: utf-8 -*-
    23# $Id$
    34
     
    1718    pass
    1819
     20try:
     21    long
     22except NameError:  # Python >= 3.0
     23    long = int
     24
    1925
    2026class test_PyGreSQL(dbapi20.DatabaseAPI20Test):
     
    6167    def test_fetch_2_rows(self):
    6268        Decimal = pgdb.decimal_type()
    63         values = ['test', pgdb.Binary('\xff\x52\xb2'),
     69        values = ['test', pgdb.Binary(b'\xff\x52\xb2'),
    6470            True, 5, 6, 5.7, Decimal('234.234234'), Decimal('75.45'),
    6571            '2011-07-17', '15:47:42', '2008-10-20 15:25:35', '15:31:05',
     
    9298            rows = cur.fetchall()
    9399            self.assertEqual(len(rows), 2)
    94             self.assertEqual(rows[0], values)
    95             self.assertEqual(rows[0], rows[1])
     100            row0 = rows[0]
     101            self.assertEqual(row0, values)
     102            self.assertEqual(row0, rows[1])
     103            self.assertIsInstance(row0[0], str)
     104            self.assertIsInstance(row0[1], bytes)
     105            self.assertIsInstance(row0[2], bool)
     106            self.assertIsInstance(row0[3], int)
     107            self.assertIsInstance(row0[4], long)
     108            self.assertIsInstance(row0[5], float)
     109            self.assertIsInstance(row0[6], Decimal)
     110            self.assertIsInstance(row0[7], Decimal)
     111            self.assertIsInstance(row0[8], str)
     112            self.assertIsInstance(row0[9], str)
     113            self.assertIsInstance(row0[10], str)
     114            self.assertIsInstance(row0[11], str)
    96115        finally:
    97116            con.close()
     
    120139                "create table %s (n smallint, floattest float)" % table)
    121140            params = enumerate(values)
    122             cur.executemany("insert into %s values(%%s,%%s)" % table, params)
     141            cur.executemany("insert into %s values (%%s,%%s)" % table, params)
    123142            cur.execute("select * from %s order by 1" % table)
    124143            rows = cur.fetchall()
     
    138157            else:
    139158                self.assertEqual(inval, outval)
     159
     160    def test_unicode_with_utf8(self):
     161        table = self.table_prefix + 'booze'
     162        input = u"He wes Leovenaðes sone — liðe him be Drihten"
     163        con = self._connect()
     164        try:
     165            cur = con.cursor()
     166            cur.execute("create table %s (t text)" % table)
     167            try:
     168                cur.execute("set client_encoding=utf8")
     169                cur.execute(u"select '%s'" % input)
     170            except Exception:
     171                self.skipTest("database does not support utf8")
     172            output1 = cur.fetchone()[0]
     173            cur.execute("insert into %s values (%%s)" % table, (input,))
     174            cur.execute("select * from %s" % table)
     175            output2 = cur.fetchone()[0]
     176            cur.execute("select t = '%s' from %s" % (input, table))
     177            output3 = cur.fetchone()[0]
     178            cur.execute("select t = %%s from %s" % table, (input,))
     179            output4 = cur.fetchone()[0]
     180        finally:
     181            con.close()
     182        if str is bytes:  # Python < 3.0
     183            input = input.encode('utf8')
     184        self.assertIsInstance(output1, str)
     185        self.assertEqual(output1, input)
     186        self.assertIsInstance(output2, str)
     187        self.assertEqual(output2, input)
     188        self.assertIsInstance(output3, bool)
     189        self.assertTrue(output3)
     190        self.assertIsInstance(output4, bool)
     191        self.assertTrue(output4)
     192
     193    def test_unicode_with_latin1(self):
     194        table = self.table_prefix + 'booze'
     195        input = u"Ehrt den König seine WÃŒrde, ehret uns der HÀnde Fleiß."
     196        con = self._connect()
     197        try:
     198            cur = con.cursor()
     199            cur.execute("create table %s (t text)" % table)
     200            try:
     201                cur.execute("set client_encoding=latin1")
     202                cur.execute(u"select '%s'" % input)
     203            except Exception:
     204                self.skipTest("database does not support latin1")
     205            output1 = cur.fetchone()[0]
     206            cur.execute("insert into %s values (%%s)" % table, (input,))
     207            cur.execute("select * from %s" % table)
     208            output2 = cur.fetchone()[0]
     209            cur.execute("select t = '%s' from %s" % (input, table))
     210            output3 = cur.fetchone()[0]
     211            cur.execute("select t = %%s from %s" % table, (input,))
     212            output4 = cur.fetchone()[0]
     213        finally:
     214            con.close()
     215        if str is bytes:  # Python < 3.0
     216            input = input.encode('latin1')
     217        self.assertIsInstance(output1, str)
     218        self.assertEqual(output1, input)
     219        self.assertIsInstance(output2, str)
     220        self.assertEqual(output2, input)
     221        self.assertIsInstance(output3, bool)
     222        self.assertTrue(output3)
     223        self.assertIsInstance(output4, bool)
     224        self.assertTrue(output4)
    140225
    141226    def test_set_decimal_type(self):
  • trunk/module/dbapi20.py

    r599 r629  
    828828
    829829    def test_Binary(self):
    830         b = self.driver.Binary('Something')
    831         b = self.driver.Binary('')
     830        b = self.driver.Binary(b'Something')
     831        b = self.driver.Binary(b'')
    832832
    833833    def test_STRING(self):
  • trunk/module/pgdb.py

    r627 r629  
    7777except NameError:  # Python >= 3.0
    7878    long = int
     79
     80try:
     81    unicode
     82except NameError:  # Python >= 3.0
     83    unicode = str
    7984
    8085try:
     
    241246        if isinstance(val, (datetime, date, time, timedelta)):
    242247            val = str(val)
    243         elif isinstance(val, str) and str is not bytes:
    244             val = val.encode('utf8')
    245         if isinstance(val, bytes):
     248        if isinstance(val, basestring):
    246249            if isinstance(val, Binary):
    247250                val = self._cnx.escape_bytea(val)
     251                if bytes is not str:  # Python >= 3.0
     252                    val = val.decode('ascii')
    248253            else:
    249254                val = self._cnx.escape_string(val)
     
    352357            raise
    353358        except Error as err:
    354             raise _db_error("error '%s' in '%s'" % (err, sql))
     359            raise _db_error("error in '%s': '%s' " % (sql, err))
    355360        except Exception as err:
    356361            raise _op_error("internal error in '%s': %s" % (sql, err))
     
    686691
    687692
    688 class Binary(str):
     693class Binary(bytes):
    689694    """construct an object capable of holding a binary (long) string value."""
    690695
  • trunk/module/pgmodule.c

    r628 r629  
    148148
    149149/* --------------------------------------------------------------------- */
    150 /* Object declarations */
     150/* Object declarations                                                                                                  */
    151151/* --------------------------------------------------------------------- */
    152152typedef struct
     
    165165        connObject      *pgcnx;                 /* parent connection object */
    166166        PGresult        *result;                /* result content */
     167        int                     encoding;               /* client encoding */
    167168        int                     result_type;    /* result type (DDL/DML/DQL) */
    168169        long            arraysize;              /* array size for fetch method */
     
    200201#endif /* LARGE_OBJECTS */
    201202
     203/* define internal types */
     204
     205#define PYGRES_INT 1
     206#define PYGRES_LONG 2
     207#define PYGRES_FLOAT 3
     208#define PYGRES_DECIMAL 4
     209#define PYGRES_MONEY 5
     210#define PYGRES_DEFAULT 6
    202211
    203212/* --------------------------------------------------------------------- */
    204 /* Internal Functions */
     213/* Internal Functions                                                                                                    */
    205214/* --------------------------------------------------------------------- */
     215
     216/* shared function for encoding and decoding strings */
     217
     218PyObject *
     219get_decoded_string(char *str, Py_ssize_t size, int encoding)
     220{
     221        if (encoding == pg_encoding_utf8)
     222                return PyUnicode_DecodeUTF8(str, size, "strict");
     223        if (encoding == pg_encoding_latin1)
     224                return PyUnicode_DecodeLatin1(str, size, "strict");
     225        if (encoding == pg_encoding_ascii)
     226                return PyUnicode_DecodeASCII(str, size, "strict");
     227        /* encoding name should be properly translated to Python here */
     228        return PyUnicode_Decode(str, size,
     229                pg_encoding_to_char(encoding), "strict");
     230}
     231
     232PyObject *
     233get_encoded_string(PyObject *unicode_obj, int encoding)
     234 {
     235        if (encoding == pg_encoding_utf8)
     236                return PyUnicode_AsUTF8String(unicode_obj);
     237        if (encoding == pg_encoding_latin1)
     238                return PyUnicode_AsLatin1String(unicode_obj);
     239        if (encoding == pg_encoding_ascii)
     240                return PyUnicode_AsASCIIString(unicode_obj);
     241        /* encoding name should be properly translated to Python here */
     242        return PyUnicode_AsEncodedString(unicode_obj,
     243                pg_encoding_to_char(encoding), "strict");
     244}
     245
    206246/* shared functions for converting PG types to Python types */
    207247static int *
     
    224264                        case INT4OID:
    225265                        case OIDOID:
    226                                 typ[j] = 1;
     266                                typ[j] = PYGRES_INT;
    227267                                break;
    228268
    229269                        case INT8OID:
    230                                 typ[j] = 2;
     270                                typ[j] = PYGRES_LONG;
    231271                                break;
    232272
    233273                        case FLOAT4OID:
    234274                        case FLOAT8OID:
    235                                 typ[j] = 3;
     275                                typ[j] = PYGRES_FLOAT;
    236276                                break;
    237277
    238278                        case NUMERICOID:
    239                                 typ[j] = 4;
     279                                typ[j] = PYGRES_DECIMAL;
    240280                                break;
    241281
    242282                        case CASHOID:
    243                                 typ[j] = 5;
     283                                typ[j] = PYGRES_MONEY;
    244284                                break;
    245285
    246286                        default:
    247                                 typ[j] = 6;
    248                                 break;
     287                                typ[j] = PYGRES_DEFAULT;
    249288                }
    250289        }
     
    388427                                                default:
    389428                                                        aligns[j] = 'l';
    390                                                         break;
    391429                                        }
    392430                                }
     
    501539
    502540/* --------------------------------------------------------------------- */
    503 /* large objects                                                        */
     541/* large objects                                                                                                                */
    504542/* --------------------------------------------------------------------- */
    505543#ifdef LARGE_OBJECTS
     
    666704
    667705        if ((size = lo_read(self->pgcnx->cnx, self->lo_fd,
    668             PyBytes_AS_STRING((PyBytesObject *)(buffer)), size)) < 0)
     706                PyBytes_AS_STRING((PyBytesObject *)(buffer)), size)) < 0)
    669707        {
    670708                PyErr_SetString(PyExc_IOError, "error while reading.");
     
    901939/* get the list of large object attributes */
    902940static PyObject *
    903 largeDir(largeObject *self) {
     941largeDir(largeObject *self)
     942{
    904943        PyObject *attrs;
    905944
     
    9961035        0,                                                              /* tp_as_mapping */
    9971036        0,                                                              /* tp_hash */
    998         0,                              /* tp_call */
     1037        0,                                                              /* tp_call */
    9991038        (reprfunc) largeStr,                    /* tp_str */
    10001039        (getattrofunc) largeGetAttr,    /* tp_getattro */
    1001         0,                              /* tp_setattro */
    1002         0,                              /* tp_as_buffer */
    1003         Py_TPFLAGS_DEFAULT,             /* tp_flags */
     1040        0,                                                              /* tp_setattro */
     1041        0,                                                              /* tp_as_buffer */
     1042        Py_TPFLAGS_DEFAULT,                             /* tp_flags */
    10041043        large__doc__,                                   /* tp_doc */
    1005         0,                              /* tp_traverse */
    1006         0,                              /* tp_clear */
    1007         0,                              /* tp_richcompare */
    1008         0,                              /* tp_weaklistoffset */
    1009         0,                              /* tp_iter */
    1010         0,                              /* tp_iternext */
     1044        0,                                                              /* tp_traverse */
     1045        0,                                                              /* tp_clear */
     1046        0,                                                              /* tp_richcompare */
     1047        0,                                                              /* tp_weaklistoffset */
     1048        0,                                                              /* tp_iter */
     1049        0,                                                              /* tp_iternext */
    10111050        largeMethods,                                   /* tp_methods */
    10121051};
     
    10141053
    10151054/* --------------------------------------------------------------------- */
    1016 /* connection object */
     1055/* connection object                                                                                                    */
    10171056/* --------------------------------------------------------------------- */
    10181057static void
     
    10791118        PGresult        *result;
    10801119        queryObject *npgobj;
    1081         const char*     encoding_name=NULL;
    10821120        int                     encoding,
    10831121                                status,
     
    10971135
    10981136        encoding = PQclientEncoding(self->cnx);
    1099         if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
    1100                         && encoding != pg_encoding_ascii)
    1101                 /* should be translated to Python here */
    1102                 encoding_name = pg_encoding_to_char(encoding);
    11031137
    11041138        if (PyBytes_Check(query_obj))
     
    11081142        else if (PyUnicode_Check(query_obj))
    11091143        {
    1110                 if (encoding == pg_encoding_utf8)
    1111                         query_obj = PyUnicode_AsUTF8String(query_obj);
    1112                 else if (encoding == pg_encoding_latin1)
    1113                         query_obj = PyUnicode_AsLatin1String(query_obj);
    1114                 else if (encoding == pg_encoding_ascii)
    1115                         query_obj = PyUnicode_AsASCIIString(query_obj);
    1116                 else
    1117                         query_obj = PyUnicode_AsEncodedString(query_obj,
    1118                                 encoding_name, "strict");
     1144                query_obj = get_encoded_string(query_obj, encoding);
    11191145                if (!query_obj) return NULL; /* pass the UnicodeEncodeError */
    11201146                query = PyBytes_AsString(query_obj);
    11211147        }
    1122         if (!query) {
     1148        if (!query)
     1149        {
    11231150                PyErr_SetString(PyExc_TypeError,
    11241151                        "query command must be a string.");
     
    11771204                        else if (PyBytes_Check(obj))
    11781205                        {
    1179                                 *s = obj;
    1180                                 *p = PyBytes_AsString(*s);
    1181                                 *l = (int)PyBytes_Size(*s);
     1206                                PyBytes_AsStringAndSize(*s = obj, p, (Py_ssize_t *)l);
    11821207                        }
    11831208                        else if (PyUnicode_Check(obj))
    11841209                        {
    1185                                 if (encoding == pg_encoding_utf8)
    1186                                         *s = PyUnicode_AsUTF8String(obj);
    1187                                 else if (encoding == pg_encoding_latin1)
    1188                                         *s = PyUnicode_AsLatin1String(obj);
    1189                                 else if (encoding == pg_encoding_ascii)
    1190                                         *s = PyUnicode_AsASCIIString(obj);
    1191                                 else
    1192                                         *s = PyUnicode_AsEncodedString(obj,
    1193                                                 encoding_name, "strict");
     1210                                *s = get_encoded_string(obj, encoding);
    11941211                                if (!*s)
    11951212                                {
     
    12041221                                        return NULL; /* pass the UnicodeEncodeError */
    12051222                                }
    1206                                 *p = PyBytes_AsString(*s);
    1207                                 *l = (int)PyBytes_Size(*s);
     1223                                PyBytes_AsStringAndSize(*s, p, (Py_ssize_t *)l);
    12081224                        }
    12091225                        else
     
    12991315                                set_dberror(InternalError,
    13001316                                        "internal error: unknown result status.", result);
    1301                                 break;
    13021317                }
    13031318
     
    14461461                                *buffer,
    14471462                                *bufpt;
    1448         const char *encoding_name=NULL;
    14491463        int                     encoding;
    14501464        size_t          bufsiz;
     
    15151529
    15161530        encoding = PQclientEncoding(self->cnx);
    1517         if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
    1518                         && encoding != pg_encoding_ascii)
    1519                 /* should be translated to Python here */
    1520                 encoding_name = pg_encoding_to_char(encoding);
    15211531
    15221532        PQclear(result);
     
    15981608                        else if (PyUnicode_Check(item))
    15991609                        {
    1600                                 PyObject *s;
    1601                                 if (encoding == pg_encoding_utf8)
    1602                                         s = PyUnicode_AsUTF8String(item);
    1603                                 else if (encoding == pg_encoding_latin1)
    1604                                         s = PyUnicode_AsLatin1String(item);
    1605                                 else if (encoding == pg_encoding_ascii)
    1606                                         s = PyUnicode_AsASCIIString(item);
    1607                                 else
    1608                                         s = PyUnicode_AsEncodedString(item,
    1609                                                 encoding_name, "strict");
     1610                                PyObject *s = get_encoded_string(item, encoding);
    16101611                                if (!s)
    16111612                                {
     
    17621763connEscapeLiteral(connObject *self, PyObject *args)
    17631764{
    1764         char *str; /* our string argument */
    1765         int str_length; /* length of string */
    1766         char *esc; /* the escaped version of the string */
    1767         PyObject *ret; /* string object to return */
    1768 
    1769         if (!PyArg_ParseTuple(args, "s#", &str, &str_length))
    1770                 return NULL;
    1771         esc = PQescapeLiteral(self->cnx, str, (size_t)str_length);
    1772         ret = Py_BuildValue("s", esc);
    1773         if (esc)
    1774                 PQfreemem(esc);
    1775         if (!ret) /* pass on exception */
    1776                 return NULL;
    1777         return ret;
     1765        PyObject   *from_obj, /* the object that was passed in */
     1766                           *to_obj; /* string object to return */
     1767        char       *from=NULL, /* our string argument as encoded string */
     1768                           *to; /* the result as encoded string */
     1769        Py_ssize_t      from_length; /* length of string */
     1770        size_t          to_length; /* length of result */
     1771        int                     encoding = -1; /* client encoding */
     1772
     1773        if (!PyArg_ParseTuple(args, "O", &from_obj))
     1774                return NULL;
     1775
     1776        if (PyBytes_Check(from_obj))
     1777        {
     1778                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1779        }
     1780        else if (PyUnicode_Check(from_obj))
     1781        {
     1782                encoding = PQclientEncoding(self->cnx);
     1783                from_obj = get_encoded_string(from_obj, encoding);
     1784                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     1785                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1786        }
     1787        if (!from)
     1788        {
     1789                PyErr_SetString(PyExc_TypeError, "escape_literal() expects a string.");
     1790                return NULL;
     1791        }
     1792
     1793        to = PQescapeLiteral(self->cnx, from, (size_t)from_length);
     1794        to_length = strlen(to);
     1795
     1796        if (encoding == -1)
     1797                to_obj = PyBytes_FromStringAndSize(to, to_length);
     1798        else
     1799                to_obj = get_decoded_string(to, to_length, encoding);
     1800        if (to)
     1801                PQfreemem(to);
     1802        return to_obj;
    17781803}
    17791804
     
    17851810connEscapeIdentifier(connObject *self, PyObject *args)
    17861811{
    1787         char *str; /* our string argument */
    1788         int str_length; /* length of string */
    1789         char *esc; /* the escaped version of the string */
    1790         PyObject *ret; /* string object to return */
    1791 
    1792         if (!PyArg_ParseTuple(args, "s#", &str, &str_length))
    1793                 return NULL;
    1794         esc = PQescapeIdentifier(self->cnx, str, (size_t)str_length);
    1795         ret = Py_BuildValue("s", esc);
    1796         if (esc)
    1797                 PQfreemem(esc);
    1798         if (!ret) /* pass on exception */
    1799                 return NULL;
    1800         return ret;
     1812        PyObject   *from_obj, /* the object that was passed in */
     1813                           *to_obj; /* string object to return */
     1814        char       *from=NULL, /* our string argument as encoded string */
     1815                           *to; /* the result as encoded string */
     1816        Py_ssize_t      from_length; /* length of string */
     1817        size_t          to_length; /* length of result */
     1818        int                     encoding = -1; /* client encoding */
     1819
     1820        if (!PyArg_ParseTuple(args, "O", &from_obj))
     1821                return NULL;
     1822
     1823        if (PyBytes_Check(from_obj))
     1824        {
     1825                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1826        }
     1827        else if (PyUnicode_Check(from_obj))
     1828        {
     1829                encoding = PQclientEncoding(self->cnx);
     1830                from_obj = get_encoded_string(from_obj, encoding);
     1831                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     1832                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1833        }
     1834        if (!from)
     1835        {
     1836                PyErr_SetString(PyExc_TypeError,
     1837                        "escape_identifier() expects a string.");
     1838                return NULL;
     1839        }
     1840
     1841        to = PQescapeIdentifier(self->cnx, from, (size_t)from_length);
     1842        to_length = strlen(to);
     1843
     1844        if (encoding == -1)
     1845                to_obj = PyBytes_FromStringAndSize(to, to_length);
     1846        else
     1847                to_obj = get_decoded_string(to, to_length, encoding);
     1848        if (to)
     1849                PQfreemem(to);
     1850        return to_obj;
    18011851}
    18021852
     
    18101860connEscapeString(connObject *self, PyObject *args)
    18111861{
    1812         char *from; /* our string argument */
    1813         char *to=NULL; /* the result */
    1814         int from_length; /* length of string */
    1815         int to_length; /* length of result */
    1816         PyObject *ret; /* string object to return */
    1817 
    1818         if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
    1819                 return NULL;
     1862        PyObject   *from_obj, /* the object that was passed in */
     1863                           *to_obj; /* string object to return */
     1864        char       *from=NULL, /* our string argument as encoded string */
     1865                           *to; /* the result as encoded string */
     1866        Py_ssize_t      from_length; /* length of string */
     1867        size_t          to_length; /* length of result */
     1868        int                     encoding = -1; /* client encoding */
     1869
     1870        if (!PyArg_ParseTuple(args, "O", &from_obj))
     1871                return NULL;
     1872
     1873        if (PyBytes_Check(from_obj))
     1874        {
     1875                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1876        }
     1877        else if (PyUnicode_Check(from_obj))
     1878        {
     1879                encoding = PQclientEncoding(self->cnx);
     1880                from_obj = get_encoded_string(from_obj, encoding);
     1881                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     1882                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1883        }
     1884        if (!from)
     1885        {
     1886                PyErr_SetString(PyExc_TypeError, "escape_string() expects a string.");
     1887                return NULL;
     1888        }
     1889
    18201890        to_length = 2*from_length + 1;
    18211891        if (to_length < from_length) /* overflow */
     
    18251895        }
    18261896        to = (char *)malloc(to_length);
    1827         to_length = (int)PQescapeStringConn(self->cnx,
     1897        to_length = PQescapeStringConn(self->cnx,
    18281898                to, from, (size_t)from_length, NULL);
    1829         ret = Py_BuildValue("s#", to, to_length);
     1899
     1900        if (encoding == -1)
     1901                to_obj = PyBytes_FromStringAndSize(to, to_length);
     1902        else
     1903                to_obj = get_decoded_string(to, to_length, encoding);
    18301904        if (to)
    18311905                free(to);
    1832         if (!ret) /* pass on exception */
    1833                 return NULL;
    1834         return ret;
     1906        return to_obj;
    18351907}
    18361908
     
    18421914connEscapeBytea(connObject *self, PyObject *args)
    18431915{
    1844         unsigned char *from; /* our string argument */
    1845         unsigned char *to; /* the result */
    1846         int from_length; /* length of string */
    1847         size_t to_length; /* length of result */
    1848         PyObject *ret; /* string object to return */
    1849 
    1850         if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
    1851                 return NULL;
    1852         to = PQescapeByteaConn(self->cnx, from, (int)from_length, &to_length);
    1853         ret = Py_BuildValue("s", to);
     1916        PyObject   *from_obj, /* the object that was passed in */
     1917                           *to_obj; /* string object to return */
     1918        char       *from=NULL, /* our string argument as encoded string */
     1919                           *to; /* the result as encoded string */
     1920        Py_ssize_t      from_length; /* length of string */
     1921        size_t          to_length; /* length of result */
     1922        int                     encoding = -1; /* client encoding */
     1923
     1924        if (!PyArg_ParseTuple(args, "O", &from_obj))
     1925                return NULL;
     1926
     1927        if (PyBytes_Check(from_obj))
     1928        {
     1929                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1930        }
     1931        else if (PyUnicode_Check(from_obj))
     1932        {
     1933                encoding = PQclientEncoding(self->cnx);
     1934                from_obj = get_encoded_string(from_obj, encoding);
     1935                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     1936                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     1937        }
     1938        if (!from)
     1939        {
     1940                PyErr_SetString(PyExc_TypeError, "escape_bytea() expects a string.");
     1941                return NULL;
     1942        }
     1943
     1944        to = (char *)PQescapeByteaConn(self->cnx,
     1945                (unsigned char *)from, (size_t)from_length, &to_length);
     1946
     1947        if (encoding == -1)
     1948                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
     1949        else
     1950                to_obj = get_decoded_string(to, to_length - 1, encoding);
    18541951        if (to)
    1855                 PQfreemem((void *)to);
    1856         if (!ret) /* pass on exception */
    1857                 return NULL;
    1858         return ret;
     1952                PQfreemem(to);
     1953        return to_obj;
    18591954}
    18601955
     
    21882283/* get the list of connection attributes */
    21892284static PyObject *
    2190 connDir(connObject *self) {
     2285connDir(connObject *self)
     2286{
    21912287        PyObject *attrs;
    21922288
     
    23422438        0,                                                      /* tp_setattro */
    23432439        0,                                                      /* tp_as_buffer */
    2344         Py_TPFLAGS_DEFAULT,         /* tp_flags */
     2440        Py_TPFLAGS_DEFAULT,                     /* tp_flags */
    23452441        0,                                                      /* tp_doc */
    23462442        0,                                                      /* tp_traverse */
     
    23542450
    23552451/* --------------------------------------------------------------------- */
    2356 /* source object */
     2452/* source object                                                                                                                */
    23572453/* --------------------------------------------------------------------- */
    23582454/* checks source object validity */
     
    24372533sourceExecute(sourceObject *self, PyObject *args)
    24382534{
    2439         char            *query;
     2535        PyObject        *query_obj;
     2536        char            *query = NULL;
     2537        int                     encoding;
    24402538
    24412539        /* checks validity */
     
    24482546
    24492547        /* get query args */
    2450         if (!PyArg_ParseTuple(args, "s", &query))
    2451         {
    2452                 PyErr_SetString(PyExc_TypeError, "execute(sql), with sql (string).");
     2548        if (!PyArg_ParseTuple(args, "O", &query_obj))
     2549        {
     2550                return NULL;
     2551        }
     2552
     2553        encoding = PQclientEncoding(self->pgcnx->cnx);
     2554
     2555        if (PyBytes_Check(query_obj))
     2556        {
     2557                query = PyBytes_AsString(query_obj);
     2558        }
     2559        else if (PyUnicode_Check(query_obj))
     2560        {
     2561                query_obj = get_encoded_string(query_obj, encoding);
     2562                if (!query_obj) return NULL; /* pass the UnicodeEncodeError */
     2563                query = PyBytes_AsString(query_obj);
     2564        }
     2565        if (!query)
     2566        {
     2567                PyErr_SetString(PyExc_TypeError, "executed sql must be a string.");
    24532568                return NULL;
    24542569        }
     
    24632578        self->current_row = 0;
    24642579        self->num_fields = 0;
     2580        self->encoding = encoding;
    24652581
    24662582        /* gets result */
     
    25152631                        set_dberror(InternalError, "internal error: "
    25162632                                "unknown result status.", self->result);
    2517                         break;
    25182633        }
    25192634
     
    25652680sourceFetch(sourceObject *self, PyObject *args)
    25662681{
    2567         PyObject   *rowtuple,
    2568                            *reslist,
    2569                            *str;
     2682        PyObject   *reslist;
    25702683        int                     i,
    2571                                 j;
     2684                                k;
    25722685        long            size;
     2686#if IS_PY3
     2687        int                     encoding;
     2688#endif
    25732689
    25742690        /* checks validity */
     
    25942710                return NULL;
    25952711
     2712#if IS_PY3
     2713        encoding = self->encoding;
     2714#endif
     2715
    25962716        /* builds result */
    2597         for (i = 0; i < size; i++)
    2598         {
     2717        for (i = 0, k = self->current_row; i < size; i++, k++)
     2718        {
     2719                PyObject   *rowtuple;
     2720                int                     j;
     2721
    25992722                if (!(rowtuple = PyTuple_New(self->num_fields)))
    26002723                {
     
    26052728                for (j = 0; j < self->num_fields; j++)
    26062729                {
    2607                         if (PQgetisnull(self->result, self->current_row, j))
     2730                        PyObject   *str;
     2731
     2732                        if (PQgetisnull(self->result, k, j))
    26082733                        {
    26092734                                Py_INCREF(Py_None);
    26102735                                str = Py_None;
    26112736                        }
    2612                         else
    2613                                 str = PyStr_FromString(
    2614                                         PQgetvalue(self->result, self->current_row, j));
    2615 
     2737                        else {
     2738                                char *s = PQgetvalue(self->result, k, j);
     2739                                Py_ssize_t size = PQgetlength(self->result, k, j);
     2740#if IS_PY3
     2741                                if (PQfformat(self->result, j) == 0) /* textual format */
     2742                                {
     2743                                        str = get_decoded_string(s, size, encoding);
     2744                                        if (!str) /* cannot decode */
     2745                                                str = PyBytes_FromStringAndSize(s, size);
     2746                                }
     2747                                else
     2748#endif
     2749                                str = PyBytes_FromStringAndSize(s, size);
     2750                        }
    26162751                        PyTuple_SET_ITEM(rowtuple, j, str);
    26172752                }
     
    26192754                PyList_Append(reslist, rowtuple);
    26202755                Py_DECREF(rowtuple);
    2621                 self->current_row++;
    2622         }
    2623 
     2756        }
     2757
     2758        self->current_row = k;
    26242759        return reslist;
    26252760}
     
    28582993/* get the list of source object attributes */
    28592994static PyObject *
    2860 sourceDir(connObject *self) {
     2995sourceDir(connObject *self)
     2996{
    28612997        PyObject *attrs;
    28622998
     
    32293365queryGetResult(queryObject *self, PyObject *args)
    32303366{
    3231         PyObject   *rowtuple,
    3232                            *reslist,
    3233                            *val;
     3367        PyObject   *reslist;
    32343368        int                     i,
    3235                                 j,
    32363369                                m,
    32373370                                n,
    3238                            *typ;
     3371                           *coltypes;
    32393372#if IS_PY3
    32403373        int                     encoding;
    3241         const char *encoding_name=NULL;
    32423374#endif
    32433375
     
    32493381                return NULL;
    32503382        }
    3251 
    3252 #if IS_PY3
    3253         encoding = self->encoding;
    3254         if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
    3255                         && encoding != pg_encoding_ascii)
    3256                 /* should be translated to Python here */
    3257                 encoding_name = pg_encoding_to_char(encoding);
    3258 #endif
    32593383
    32603384        /* stores result in tuple */
    32613385        m = PQntuples(self->result);
    32623386        n = PQnfields(self->result);
    3263         reslist = PyList_New(m);
    3264 
    3265         typ = get_type_array(self->result, n);
     3387        if (!(reslist = PyList_New(m)))
     3388                return NULL;
     3389
     3390#if IS_PY3
     3391        encoding = self->encoding;
     3392#endif
     3393
     3394        coltypes = get_type_array(self->result, n);
    32663395
    32673396        for (i = 0; i < m; i++)
    32683397        {
     3398                PyObject   *rowtuple;
     3399                int                     j;
     3400
    32693401                if (!(rowtuple = PyTuple_New(n)))
    32703402                {
     
    32763408                for (j = 0; j < n; j++)
    32773409                {
    3278                         int                     k;
    3279                         char       *s = PQgetvalue(self->result, i, j);
    3280                         char            cashbuf[64];
    3281                         PyObject   *tmp_obj;
     3410                        PyObject * val;
    32823411
    32833412                        if (PQgetisnull(self->result, i, j))
     
    32873416                        }
    32883417                        else
    3289                                 switch (typ[j])
     3418                        {
     3419                                char       *s = PQgetvalue(self->result, i, j);
     3420                                char            cashbuf[64];
     3421                                int                     k;
     3422                                Py_ssize_t      size;
     3423                                PyObject   *tmp_obj;
     3424
     3425                                switch (coltypes[j])
    32903426                                {
    3291                                         case 1:  /* int2/4 */
     3427                                        case PYGRES_INT:
    32923428                                                val = PyInt_FromString(s, NULL, 10);
    32933429                                                break;
    32943430
    3295                                         case 2:  /* int8 */
     3431                                        case PYGRES_LONG:
    32963432                                                val = PyLong_FromString(s, NULL, 10);
    32973433                                                break;
    32983434
    3299                                         case 3:  /* float/double */
     3435                                        case PYGRES_FLOAT:
    33003436                                                tmp_obj = PyStr_FromString(s);
    33013437#if IS_PY3
     
    33073443                                                break;
    33083444
    3309                                         case 5:  /* money */
     3445                                        case PYGRES_MONEY:
    33103446                                                /* convert to decimal only if decimal point is set */
    33113447                                                if (!decimal_point) goto default_case;
    33123448
    33133449                                                for (k = 0;
    3314                                                          *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
    3315                                                          s++)
     3450                                                        *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
     3451                                                        s++)
    33163452                                                {
    33173453                                                        if (*s >= '0' && *s <= '9')
     
    33263462
    33273463                                        /* FALLTHROUGH */ /* no break */
    3328                                         case 4:  /* numeric */
     3464                                        case PYGRES_DECIMAL:
    33293465                                                if (decimal)
    33303466                                                {
     
    33463482                                        default:
    33473483                                        default_case:
     3484                                                size = PQgetlength(self->result, i, j);
    33483485#if IS_PY3
    3349                                                 if (encoding == pg_encoding_utf8)
    3350                                                         val = PyUnicode_DecodeUTF8(s, strlen(s), "strict");
    3351                                                 else if (encoding == pg_encoding_latin1)
    3352                                                         val = PyUnicode_DecodeLatin1(s, strlen(s), "strict");
    3353                                                 else if (encoding == pg_encoding_ascii)
    3354                                                         val = PyUnicode_DecodeASCII(s, strlen(s), "strict");
     3486                                                if (PQfformat(self->result, j) == 0) /* text */
     3487                                                {
     3488                                                        val = get_decoded_string(s, size, encoding);
     3489                                                        if (!val) /* cannot decode */
     3490                                                                val = PyBytes_FromStringAndSize(s, size);
     3491                                                }
    33553492                                                else
    3356                                                         val = PyUnicode_Decode(s, strlen(s),
    3357                                                                 encoding_name, "strict");
    3358                                                 if (!val)
    3359                                                         val = PyBytes_FromString(s);
    3360 #else
    3361                                                 val = PyBytes_FromString(s);
    33623493#endif
    3363                                                 break;
     3494                                                val = PyBytes_FromStringAndSize(s, size);
    33643495                                }
     3496                        }
    33653497
    33663498                        if (!val)
     
    33793511
    33803512exit:
    3381         free(typ);
     3513        free(coltypes);
    33823514
    33833515        /* returns list */
     
    33943526queryDictResult(queryObject *self, PyObject *args)
    33953527{
    3396         PyObject   *dict,
    3397                            *reslist,
    3398                            *val;
     3528        PyObject   *reslist;
    33993529        int                     i,
    3400                                 j,
    34013530                                m,
    34023531                                n,
    3403                            *typ;
     3532                           *coltypes;
    34043533#if IS_PY3
    34053534        int                     encoding;
    3406         const char *encoding_name=NULL;
    34073535#endif
    34083536
     
    34143542                return NULL;
    34153543        }
    3416 
    3417 #if IS_PY3
    3418         encoding = self->encoding;
    3419         if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
    3420                         && encoding != pg_encoding_ascii)
    3421                 /* should be translated to Python here */
    3422                 encoding_name = pg_encoding_to_char(encoding);
    3423 #endif
    34243544
    34253545        /* stores result in list */
    34263546        m = PQntuples(self->result);
    34273547        n = PQnfields(self->result);
    3428         reslist = PyList_New(m);
    3429 
    3430         typ = get_type_array(self->result, n);
     3548        if (!(reslist = PyList_New(m)))
     3549                return NULL;
     3550
     3551#if IS_PY3
     3552        encoding = self->encoding;
     3553#endif
     3554
     3555        coltypes = get_type_array(self->result, n);
    34313556
    34323557        for (i = 0; i < m; i++)
    34333558        {
     3559                PyObject   *dict;
     3560                int                     j;
     3561
    34343562                if (!(dict = PyDict_New()))
    34353563                {
     
    34413569                for (j = 0; j < n; j++)
    34423570                {
    3443                         int                     k;
    3444                         char       *s = PQgetvalue(self->result, i, j);
    3445                         char            cashbuf[64];
    3446                         PyObject   *tmp_obj;
     3571                        PyObject * val;
    34473572
    34483573                        if (PQgetisnull(self->result, i, j))
     
    34523577                        }
    34533578                        else
    3454                                 switch (typ[j])
     3579                        {
     3580                                char       *s = PQgetvalue(self->result, i, j);
     3581                                char            cashbuf[64];
     3582                                int                     k;
     3583                                Py_ssize_t      size;
     3584                                PyObject   *tmp_obj;
     3585
     3586                                switch (coltypes[j])
    34553587                                {
    3456                                         case 1:  /* int2/4 */
     3588                                        case PYGRES_INT:
    34573589                                                val = PyInt_FromString(s, NULL, 10);
    34583590                                                break;
    34593591
    3460                                         case 2:  /* int8 */
     3592                                        case PYGRES_LONG:
    34613593                                                val = PyLong_FromString(s, NULL, 10);
    34623594                                                break;
    34633595
    3464                                         case 3:  /* float/double */
     3596                                        case PYGRES_FLOAT:
    34653597                                                tmp_obj = PyBytes_FromString(s);
    34663598#if IS_PY3
     
    34723604                                                break;
    34733605
    3474                                         case 5:  /* money */
     3606                                        case PYGRES_MONEY:
    34753607                                                /* convert to decimal only if decimal point is set */
    34763608                                                if (!decimal_point) goto default_case;
    34773609
    34783610                                                for (k = 0;
    3479                                                          *s && k < sizeof(cashbuf) / sizeof(cashbuf[0]) - 1;
    3480                                                          s++)
     3611                                                        *s && k < sizeof(cashbuf)/sizeof(cashbuf[0]) - 1;
     3612                                                        s++)
    34813613                                                {
    34823614                                                        if (*s >= '0' && *s <= '9')
     
    34913623
    34923624                                        /* FALLTHROUGH */ /* no break */
    3493                                         case 4:  /* numeric */
     3625                                        case PYGRES_DECIMAL:
    34943626                                                if (decimal)
    34953627                                                {
     
    35113643                                        default:
    35123644                                        default_case:
     3645                                                size = PQgetlength(self->result, i, j);
    35133646#if IS_PY3
    3514                                                 if (encoding == pg_encoding_utf8)
    3515                                                         val = PyUnicode_DecodeUTF8(s, strlen(s), "strict");
    3516                                                 else if (encoding == pg_encoding_latin1)
    3517                                                         val = PyUnicode_DecodeLatin1(s, strlen(s), "strict");
    3518                                                 else if (encoding == pg_encoding_ascii)
    3519                                                         val = PyUnicode_DecodeASCII(s, strlen(s), "strict");
     3647                                                if (PQfformat(self->result, j) == 0) /* text */
     3648                                                {
     3649                                                        val = get_decoded_string(s, size, encoding);
     3650                                                        if (!val) /* cannot decode */
     3651                                                                val = PyBytes_FromStringAndSize(s, size);
     3652                                                }
    35203653                                                else
    3521                                                         val = PyUnicode_Decode(s, strlen(s),
    3522                                                                 encoding_name, "strict");
    3523                                                 if (!val)
    3524                                                         val = PyBytes_FromString(s);
    3525 #else
    3526                                                 val = PyBytes_FromString(s);
    35273654#endif
    3528                                                 break;
     3655                                                val = PyBytes_FromStringAndSize(s, size);
    35293656                                }
     3657                        }
    35303658
    35313659                        if (!val)
     
    35453673
    35463674exit:
    3547         free(typ);
     3675        free(coltypes);
    35483676
    35493677        /* returns list */
     
    36543782/* get the list of notice attributes */
    36553783static PyObject *
    3656 noticeDir(noticeObject *self) {
     3784noticeDir(noticeObject *self)
     3785{
    36573786        PyObject *attrs;
    36583787
     
    37663895pgEscapeString(PyObject *self, PyObject *args)
    37673896{
    3768         char *from; /* our string argument */
    3769         char *to=NULL; /* the result */
    3770         int from_length; /* length of string */
    3771         int to_length; /* length of result */
    3772         PyObject *ret; /* string object to return */
    3773 
    3774         if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
    3775                 return NULL;
     3897        PyObject   *from_obj, /* the object that was passed in */
     3898                           *to_obj; /* string object to return */
     3899        char       *from=NULL, /* our string argument as encoded string */
     3900                           *to; /* the result as encoded string */
     3901        Py_ssize_t      from_length; /* length of string */
     3902        size_t          to_length; /* length of result */
     3903        int                     encoding = -1; /* client encoding */
     3904
     3905        if (!PyArg_ParseTuple(args, "O", &from_obj))
     3906                return NULL;
     3907
     3908        if (PyBytes_Check(from_obj))
     3909        {
     3910                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     3911        }
     3912        else if (PyUnicode_Check(from_obj))
     3913        {
     3914                encoding = pg_encoding_ascii;
     3915                from_obj = get_encoded_string(from_obj, encoding);
     3916                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     3917                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     3918        }
     3919        if (!from)
     3920        {
     3921                PyErr_SetString(PyExc_TypeError, "escape_string() expects a string.");
     3922                return NULL;
     3923        }
     3924
    37763925        to_length = 2*from_length + 1;
    37773926        if (to_length < from_length) /* overflow */
     
    37823931        to = (char *)malloc(to_length);
    37833932        to_length = (int)PQescapeString(to, from, (size_t)from_length);
    3784         ret = Py_BuildValue("s#", to, to_length);
     3933
     3934        if (encoding == -1)
     3935                to_obj = PyBytes_FromStringAndSize(to, to_length);
     3936        else
     3937                to_obj = get_decoded_string(to, to_length, encoding);
    37853938        if (to)
    37863939                free(to);
    3787         if (!ret) /* pass on exception */
    3788                 return NULL;
    3789         return ret;
     3940        return to_obj;
    37903941}
    37913942
     
    37973948pgEscapeBytea(PyObject *self, PyObject *args)
    37983949{
    3799         unsigned char *from; /* our string argument */
    3800         unsigned char *to; /* the result */
    3801         int from_length; /* length of string */
    3802         size_t to_length; /* length of result */
    3803         PyObject *ret; /* string object to return */
    3804 
    3805         if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
    3806                 return NULL;
    3807         to = PQescapeBytea(from, (int)from_length, &to_length);
    3808         ret = Py_BuildValue("s", to);
     3950        PyObject   *from_obj, /* the object that was passed in */
     3951                           *to_obj; /* string object to return */
     3952        char       *from=NULL, /* our string argument as encoded string */
     3953                           *to; /* the result as encoded string */
     3954        Py_ssize_t      from_length; /* length of string */
     3955        size_t          to_length; /* length of result */
     3956        int                     encoding = -1; /* client encoding */
     3957
     3958        if (!PyArg_ParseTuple(args, "O", &from_obj))
     3959                return NULL;
     3960
     3961        if (PyBytes_Check(from_obj))
     3962        {
     3963                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     3964        }
     3965        else if (PyUnicode_Check(from_obj))
     3966        {
     3967                encoding = pg_encoding_ascii;
     3968                from_obj = get_encoded_string(from_obj, encoding);
     3969                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     3970                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     3971        }
     3972        if (!from)
     3973        {
     3974                PyErr_SetString(PyExc_TypeError, "escape_bytea() expects a string.");
     3975                return NULL;
     3976        }
     3977
     3978        to = (char *)PQescapeBytea(
     3979                (unsigned char*)from, (size_t)from_length, &to_length);
     3980
     3981        if (encoding == -1)
     3982                to_obj = PyBytes_FromStringAndSize(to, to_length - 1);
     3983        else
     3984                to_obj = get_decoded_string(to, to_length - 1, encoding);
    38093985        if (to)
    3810                 PQfreemem((void *)to);
    3811         if (!ret) /* pass on exception */
    3812                 return NULL;
    3813         return ret;
     3986                PQfreemem(to);
     3987        return to_obj;
    38143988}
    38153989
     
    38213995*pgUnescapeBytea(PyObject *self, PyObject *args)
    38223996{
    3823         unsigned char *from; /* our string argument */
    3824         unsigned char *to; /* the result */
    3825         int from_length; /* length of string */
    3826         size_t to_length; /* length of result string */
    3827         PyObject *ret; /* string object to return */
    3828 
    3829         if (!PyArg_ParseTuple(args, "s#", &from, &from_length))
    3830                 return NULL;
    3831         to = PQunescapeBytea(from, &to_length);
    3832         if (!to)
    3833             return NULL;
    3834         ret = Py_BuildValue("s#", to, (int)to_length);
     3997        PyObject   *from_obj, /* the object that was passed in */
     3998                           *to_obj; /* string object to return */
     3999        char       *from=NULL, /* our string argument as encoded string */
     4000                           *to; /* the result as encoded string */
     4001        Py_ssize_t      from_length; /* length of string */
     4002        size_t          to_length; /* length of result */
     4003
     4004        if (!PyArg_ParseTuple(args, "O", &from_obj))
     4005                return NULL;
     4006
     4007        if (PyBytes_Check(from_obj))
     4008        {
     4009                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     4010        }
     4011        else if (PyUnicode_Check(from_obj))
     4012        {
     4013                from_obj = get_encoded_string(from_obj, pg_encoding_ascii);
     4014                if (!from_obj) return NULL; /* pass the UnicodeEncodeError */
     4015                PyBytes_AsStringAndSize(from_obj, &from, &from_length);
     4016        }
     4017        if (!from)
     4018        {
     4019                PyErr_SetString(PyExc_TypeError, "unescape_bytea() expects a string.");
     4020                return NULL;
     4021        }
     4022
     4023        to = (char *)PQunescapeBytea((unsigned char*)from, &to_length);
     4024
     4025        to_obj = PyBytes_FromStringAndSize(to, to_length);
    38354026        if (to)
    3836             PQfreemem((void *)to);
    3837         if (!ret) /* pass on exception */
    3838                 return NULL;
    3839         return ret;
     4027                PQfreemem(to);
     4028        return to_obj;
    38404029}
    38414030
     
    38514040
    38524041        /* gets arguments */
    3853         if (PyArg_ParseTuple(args, "z", &s)) {
     4042        if (PyArg_ParseTuple(args, "z", &s))
     4043        {
    38544044                if (!s)
    38554045                        s = "\0";
     
    38584048        }
    38594049
    3860         if (s) {
     4050        if (s)
     4051        {
    38614052                decimal_point = *s;
    38624053                Py_INCREF(Py_None); ret = Py_None;
     
    38814072        if (PyArg_ParseTuple(args, ""))
    38824073        {
    3883                 if (decimal_point) {
     4074                if (decimal_point)
     4075                {
    38844076                        s[0] = decimal_point; s[1] = '\0';
    38854077                        ret = PyStr_FromString(s);
Note: See TracChangeset for help on using the changeset viewer.