Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

database/_table_utils.py: allow to rename columns

I need this piece of code because soon I'll need to be able
to s/can_share/can_publish/ in bittorrent and speedtest table
of the database, when I'll upgrade the database subsystem to
version 2.0 of the privacy policy.

This is not straightforward because sqlite3 does not allow to
do that via a simple 'ALTER TABLE'.  The strategy to do that
is described on stackowerflow.com at this URI:

    http://stackoverflow.com/questions/805363

Discussed with Roberto.

Tested using the attached regression test.
  • Loading branch information...
commit d5742a64d1edd5121919bd7d37a912816ed492d7 1 parent b85334b
@bassosimone bassosimone authored
Showing with 103 additions and 1 deletion.
  1. +40 −1 neubot/database/_table_utils.py
  2. +63 −0 regress/database/_table_utils.py
View
41 neubot/database/_table_utils.py
@@ -1,7 +1,7 @@
# neubot/database/_table_utils.py
#
-# Copyright (c) 2011 Simone Basso <bassosimone@gmail.com>,
+# Copyright (c) 2011-2012 Simone Basso <bassosimone@gmail.com>,
# NEXA Center for Internet & Society at Politecnico di Torino
#
# This file is part of Neubot <http://www.neubot.org/>.
@@ -189,3 +189,42 @@ def make_select(table, template, **kwargs):
vector.append(";")
query = "".join(vector)
return query
+
+def rename_column_query(table1, template1, table2, template2):
+
+ ''' Returns the query that copies from table1, described by
+ template1, to table2, described by template2 '''
+
+ query = ["INSERT INTO %s(" % __check(table2)]
+ for name in template2:
+ query.append(__check(name))
+ query.append(",")
+ query[-1] = ") SELECT "
+ for name in template1:
+ query.append(__check(name))
+ query.append(",")
+ query[-1] = " FROM %s;" % __check(table1)
+
+ query = "".join(query)
+ return query
+
+def rename_column(connection, table, template, mapping):
+
+ ''' General procedure to rename one or more columns in a table,
+ described by template, according to the specified mapping '''
+
+ # See http://stackoverflow.com/questions/805363
+
+ table = __check(table)
+ otable = "old_%s" % table
+
+ ntemplate = {}
+ for key, value in template.items():
+ if key in mapping:
+ key = mapping[key]
+ ntemplate[key] = value
+
+ connection.execute("ALTER TABLE %s RENAME TO %s" % (table, otable))
+ connection.execute(make_create_table(table, ntemplate))
+ connection.execute(rename_column_query(otable, template, table, ntemplate))
+ connection.execute("DROP TABLE %s;" % otable)
View
63 regress/database/_table_utils.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2012 Simone Basso <bassosimone@gmail.com>,
+# NEXA Center for Internet & Society at Politecnico di Torino
+#
+# This file is part of Neubot <http://www.neubot.org/>.
+#
+# Neubot is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Neubot is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Neubot. If not, see <http://www.gnu.org/licenses/>.
+#
+
+''' Regression tests for neubot/database/_table_utils.py '''
+
+import unittest
+import sqlite3
+import sys
+
+if __name__ == '__main__':
+ sys.path.insert(0, '.')
+
+from neubot.database import _table_utils
+
+class TestRenameColumn(unittest.TestCase):
+
+ ''' Regression test for rename_column() feature '''
+
+ template = {
+ 'namex': 'Simone',
+ 'sur_name': 'Basso',
+ 'age': 29,
+ }
+
+ mapping = {
+ 'namex': 'name',
+ 'sur_name': 'surname'
+ }
+
+ def test_success(self):
+ ''' Test for the successful case '''
+ connection = sqlite3.connect(':memory:')
+ connection.execute(_table_utils.make_create_table(
+ 'Person', self.template))
+ _table_utils.rename_column(connection, 'Person', self.template,
+ self.mapping)
+ cursor = connection.cursor()
+ cursor.execute('SELECT sql FROM sqlite_master WHERE name="Person";')
+ query = cursor.next()[0]
+ self.assertEqual(query, 'CREATE TABLE Person (id INTEGER PRIMARY '
+ 'KEY, age INTEGER, surname TEXT, name TEXT)')
+
+if __name__ == '__main__':
+ unittest.main()
Please sign in to comment.
Something went wrong with that request. Please try again.