Browse Source

Implemented DropColumn for sqlite

Yann Weber 9 years ago
parent
commit
16a962fb3f
4 changed files with 51 additions and 7 deletions
  1. 36
    1
      Database/sqlalter.py
  2. 12
    3
      Database/sqlutils.py
  3. 2
    1
      EditorialModel/fields.py
  4. 1
    2
      EditorialModel/test/test_field.py

+ 36
- 1
Database/sqlalter.py View File

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 
2
 
3
 import os
3
 import os
4
+import time
4
 
5
 
5
 import sqlalchemy as sqla
6
 import sqlalchemy as sqla
6
 from sqlalchemy.ext.compiler import compiles
7
 from sqlalchemy.ext.compiler import compiles
55
     return 'ALTER TABLE %s DROP COLUMN %s'%(tname, colname)
56
     return 'ALTER TABLE %s DROP COLUMN %s'%(tname, colname)
56
 
57
 
57
 @compiles(DropColumn)
58
 @compiles(DropColumn)
59
+##
60
+# @warning Returns more than one query @ref Database.sqlutils.ddl_execute
58
 def visit_drop_column(element, ddlcompiler, **kw):
61
 def visit_drop_column(element, ddlcompiler, **kw):
59
-    raise NotImplementedError('Drop column not yet implemented for '+str(ddlcompiler.dialect.name))
62
+    prep = ddlcompiler.sql_compiler.preparer
63
+    tname = prep.format_table(element.table)
64
+
65
+    #Temporary table
66
+    tmpname = str(element.table)+'_copydropcol'
67
+    tmpTable = sqla.Table(tmpname, sqla.MetaData())
68
+    tmptname = prep.format_table(tmpTable)
69
+
70
+    query =  'ALTER TABLE %s RENAME TO %s; '%(tname, tmptname)
71
+
72
+    colname = prep.format_column(element.col)
73
+
74
+    meta = sqla.MetaData()
75
+    newtable = sqla.Table(element.table, meta)
76
+    clist = element.table.columns
77
+
78
+    cols = []
79
+    for col in clist:
80
+        if col.name != element.col.name:
81
+            newtable.append_column(col.copy())
82
+            cols.append(prep.format_column(col))
83
+    cols=', '.join(cols)
84
+
85
+    query += str(sqla.schema.CreateTable(newtable).compile(dialect = ddlcompiler.dialect))+';'
86
+
87
+    query += 'INSERT INTO %s ( %s ) SELECT %s FROM %s;' % (newtable, cols, cols, tmptname)
88
+
89
+    query += 'DROP TABLE %s'% (tmpname)
90
+
91
+    return query
92
+
93
+
94
+    #raise NotImplementedError('Drop column not yet implemented for '+str(ddlcompiler.dialect.name))
60
 
95
 
61
 class AlterColumn(sqla.schema.DDLElement):
96
 class AlterColumn(sqla.schema.DDLElement):
62
     """ Defines the DDL for changing the type of a column """
97
     """ Defines the DDL for changing the type of a column """

+ 12
- 3
Database/sqlutils.py View File

91
     engine = cls.getDbE()
91
     engine = cls.getDbE()
92
     return sqla.Table(cls.table, meta(engine))
92
     return sqla.Table(cls.table, meta(engine))
93
 
93
 
94
+## This function is intended to execute ddl defined in sqlalter
95
+# @warning There is a dirty workaround here, DDL should returns only one query, but DropColumn for sqlite has to return 4 queries (rename, create, insert, drop). There is a split on the compiled SQL to extract and execute one query at a time
96
+# @param ddl DDLElement: Can be an Database.sqlalter.DropColumn Database.sqlalter.AddColumn or Database.sqlalter.AlterColumn
97
+# @param db_engine: A database engine
98
+# @return True if success, else False
94
 def ddl_execute(ddl, db_engine):
99
 def ddl_execute(ddl, db_engine):
95
     conn = db_engine.connect()
100
     conn = db_engine.connect()
96
     req = str(ddl.compile(dialect=db_engine.dialect))
101
     req = str(ddl.compile(dialect=db_engine.dialect))
97
-    logger.debug("Executing custom raw SQL query : '"+req+"'")
98
-    ret = conn.execute(req)
102
+    queries = req.split(';')
103
+    for query in queries:
104
+        logger.debug("Executing custom raw SQL query : '"+query+"'")
105
+        ret = conn.execute(query)
106
+        if not bool(ret):
107
+            return False
99
     conn.close()
108
     conn.close()
100
-    return bool(ret)
109
+    return True
101
 
110
 

+ 2
- 1
EditorialModel/fields.py View File

85
     # @return bool : True if deleted False if deletion aborded
85
     # @return bool : True if deleted False if deletion aborded
86
     # @todo Check if unconditionnal deletion is correct
86
     # @todo Check if unconditionnal deletion is correct
87
     def delete(self):
87
     def delete(self):
88
-        class_table = self.get_class_table()
88
+        dbe = self.__class__.getDbE()
89
+        class_table = sql.Table(self.get_class_table(), sqlutils.meta(dbe))
89
         field_col = sql.Column(self.name)
90
         field_col = sql.Column(self.name)
90
         ddl = DropColumn(class_table, field_col)
91
         ddl = DropColumn(class_table, field_col)
91
         sqlutils.ddl_execute(ddl, self.__class__.getDbE())
92
         sqlutils.ddl_execute(ddl, self.__class__.getDbE())

+ 1
- 2
EditorialModel/test/test_field.py View File

129
         self.assertIn(field_column.name, field_table_columns)
129
         self.assertIn(field_column.name, field_table_columns)
130
         pass
130
         pass
131
     
131
     
132
-    @unittest.skip("Delete not implemente for sqlite...")
133
     def test_deletion(self):
132
     def test_deletion(self):
134
         field_names = ['field1', 'field2']
133
         field_names = ['field1', 'field2']
135
         for name in field_names:
134
         for name in field_names:
143
             for deleted_name in field_names[:i+1]:
142
             for deleted_name in field_names[:i+1]:
144
                 self.assertNotIn(deleted_name, cols, "Column is  not deleted")
143
                 self.assertNotIn(deleted_name, cols, "Column is  not deleted")
145
             for not_deleted_name in field_names[i+1:]:
144
             for not_deleted_name in field_names[i+1:]:
146
-                self.assertIn(deleted_name, cols, "A bad column was deleted")
145
+                self.assertIn(not_deleted_name, cols, "A bad column was deleted")
147
                 
146
                 
148
             with self.assertRaises(EmComponentNotExistError, msg="This field should be deleted"):
147
             with self.assertRaises(EmComponentNotExistError, msg="This field should be deleted"):
149
                 EmField(name)
148
                 EmField(name)

Loading…
Cancel
Save