[server] add a db-namespace option in source definition (closes #1631339)
authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
Wed, 03 Dec 2014 16:29:16 +0100
changeset 10125 bc6461a7d2da
parent 10124 153c969b3a05
child 10126 459c5585d2f1
[server] add a db-namespace option in source definition (closes #1631339) "namespace" is preferred to the postgresql term "schema" to try and avoid confusion with cubicweb's schema. cubicweb now depends on logilab-database >= 1.13.0
__pkginfo__.py
cubicweb.spec
debian/control
server/serverctl.py
server/sources/native.py
server/sqlutils.py
--- a/__pkginfo__.py	Fri Dec 19 12:08:01 2014 +0100
+++ b/__pkginfo__.py	Wed Dec 03 16:29:16 2014 +0100
@@ -48,7 +48,7 @@
     'lxml': '',
     # XXX graphviz
     # server dependencies
-    'logilab-database': '>= 1.12.1',
+    'logilab-database': '>= 1.13.0',
     'passlib': '',
     'Markdown': ''
     }
--- a/cubicweb.spec	Fri Dec 19 12:08:01 2014 +0100
+++ b/cubicweb.spec	Wed Dec 03 16:29:16 2014 +0100
@@ -24,7 +24,7 @@
 Requires:       %{python}-logilab-mtconverter >= 0.8.0
 Requires:       %{python}-rql >= 0.31.2
 Requires:       %{python}-yams >= 0.40.0
-Requires:       %{python}-logilab-database >= 1.12.1
+Requires:       %{python}-logilab-database >= 1.13.0
 Requires:       %{python}-passlib
 Requires:       %{python}-lxml
 Requires:       %{python}-twisted-web
--- a/debian/control	Fri Dec 19 12:08:01 2014 +0100
+++ b/debian/control	Wed Dec 03 16:29:16 2014 +0100
@@ -52,7 +52,7 @@
  ${python:Depends},
  cubicweb-common (= ${source:Version}),
  cubicweb-ctl (= ${source:Version}),
- python-logilab-database (>= 1.12.1),
+ python-logilab-database (>= 1.13.0),
  cubicweb-postgresql-support
  | cubicweb-mysql-support
  | python-pysqlite2,
--- a/server/serverctl.py	Fri Dec 19 12:08:01 2014 +0100
+++ b/server/serverctl.py	Wed Dec 03 16:29:16 2014 +0100
@@ -88,6 +88,7 @@
     extra = extra_args and {'extra_args': extra_args} or {}
     cnx = get_connection(driver, dbhost, dbname, user, password=password,
                          port=source.get('db-port'),
+                         schema=source.get('db-namespace'),
                          **extra)
     try:
         cnx.logged_user = user
@@ -242,6 +243,13 @@
     cmdname = 'delete'
     cfgname = 'repository'
 
+    def _drop_namespace(self, source):
+        db_namespace = source.get('db-namespace')
+        with db_transaction(source, privilege='DROP SCHEMA') as cursor:
+            helper = get_db_helper(source['db-driver'])
+            helper.drop_schema(cursor, db_namespace)
+            print '-> database schema %s dropped' % db_namespace
+
     def _drop_database(self, source):
         dbname = source['db-name']
         if source['db-driver'] == 'sqlite':
@@ -263,10 +271,15 @@
                 cursor.execute('DROP USER %s' % user)
 
     def _cleanup_steps(self, source):
-        # 1/ delete database
+        # 1/ delete namespace if used
+        db_namespace = source.get('db-namespace')
+        if db_namespace:
+            yield ('Delete database namespace "%s"' % db_namespace,
+                   self._drop_namespace, True)
+        # 2/ delete database
         yield ('Delete database "%(db-name)s"' % source,
                self._drop_database, True)
-        # 2/ delete user
+        # 3/ delete user
         helper = get_db_helper(source['db-driver'])
         if source['db-user'] and helper.users_support:
             # XXX should check we are not connected as user
@@ -402,10 +415,14 @@
             except BaseException:
                 dbcnx.rollback()
                 raise
-        cnx = system_source_cnx(source, special_privs='CREATE LANGUAGE',
+        cnx = system_source_cnx(source, special_privs='CREATE LANGUAGE/SCHEMA',
                                 interactive=not automatic)
         cursor = cnx.cursor()
         helper.init_fti_extensions(cursor)
+        namespace = source.get('db-namespace')
+        if namespace and ASK.confirm('Create schema %s in database %s ?'
+                                     % (namespace, dbname)):
+            helper.create_schema(cursor, namespace)
         cnx.commit()
         # postgres specific stuff
         if driver == 'postgres':
@@ -480,7 +497,7 @@
                 system['db-driver'], database=system['db-name'],
                 host=system.get('db-host'), port=system.get('db-port'),
                 user=system.get('db-user') or '', password=system.get('db-password') or '',
-                **extra)
+                schema=system.get('db-namespace'), **extra)
         except Exception as ex:
             raise ConfigurationError(
                 'You seem to have provided wrong connection information in '\
--- a/server/sources/native.py	Fri Dec 19 12:08:01 2014 +0100
+++ b/server/sources/native.py	Wed Dec 03 16:29:16 2014 +0100
@@ -293,6 +293,12 @@
           'help': 'database name',
           'group': 'native-source', 'level': 0,
           }),
+        ('db-namespace',
+         {'type' : 'string',
+          'default': '',
+          'help': 'database namespace (schema) name',
+          'group': 'native-source', 'level': 1,
+          }),
         ('db-user',
          {'type' : 'string',
           'default': CubicWebNoAppConfiguration.mode == 'user' and getlogin() or 'cubicweb',
--- a/server/sqlutils.py	Fri Dec 19 12:08:01 2014 +0100
+++ b/server/sqlutils.py	Wed Dec 03 16:29:16 2014 +0100
@@ -312,10 +312,11 @@
         dbpassword = source_config.get('db-password')
         dbencoding = source_config.get('db-encoding', 'UTF-8')
         dbextraargs = source_config.get('db-extra-arguments')
+        dbnamespace = source_config.get('db-namespace')
         self.dbhelper = db.get_db_helper(self.dbdriver)
         self.dbhelper.record_connection_info(dbname, dbhost, dbport, dbuser,
                                              dbpassword, dbextraargs,
-                                             dbencoding)
+                                             dbencoding, dbnamespace)
         self.sqlgen = SQLGenerator()
         # copy back some commonly accessed attributes
         dbapi_module = self.dbhelper.dbapi_module