Browse Source

Merge branch 'sqlupdates' with SQL isolation and sqlsetup fixes

Yann Weber 10 years ago
parent
commit
b1ffef53b9
4 changed files with 126 additions and 58 deletions
  1. 16
    16
      Database/sqlsetup.py
  2. 15
    10
      Database/sqlwrapper.py
  3. 40
    12
      EditorialModel/classes.py
  4. 55
    20
      EditorialModel/components.py

+ 16
- 16
Database/sqlsetup.py View File

@@ -5,7 +5,7 @@ from Database.sqlwrapper import SqlWrapper
5 5
 class SQLSetup(object): 
6 6
 
7 7
     def initDb(self, dbconfname = 'default'):
8
-        db = SqlWrapper(read_db = dbconfname, write_db = dbconfname)
8
+        db = SqlWrapper(read_db = dbconfname, write_db = dbconfname, alchemy_logs=True)
9 9
         tables = self.get_schema()
10 10
         db.dropAll()
11 11
         db.createAllFromConf(tables)
@@ -14,7 +14,7 @@ class SQLSetup(object):
14 14
         tables = []
15 15
 
16 16
         default_columns = [
17
-            {"name":"uid",          "type":"VARCHAR(50)", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
17
+            {"name":"uid",          "type":"INTEGER", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
18 18
             {"name":"name",         "type":"VARCHAR(50)", "extra":{"nullable":False, "unique":True}},
19 19
             {"name":"string",       "type":"TEXT"},
20 20
             {"name":"help",         "type":"TEXT"},
@@ -47,7 +47,7 @@ class SQLSetup(object):
47 47
         # Table listing the types
48 48
         em_type = {"name":"em_type"}
49 49
         em_type['columns'] = default_columns + [
50
-            {"name":"class_id",     "type":"VARCHAR(50)", "extra":{"foreignkey":"em_class.uid", "nullable":False}},
50
+            {"name":"class_id",     "type":"INTEGER", "extra":{"foreignkey":"em_class.uid", "nullable":False}},
51 51
             {"name":"sortcolumn",   "type":"VARCHAR(50)", "extra":{"default":"rank"}},
52 52
             {"name":"icon",         "type":"INTEGER"},
53 53
         ]
@@ -56,8 +56,8 @@ class SQLSetup(object):
56 56
         # relation between types: which type can be a child of another
57 57
         em_type_hierarchy = {"name":"em_type_hierarchy"}
58 58
         em_type_hierarchy['columns'] = [
59
-            {"name":"superior_id",    "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
60
-            {"name":"subordinate_id", "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
59
+            {"name":"superior_id",    "type":"INTEGER", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
60
+            {"name":"subordinate_id", "type":"INTEGER", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
61 61
             {"name":"nature",         "type":"VARCHAR(50)"},
62 62
         ]
63 63
         tables.append(em_type_hierarchy)
@@ -65,17 +65,17 @@ class SQLSetup(object):
65 65
        # Table listing the fieldgroups of a class
66 66
         em_fieldgroup = {"name":"em_fieldgroup"}
67 67
         em_fieldgroup['columns'] = default_columns + [
68
-            {"name":"class_id",     "type":"VARCHAR(50)", "extra":{"foreignkey":"em_class.uid", "nullable":False}},
68
+            {"name":"class_id",     "type":"INTEGER", "extra":{"foreignkey":"em_class.uid", "nullable":False}},
69 69
         ]
70 70
         tables.append(em_fieldgroup)
71 71
 
72 72
         # Table listing the fields of a fieldgroup
73 73
         em_field = {"name":"em_field"}
74 74
         em_field['columns'] = default_columns + [
75
-            {"name":"fieldtype_id",   "type":"VARCHAR(50)", "extra":{"nullable":False}},
76
-            {"name":"fieldgroup_id",  "type":"VARCHAR(50)", "extra":{"foreignkey":"em_fieldgroup.uid", "nullable":False}},
77
-            {"name":"rel_to_type_id", "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid", "nullable":False}}, # if relational: type this field refer to
78
-            {"name":"rel_field_id",   "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid", "nullable":False}}, # if relational: field that specify the rel_to_type_id
75
+            {"name":"fieldtype_id",   "type":"INTEGER", "extra":{"nullable":False}},
76
+            {"name":"fieldgroup_id",  "type":"INTEGER", "extra":{"foreignkey":"em_fieldgroup.uid", "nullable":False}},
77
+            {"name":"rel_to_type_id", "type":"INTEGER", "extra":{"foreignkey":"em_type.uid", "nullable":False}}, # if relational: type this field refer to
78
+            {"name":"rel_field_id",   "type":"INTEGER", "extra":{"foreignkey":"em_type.uid", "nullable":False}}, # if relational: field that specify the rel_to_type_id
79 79
             {"name":"optional",       "type":"BOOLEAN"},
80 80
             {"name":"internal",       "type":"BOOLEAN"},
81 81
             {"name":"icon",           "type":"INTEGER"},
@@ -85,8 +85,8 @@ class SQLSetup(object):
85 85
         # selected field for each type
86 86
         em_field_type = {"name":"em_field_type"}
87 87
         em_field_type['columns'] = [
88
-            {"name":"type_id",   "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
89
-            {"name":"field_id",  "type":"VARCHAR(50)", "extra":{"foreignkey":"em_field.uid", "nullable":False, "primarykey":True}},
88
+            {"name":"type_id",   "type":"INTEGER", "extra":{"foreignkey":"em_type.uid", "nullable":False, "primarykey":True}},
89
+            {"name":"field_id",  "type":"INTEGER", "extra":{"foreignkey":"em_field.uid", "nullable":False, "primarykey":True}},
90 90
         ]
91 91
         tables.append(em_field_type)
92 92
 
@@ -94,10 +94,10 @@ class SQLSetup(object):
94 94
         objects = {
95 95
             "name":"objects",
96 96
             "columns":[
97
-                {"name":"uid",         "type":"VARCHAR(50)", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
97
+                {"name":"uid",         "type":"INTEGER", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
98 98
                 {"name":"string",      "type":"VARCHAR(50)"},
99
-                {"name":"class_id",    "type":"VARCHAR(50)", "extra":{"foreignkey":"em_class.uid"}},
100
-                {"name":"type_id",     "type":"VARCHAR(50)", "extra":{"foreignkey":"em_type.uid"}},
99
+                {"name":"class_id",    "type":"INTEGER", "extra":{"foreignkey":"em_class.uid"}},
100
+                {"name":"type_id",     "type":"INTEGER", "extra":{"foreignkey":"em_type.uid"}},
101 101
                 {"name":"date_update", "type":"DATE"},
102 102
                 {"name":"date_create", "type":"DATE"},
103 103
                 {"name":"history",     "type":"TEXT"}
@@ -110,7 +110,7 @@ class SQLSetup(object):
110 110
         files = {
111 111
             "name":"files",
112 112
             "columns":[
113
-                {"name":"uid",     "type":"VARCHAR(50)", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
113
+                {"name":"uid",     "type":"INTEGER", "extra":{"foreignkey":"uids.uid", "nullable":False, "primarykey":True}},
114 114
                 {"name":"field1",  "type":"VARCHAR(50)"}
115 115
             ]
116 116
         }

+ 15
- 10
Database/sqlwrapper.py View File

@@ -81,6 +81,10 @@ class SqlWrapper(object):
81 81
         logger.debug("New wrapper instance : <"+self.name+" read:"+str(self.r_engine)+" write:"+str(self.w_engine))
82 82
         pass
83 83
 
84
+    @classmethod
85
+    def getEngine(c, ename = 'default', logs = None):
86
+        return c(read_db = ename, write_db = ename, alchemy_logs = logs).r_engine
87
+
84 88
     @property
85 89
     def cfg(self):
86 90
         """ Return the SqlWrapper.config dict """
@@ -273,13 +277,10 @@ class SqlWrapper(object):
273 277
                     err.append('Missing "'+dbname+'" db configuration')
274 278
                 else:
275 279
                     db = self.cfg['db'][dbname]
276
-                    if 'ENGINE' not in db:
277
-                        err.append('Missing "ENGINE" in database "'+db+'"')
278
-                    else:
279
-                        if db['ENGINE'] not in self._engines_cfg:
280
-                            err.append('Unknown engine "'+db['ENGINE']+'"')
281
-                        elif db['ENGINE'] != 'sqlite' and 'USER' not in db:
282
-                            err.append('Missing "User" in configuration of database "'+dbname+'"')
280
+                    if db['ENGINE'] not in self._engines_cfg:
281
+                        err.append('Unknown engine "'+db['ENGINE']+'"')
282
+                    elif db['ENGINE'] != 'sqlite' and 'USER' not in db:
283
+                        err.append('Missing "User" in configuration of database "'+dbname+'"')
283 284
                     if 'NAME' not in db:
284 285
                         err.append('Missing "NAME" in database "'+dbname+'"')
285 286
                         
@@ -294,7 +295,8 @@ class SqlWrapper(object):
294 295
         if not settings.DEBUG:
295 296
             logger.critical("Trying to drop all tables but we are not in DEBUG !!!")
296 297
             raise RuntimeError("Trying to drop all tables but we are not in DEBUG !!!")
297
-        meta = sqla.MetaData(bind=self.w_engine, reflect = True)
298
+        meta = sqla.MetaData(bind=self.w_engine)
299
+        meta.reflect()
298 300
         meta.drop_all()
299 301
         pass
300 302
 
@@ -310,7 +312,7 @@ class SqlWrapper(object):
310 312
             if not isinstance(table, dict):
311 313
                 raise TypeError("Excepted a list of dict but got a "+str(type(schema))+" in the list")
312 314
             self.createTable(**table)
313
-
315
+        
314 316
         self.meta_crea.create_all(bind = self.w_engine)
315 317
         logger.info("All tables created")
316 318
         self.meta_crea = None
@@ -334,14 +336,17 @@ class SqlWrapper(object):
334 336
         if not isinstance(name, str):
335 337
             raise TypeError("<class str> excepted for table name, but got "+type(name))
336 338
 
339
+        #if not 'mysql_engine' in kw and self.w_engine.dialect.name == 'mysql':
340
+        #    kw['mysql_engine'] = 'InnoDB'
341
+
337 342
         res = sqla.Table(name, self.meta_crea, **kw)
338 343
         for i,col in enumerate(columns):
339 344
             res.append_column(self.createColumn(**col))
340 345
 
341 346
         if crea_now:
342 347
             self.meta_crea.create_all(self.w_engine)
348
+            logger.debug("Table '"+name+"' created")
343 349
 
344
-        #logger.debug("Table '"+name+"' created")
345 350
         pass
346 351
 
347 352
     def createColumn(self, **kwargs):

+ 40
- 12
EditorialModel/classes.py View File

@@ -5,11 +5,17 @@
5 5
     @see EmClass, EmType, EmFieldGroup, EmField
6 6
 """
7 7
 
8
+import logging as logger
9
+
8 10
 from EditorialModel.components import EmComponent, EmComponentNotExistError
9
-from Database.sqlwrapper import SqlWrapper
10
-from Database.sqlobject import SqlObject
11
+#from Database.sqlwrapper import SqlWrapper
12
+from Database import sqlutils
13
+import sqlalchemy as sql
14
+
11 15
 import EditorialModel
12 16
 
17
+
18
+
13 19
 class EmClass(EmComponent):
14 20
     table = 'em_class'
15 21
 
@@ -21,22 +27,44 @@ class EmClass(EmComponent):
21 27
         @param name str: name of the new class
22 28
         @param class_type EmClasstype: type of the class
23 29
     """
24
-    @staticmethod
25
-    def create(name, class_type):
30
+    @classmethod
31
+    def create(c, name, class_type):
26 32
         try:
27 33
             exists = EmClass(name)
34
+            logger.info("Trying to create an EmClass that allready exists")
28 35
         except EmComponentNotExistError:
29
-            uids = SqlObject('uids')
30
-            res = uids.wexec(uids.table.insert().values(table=EmClass.table))
31
-            uid = res.inserted_primary_key
32
-
33
-            emclass = SqlObject(EmClass.table)
34
-            res = emclass.wexec(emclass.table.insert().values(uid=uid, name=name, classtype=class_type['name']))
35
-            SqlWrapper.wc().execute("CREATE TABLE %s (uid VARCHAR(50))" % name)
36
-            return EmClass(name)
36
+            return c._createDb(name, class_type)
37 37
 
38 38
         return exists
39 39
 
40
+    @classmethod
41
+    def _createDb(c, name, class_type):
42
+        """ Do the db querys for EmClass::create() """
43
+        dbe = c.getDbE()
44
+        #Create a new uid
45
+        uids = sql.Table('uids', sqlutils.meta(dbe))
46
+        conn = dbe.connect()
47
+        req = uids.insert(values={'table':c.table})
48
+        res = conn.execute(req)
49
+        
50
+        uid = res.inserted_primary_key
51
+
52
+        #Create a new entry in the em_class table
53
+        dbclass = sql.Table(c.table, sqlutils.meta(dbe))
54
+        req = dbclass.insert().values(uid = uid, name=name, classtype=class_type['name'])
55
+        res = conn.execute(req)
56
+
57
+        #Create a new table storing LodelObjects of this EmClass
58
+        meta = sql.MetaData()
59
+        emclasstable = sql.Table(name, meta,
60
+            sql.Column('uid', sql.VARCHAR(50), primary_key = True))
61
+        emclasstable.create(conn)
62
+
63
+        conn.close()
64
+
65
+        return EmClass(res.inserted_primary_key)
66
+
67
+
40 68
     def populate(self):
41 69
         row = super(EmClass, self).populate()
42 70
         self.classtype = row.classtype

+ 55
- 20
EditorialModel/components.py View File

@@ -6,21 +6,22 @@
6 6
 """
7 7
 
8 8
 from Lodel.utils.mlstring import MlString
9
-from Database.sqlwrapper import SqlWrapper
10
-from Database.sqlobject import SqlObject
9
+#from Database.sqlwrapper import SqlWrapper
11 10
 import logging
12 11
 import sqlalchemy as sql
12
+from Database import sqlutils
13 13
 
14 14
 logger = logging.getLogger('Lodel2.EditorialModel')
15 15
 
16 16
 class EmComponent(object):
17 17
 
18
+    dbconf = 'default' #the name of the engine configuration
19
+
18 20
     """ instaciate an EmComponent
19 21
         @param id_or_name int|str: name or id of the object
20 22
         @exception TypeError
21 23
     """
22 24
     def __init__(self, id_or_name):
23
-        SqlWrapper.start()
24 25
         if self is EmComponent:
25 26
             raise EnvironmentError('Abstract class')
26 27
         if isinstance(id_or_name, int):
@@ -36,20 +37,7 @@ class EmComponent(object):
36 37
     """ Lookup in the database properties of the object to populate the properties
37 38
     """
38 39
     def populate(self):
39
-        table = SqlObject(self.table)
40
-        select = table.sel
41
-
42
-        if self.id is None:
43
-            select.where(table.col.name == self.name)
44
-        else:
45
-            select.where(table.col.uid == self.id)
46
-
47
-        sqlresult = table.rexec(select)
48
-        records = sqlresult.fetchall()
49
-
50
-        if not records:
51
-            # could have two possible Error message for id and for name
52
-            raise EmComponentNotExistError("Bad id_or_name: could not find the component")
40
+        records = self._populateDb() #Db query
53 41
 
54 42
         for record in records:
55 43
             row = type('row', (object,), {})()
@@ -66,6 +54,32 @@ class EmComponent(object):
66 54
 
67 55
         return row
68 56
 
57
+    @classmethod
58
+    def getDbE(c):
59
+        """ Shortcut that return the sqlAlchemy engine """
60
+        return sqlutils.getEngine(c.dbconf)
61
+
62
+    def _populateDb(self):
63
+        """ Do the query on the db """
64
+        dbe = self.__class__.getDbE()
65
+        component = sql.Table(self.table, sqlutils.meta(dbe))
66
+        req = sql.sql.select([component])
67
+
68
+        if self.id == None:
69
+            req.where(component.c.name == self.name)
70
+        else:
71
+            req.where(component.c.uid == self.id)
72
+        c = dbe.connect()
73
+        res = c.execute(req)
74
+        c.close()
75
+
76
+        res = res.fetchall()
77
+
78
+        if not res or len(res) == 0:
79
+            raise EmComponentNotExistError("No component found with "+('name '+self.name if self.id == None else 'id '+self.id ))
80
+
81
+        return res
82
+
69 83
     """ write the representation of the component in the database
70 84
         @return bool
71 85
     """
@@ -77,14 +91,35 @@ class EmComponent(object):
77 91
         values['string'] = str(self.string)
78 92
         values['help']= str(self.help)
79 93
 
80
-        emclass = SqlObject(self.table)
81
-        update = emclass.table.update(values=values)
82
-        res = emclass.wexec(update)
94
+        self._saveDb(values)
95
+
96
+    def _saveDb(self, values):
97
+        """ Do the query on the db """
98
+        dbe = self.__class__.getDbE()
99
+        component = sql.Table(self.table, sqlutils.meta(dbe))
100
+        req = sql.update(t, values = values).where(component.id == self.id)
101
+
102
+        c = dbe.connect()
103
+        res = c.execute(req)
104
+        c.close()
105
+        if not res:
106
+            raise RuntimeError("Unable to save the component in the database")
107
+        
83 108
 
84 109
     """ delete this component data in the database
85 110
         @return bool
86 111
     """
87 112
     def delete(self):
113
+        #<SQL>
114
+        dbe = self.__class__.getDbE()
115
+        component = sql.Table(self.table, sqlutils.meta(dbe))
116
+        req= component.delete().where(component.id == self.id)
117
+        c = dbe.connect()
118
+        res = c.execute(req)
119
+        c.close
120
+        if not res:
121
+            raise RuntimeError("Unable to delete the component in the database")
122
+        #</SQL>
88 123
         pass
89 124
 
90 125
     """ change the rank of the component

Loading…
Cancel
Save