]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
sqlalchemy/dialects/postgresql/pgjson:
authornathan <nathan.alexander.rice@gmail.com>
Tue, 10 Dec 2013 15:01:51 +0000 (10:01 -0500)
committernathan <nathan.alexander.rice@gmail.com>
Tue, 10 Dec 2013 15:01:51 +0000 (10:01 -0500)
 - Fixed reference to HSTORE
 - Corrected spelling of SQLAlchemy

 sqlalchemy/dialects/postgresql/psycopg2:
 - Added psycopg2 specific wrapper type for JSON which uses inherent json deserialization facilities
 - Added code to detect and utilize the JSON wrapper if psycopg2 >= 2.5

test/dialect/postgresql/test_types:
- removed reference to use_native_hstore

lib/sqlalchemy/dialects/postgresql/pgjson.py
lib/sqlalchemy/dialects/postgresql/psycopg2.py
test/dialect/postgresql/test_types.py

index aef54709bbcafd5c9c77d708145ef55c0009c698..161fe83fa895a3552069ecd3c8e271437b4435be 100644 (file)
@@ -16,7 +16,7 @@ __all__ = ('JSON', 'json')
 
 
 class JSON(sqltypes.TypeEngine):
-    """Represent the Postgresql HSTORE type.
+    """Represent the Postgresql JSON type.
 
     The :class:`.JSON` type stores arbitrary JSON format data, e.g.::
 
@@ -41,7 +41,7 @@ class JSON(sqltypes.TypeEngine):
 
         data_table.c.data.get_path('{key_1, key_2, ..., key_n}']
 
-    Please be aware that when used with the SQL Alchemy ORM, you will need to
+    Please be aware that when used with the SQLAlchemy ORM, you will need to
     replace the JSON object present on an attribute with a new object in order
     for any changes to be properly persisted.
 
index d7ce6eb90b8978c4d25d116f7c4b8ec4ed31d089..1f40785009d27992b9ac948f7726478292c66a32 100644 (file)
@@ -168,6 +168,8 @@ from __future__ import absolute_import
 import re
 import logging
 
+import psycopg2.extensions as ext
+
 from ... import util, exc
 import decimal
 from ... import processors
@@ -179,6 +181,7 @@ from .base import PGDialect, PGCompiler, \
                                 ENUM, ARRAY, _DECIMAL_TYPES, _FLOAT_TYPES,\
                                 _INT_TYPES
 from .hstore import HSTORE
+from .pgjson import JSON
 
 
 logger = logging.getLogger('sqlalchemy.dialects.postgresql')
@@ -243,6 +246,17 @@ class _PGHStore(HSTORE):
         else:
             return super(_PGHStore, self).result_processor(dialect, coltype)
 
+
+class _PGJSON(JSON):
+    # I've omitted the bind processor here because the method of serializing
+    # involves registering specific types to auto-serialize, and the adapter
+    # just a thin wrapper over json.dumps.
+    def result_processor(self, dialect, coltype):
+        if dialect._has_native_json:
+            return None
+        else:
+            return super(_PGJSON, self).result_processor(dialect, coltype)
+
 # When we're handed literal SQL, ensure it's a SELECT-query. Since
 # 8.3, combining cursors and "FOR UPDATE" has been fine.
 SERVER_SIDE_CURSOR_RE = re.compile(
@@ -327,6 +341,7 @@ class PGDialect_psycopg2(PGDialect):
     psycopg2_version = (0, 0)
 
     _has_native_hstore = False
+    _has_native_json = False
 
     colspecs = util.update_copy(
         PGDialect.colspecs,
@@ -336,6 +351,7 @@ class PGDialect_psycopg2(PGDialect):
             sqltypes.Enum: _PGEnum,  # needs force_unicode
             ARRAY: _PGArray,  # needs force_unicode
             HSTORE: _PGHStore,
+            JSON: _PGJSON
         }
     )
 
@@ -363,6 +379,7 @@ class PGDialect_psycopg2(PGDialect):
         self._has_native_hstore = self.use_native_hstore and \
                         self._hstore_oids(connection.connection) \
                             is not None
+        self._has_native_json = self.psycopg2_version >= (2, 5)
 
     @classmethod
     def dbapi(cls):
index 5a944ae9d0d27aa2b78b145c4342e7a669da412a..114b36f8f4c34de09119f83b2a8ff9dd72525219 100644 (file)
@@ -1768,7 +1768,7 @@ class JSONRoundTripTest(fixtures.TablesTest):
 
     def _non_native_engine(self):
         if testing.against("postgresql+psycopg2"):
-            engine = engines.testing_engine(options=dict(use_native_hstore=False))
+            engine = engines.testing_engine()
         else:
             engine = testing.db
         engine.connect()