Browse Source

Modified SqlWrapper to handle SqlSetup script

Now SQLSetup in able (via initDb) to initialize the database.
WARNING : initDb start by droping all tables in database before creating the new ones
Yann Weber 9 years ago
parent
commit
ddfbb2b056
2 changed files with 111 additions and 6 deletions
  1. 4
    4
      Database/sqlsetup.py
  2. 107
    2
      Database/sqlwrapper.py

+ 4
- 4
Database/sqlsetup.py View File

@@ -4,11 +4,11 @@ from Database.sqlwrapper import SqlWrapper
4 4
 
5 5
 class SQLSetup(object): 
6 6
 
7
-    def initDb(self):
8
-        db = SqlWrapper()
7
+    def initDb(self, dbconfname = 'default'):
8
+        db = SqlWrapper(read_db = dbconfname, write_db = dbconfname)
9 9
         tables = self.get_schema()
10
-        for table in tables:
11
-            err = db.create_table(table)
10
+        db.dropAll()
11
+        db.createAllFromConf(tables)
12 12
 
13 13
     def get_schema(self):
14 14
         tables = []

+ 107
- 2
Database/sqlwrapper.py View File

@@ -1,5 +1,6 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import os
3
+import re
3 4
 import logging as logger
4 5
 
5 6
 import sqlalchemy as sqla
@@ -55,7 +56,7 @@ class SqlWrapper(object):
55 56
         self.checkConf() #raise if errors in configuration
56 57
 
57 58
         if name in self.__class__.wrapinstance:
58
-            logger.wraning("A SqlWrapper with the name "+name+" allready exist. Replacing the old one by the new one")
59
+            logger.warning("A SqlWrapper with the name "+name+" allready exist. Replacing the old one by the new one")
59 60
         SqlWrapper.wrapinstance[name] = self
60 61
 
61 62
         #Engine and wrapper initialisation
@@ -63,6 +64,9 @@ class SqlWrapper(object):
63 64
         self.w_engine = self._getEngine(False, self.sqlalogging)
64 65
         self.r_conn = None
65 66
         self.w_conn = None
67
+
68
+
69
+        self.meta = None
66 70
         pass
67 71
 
68 72
     @property
@@ -188,6 +192,7 @@ class SqlWrapper(object):
188 192
             conn_str = '%s+%s://'%(cfg['ENGINE'], edata['driver'])
189 193
             conn_str += '%s@%s/%s'%(user,host,cfg['NAME'])
190 194
 
195
+
191 196
         return sqla.create_engine(conn_str, encoding=edata['encoding'], echo=self.sqlalogging)
192 197
 
193 198
     @classmethod
@@ -241,4 +246,104 @@ class SqlWrapper(object):
241 246
             for e in err:
242 247
                 err_str += "\t\t"+e+"\n"
243 248
             raise NameError('Configuration errors in LODEL2SQLWRAPPER:'+err_str)
244
-                
249
+    
250
+    def dropAll(self):
251
+        """ Drop ALL tables from the database """
252
+        if not settings.DEBUG:
253
+            logger.critical("Trying to drop all tables but we are not in DEBUG !!!")
254
+            raise RuntimeError("Trying to drop all tables but we are not in DEBUG !!!")
255
+        meta = sqla.MetaData(bind=self.w_engine, reflect = True)
256
+        meta.drop_all()
257
+        pass
258
+
259
+    def createAllFromConf(self, schema):
260
+        """ Create a bunch of tables from a schema
261
+            @param schema list: A list of table schema
262
+            @see SqlWrapper::createTable()
263
+        """
264
+        self.meta_crea = sqla.MetaData()
265
+
266
+        for i,table in enumerate(schema):
267
+            self.createTable(**table)
268
+
269
+        self.meta_crea.create_all(self.w_engine)
270
+        self.meta_crea = None
271
+        pass
272
+            
273
+    def createTable(self, name, columns, extra = dict()):
274
+        """ Create a table
275
+            @param name str: The table name
276
+            @param columns list: A list of columns schema
277
+            @param extra dict: Extra arguments for table creation
278
+            @see SqlWrapper::createColumn()
279
+        """
280
+        if not isinstance(name, str):
281
+            raise TypeError("<class str> excepted for table name, but got "+type(name))
282
+
283
+        res = sqla.Table(name, self.meta_crea, **extra)
284
+        for i,col in enumerate(columns):
285
+            res.append_column(self.createColumn(**col))
286
+
287
+    def createColumn(self, **kwargs):
288
+        """ Create a Column
289
+            
290
+            Accepte named parameters :
291
+                - name : The column name
292
+                - type : see SqlWrapper::_strToSqlAType()
293
+                - extra : a dict like { "primarykey":True, "nullable":False, "default":"test"...}
294
+            @param **kwargs 
295
+        """
296
+        if not 'name' in kwargs or not 'type' in kwargs:
297
+            pass#ERROR
298
+
299
+        #Converting parameters
300
+        kwargs['type_'] = self._strToSqlAType(kwargs['type'])
301
+        del kwargs['type']
302
+
303
+        if 'extra' in kwargs:
304
+            #put the extra keys in kwargs
305
+            for exname in kwargs['extra']:
306
+                kwargs[exname] = kwargs['extra'][exname]
307
+            del kwargs['extra']
308
+
309
+        if 'foreignkey' in kwargs:
310
+            #Instanciate a fk
311
+            fk = sqla.ForeignKey(kwargs['foreignkey'])
312
+            del kwargs['foreignkey']
313
+        else:
314
+            fk = None
315
+
316
+        if 'primarykey' in kwargs:
317
+            #renaming primary_key in primarykey in kwargs
318
+            kwargs['primary_key'] = kwargs['primarykey']
319
+            del kwargs['primarykey']
320
+
321
+
322
+        logger.debug('Column creation arguments : '+str(kwargs))
323
+        res = sqla.Column(**kwargs)
324
+
325
+        if fk != None:
326
+            res.append_foreign_key(fk)
327
+
328
+        return res
329
+    
330
+    def _strToSqlAType(self, strtype):
331
+        """ Convert a string to an sqlAlchemy column type """
332
+
333
+        if 'VARCHAR' in strtype:
334
+            return self._strToVarchar(strtype)
335
+        else:
336
+            try:
337
+                return getattr(sqla, strtype)
338
+            except AttributeError:
339
+                raise NameError("Unknown type '"+strtype+"'")
340
+        pass
341
+
342
+    def _strToVarchar(self, vstr):
343
+        """ Convert a string like 'VARCHAR(XX)' (with XX an integer) to a SqlAlchemy varchar type"""
344
+        check_length = re.search(re.compile('VARCHAR\(([\d]+)\)', re.IGNORECASE), vstr)
345
+        column_length = int(check_length.groups()[0]) if check_length else None
346
+        return sqla.VARCHAR(length=column_length)
347
+        
348
+
349
+

Loading…
Cancel
Save