|
@@ -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
|
+
|