Нема описа
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import time
  4. import sqlalchemy as sqla
  5. from sqlalchemy.ext.compiler import compiles
  6. ## @file sqlalter.py
  7. # This file defines all DDL (data definition langage) for the ALTER TABLE instructions
  8. #
  9. # It uses the SqlAlchemy compilation and quoting methos to generate SQL
  10. class AddColumn(sqla.schema.DDLElement):
  11. """ Defines the ddl for adding a column to a table """
  12. def __init__(self, table, column):
  13. """ Instanciate the DDL
  14. @param table sqlalchemy.Table: A sqlalchemy table object
  15. @param column sqlalchemy.Column: A sqlalchemy column object
  16. """
  17. self.col = column
  18. self.table = table
  19. @compiles(AddColumn, 'mysql')
  20. @compiles(AddColumn, 'postgresql')
  21. @compiles(AddColumn, 'sqlite')
  22. def visit_add_column(element, ddlcompiler, **kw):
  23. """ Compiles the AddColumn DDL for mysql, postgresql and sqlite"""
  24. prep = ddlcompiler.sql_compiler.preparer
  25. tname = prep.format_table(element.table)
  26. colname = prep.format_column(element.col)
  27. return 'ALTER TABLE %s ADD COLUMN %s %s' % (tname, colname, element.col.type)
  28. @compiles(AddColumn)
  29. def visit_add_column(element, ddlcompiler, **kw):
  30. raise NotImplementedError('Add column not yet implemented for ' + str(ddlcompiler.dialect.name))
  31. class DropColumn(sqla.schema.DDLElement):
  32. """ Defines the DDL for droping a column from a table """
  33. def __init__(self, table, column):
  34. """ Instanciate the DDL
  35. @param table sqlalchemy.Table: A sqlalchemy table object
  36. @param column sqlalchemy.Column: A sqlalchemy column object representing the column to drop
  37. """
  38. self.col = column
  39. self.table = table
  40. @compiles(DropColumn, 'mysql')
  41. @compiles(DropColumn, 'postgresql')
  42. def visit_drop_column(element, ddlcompiler, **kw):
  43. """ Compiles the DropColumn DDL for mysql & postgresql """
  44. prep = ddlcompiler.sql_compiler.preparer
  45. tname = prep.format_table(element.table)
  46. colname = prep.format_column(element.col)
  47. return 'ALTER TABLE %s DROP COLUMN %s' % (tname, colname)
  48. @compiles(DropColumn)
  49. ##
  50. # @warning Returns more than one query @ref Database.sqlutils.ddl_execute
  51. def visit_drop_column(element, ddlcompiler, **kw):
  52. prep = ddlcompiler.sql_compiler.preparer
  53. tname = prep.format_table(element.table)
  54. #Temporary table
  55. tmpname = str(element.table) + '_copydropcol'
  56. tmpTable = sqla.Table(tmpname, sqla.MetaData())
  57. tmptname = prep.format_table(tmpTable)
  58. query = 'ALTER TABLE %s RENAME TO %s; ' % (tname, tmptname)
  59. colname = prep.format_column(element.col)
  60. meta = sqla.MetaData()
  61. newtable = sqla.Table(element.table, meta)
  62. clist = element.table.columns
  63. cols = []
  64. for col in clist:
  65. if col.name != element.col.name:
  66. newtable.append_column(col.copy())
  67. cols.append(prep.format_column(col))
  68. cols = ', '.join(cols)
  69. query += str(sqla.schema.CreateTable(newtable).compile(dialect=ddlcompiler.dialect)) + ';'
  70. query += 'INSERT INTO %s ( %s ) SELECT %s FROM %s;' % (newtable, cols, cols, tmptname)
  71. query += 'DROP TABLE %s' % (tmpname)
  72. return query
  73. #raise NotImplementedError('Drop column not yet implemented for '+str(ddlcompiler.dialect.name))
  74. class AlterColumn(sqla.schema.DDLElement):
  75. """ Defines the DDL for changing the type of a column """
  76. def __init__(self, table, column):
  77. """ Instanciate the DDL
  78. @param table sqlalchemy.Table: A sqlalchemy Table object
  79. @param column sqlalchemy.Column: A sqlalchemy Column object representing the new column
  80. """
  81. self.col = column
  82. self.table = table
  83. @compiles(AlterColumn, 'mysql')
  84. def visit_alter_column(element, ddlcompiler, **kw):
  85. """ Compiles the AlterColumn DDL for mysql """
  86. prep = ddlcompiler.sql_compiler.preparer
  87. tname = prep.format_table(element.table)
  88. colname = prep.format_column(element.col)
  89. return 'ALTER TABLE %s ALTER COLUMN %s %s' % (tname, colname, element.col.type)
  90. @compiles(AlterColumn, 'postgresql')
  91. def visit_alter_column(element, ddlcompiler, **kw):
  92. """ Compiles the AlterColumn DDL for postgresql """
  93. prep = ddlcompiler.sql_compiler.preparer
  94. tname = prep.format_table(element.table)
  95. colname = prep.format_column(element.col)
  96. return 'ALTER TABLE %s ALTER COLUMN %s TYPE %s' % (tname, colname, element.col.type)
  97. @compiles(AlterColumn)
  98. def visit_alter_column(element, ddlcompiler, **kw):
  99. raise NotImplementedError('Alter column not yet implemented for ' + str(ddlcompiler.dialect.name))