Repository: ckan/ckan

Issue:
datastore plugin pgsql check on datastore DB, not main DB
I ran into a confusing situation here, getting "We detected that you do not use a PostgreSQL database. The DataStore will NOT work and DataStore tests will be skipped." I had the datastore as postgres://, so I tried changing to postgresql:// and got the same error. I googled, found PR 359 which says it's looking for 'postgresql', got more confused, looked through the code ...

Finally realized the code is checking the sqlalchemy.url, _not_ the datastore URL. This doesn't seem to be the right behavior or match the error message, so I made a simple patch to apply the same drivername startswith check to the datastore write_url directly, which seems the least-invasive way to make the behavior/error more understandable.



Discussion:
@themgt Good catch. I didn't think someone would use a different db for CKAN and the datastore. We will need to write it a little bit different, though. 


Resolving patch:
diff --git a/ckan/model/meta.py b/ckan/model/meta.py
--- a/ckan/model/meta.py
+++ b/ckan/model/meta.py
@@ -154,13 +154,13 @@ def after_rollback(self, session):
 metadata = MetaData()
 
 
-def engine_is_sqlite():
+def engine_is_sqlite(sa_engine=None):
     # Returns true iff the engine is connected to a sqlite database.
-    return engine.url.drivername == 'sqlite'
+    return (sa_engine or engine).url.drivername == 'sqlite'
 
 
-def engine_is_pg():
+def engine_is_pg(sa_engine=None):
     # Returns true iff the engine is connected to a postgresql database.
     # According to http://docs.sqlalchemy.org/en/latest/core/engines.html#postgresql
     # all Postgres driver names start with `postgresql`
-    return engine.url.drivername.startswith('postgresql')
+    return (sa_engine or engine).url.drivername.startswith('postgresql')
diff --git a/ckanext/datastore/plugin.py b/ckanext/datastore/plugin.py
--- a/ckanext/datastore/plugin.py
+++ b/ckanext/datastore/plugin.py
@@ -52,7 +52,9 @@ def configure(self, config):
         else:
             self.read_url = self.config['ckan.datastore.read_url']
 
-        if not model.engine_is_pg():
+        read_engine = db._get_engine(
+            None, {'connection_url': self.read_url})
+        if not model.engine_is_pg(read_engine):
             log.warn('We detected that you do not use a PostgreSQL '
                      'database. The DataStore will NOT work and DataStore '
                      'tests will be skipped.')
@@ -75,13 +77,9 @@ def configure(self, config):
         resource_show = p.toolkit.get_action('resource_show')
 
         def new_resource_show(context, data_dict):
-            engine = db._get_engine(
-                context,
-                {'connection_url': self.read_url}
-            )
             new_data_dict = resource_show(context, data_dict)
             try:
-                connection = engine.connect()
+                connection = read_engine.connect()
                 result = connection.execute(
                     'SELECT 1 FROM "_table_metadata" WHERE name = %s AND alias_of IS NULL',
                     new_data_dict['id']


Test patch:
diff --git a/ckan/tests/__init__.py b/ckan/tests/__init__.py
--- a/ckan/tests/__init__.py
+++ b/ckan/tests/__init__.py
@@ -334,6 +334,7 @@ def is_migration_supported():
     return is_supported_db
 
 def is_datastore_supported():
+    # we assume that the datastore uses the same db engine that ckan uses
     is_supported_db = model.engine_is_pg()
     return is_supported_db