south.db.firebird: 157 total statements, 0.0% covered

Generated: Wed 2013-03-13 10:33 CET

Source file: /media/Envs/Envs/filer-gallery/lib/python2.7/site-packages/south/db/firebird.py

Stats: 0 executed, 152 missed, 5 excluded, 165 ignored

  1. # firebird
  2. import datetime
  3. from django.db import connection, models
  4. from django.core.management.color import no_style
  5. from django.db.utils import DatabaseError
  6. from south.db import generic
  7. class DatabaseOperations(generic.DatabaseOperations):
  8. backend_name = 'firebird'
  9. alter_string_set_type = 'ALTER %(column)s TYPE %(type)s'
  10. alter_string_set_default = 'ALTER %(column)s SET DEFAULT %(default)s;'
  11. alter_string_drop_null = ''
  12. add_column_string = 'ALTER TABLE %s ADD %s;'
  13. delete_column_string = 'ALTER TABLE %s DROP %s;'
  14. allows_combined_alters = False
  15. def _fill_constraint_cache(self, db_name, table_name):
  16. self._constraint_cache.setdefault(db_name, {})
  17. self._constraint_cache[db_name][table_name] = {}
  18. rows = self.execute("""
  19. SELECT
  20. rc.RDB$CONSTRAINT_NAME,
  21. rc.RDB$CONSTRAINT_TYPE,
  22. cc.RDB$TRIGGER_NAME
  23. FROM rdb$relation_constraints rc
  24. JOIN rdb$check_constraints cc
  25. ON rc.rdb$constraint_name = cc.rdb$constraint_name
  26. WHERE rc.rdb$constraint_type = 'NOT NULL'
  27. AND rc.rdb$relation_name = '%s'
  28. """ % table_name)
  29. for constraint, kind, column in rows:
  30. self._constraint_cache[db_name][table_name].setdefault(column, set())
  31. self._constraint_cache[db_name][table_name][column].add((kind, constraint))
  32. return
  33. def _alter_column_set_null(self, table_name, column_name, is_null):
  34. sql = """
  35. UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = %(null_flag)s
  36. WHERE RDB$FIELD_NAME = '%(column)s'
  37. AND RDB$RELATION_NAME = '%(table_name)s'
  38. """
  39. null_flag = 'NULL' if is_null else '1'
  40. return sql % {
  41. 'null_flag': null_flag,
  42. 'column': column_name.upper(),
  43. 'table_name': table_name.upper()
  44. }
  45. def _column_has_default(self, params):
  46. sql = """
  47. SELECT a.RDB$DEFAULT_VALUE
  48. FROM RDB$RELATION_FIELDS a
  49. WHERE a.RDB$FIELD_NAME = '%(column)s'
  50. AND a.RDB$RELATION_NAME = '%(table_name)s'
  51. """
  52. value = self.execute(sql % params)
  53. return True if value else False
  54. def _alter_set_defaults(self, field, name, params, sqls):
  55. "Subcommand of alter_column that sets default values (overrideable)"
  56. # Next, set any default
  57. if not field.null and field.has_default():
  58. default = field.get_default()
  59. sqls.append(('ALTER COLUMN %s SET DEFAULT %%s ' % (self.quote_name(name),), [default]))
  60. elif self._column_has_default(params):
  61. sqls.append(('ALTER COLUMN %s DROP DEFAULT' % (self.quote_name(name),), []))
  62. @generic.invalidate_table_constraints
  63. def create_table(self, table_name, fields):
  64. qn = self.quote_name(table_name)
  65. columns = []
  66. autoinc_sql = ''
  67. for field_name, field in fields:
  68. col = self.column_sql(table_name, field_name, field)
  69. if not col:
  70. continue
  71. #col = self.adj_column_sql(col)
  72. columns.append(col)
  73. if isinstance(field, models.AutoField):
  74. field_name = field.db_column or field.column
  75. autoinc_sql = connection.ops.autoinc_sql(table_name, field_name)
  76. sql = 'CREATE TABLE %s (%s);' % (qn, ', '.join([col for col in columns]))
  77. self.execute(sql)
  78. if autoinc_sql:
  79. self.execute(autoinc_sql[0])
  80. self.execute(autoinc_sql[1])
  81. def column_sql(self, table_name, field_name, field, tablespace='', with_name=True, field_prepared=False):
  82. """
  83. Creates the SQL snippet for a column. Used by add_column and add_table.
  84. """
  85. # If the field hasn't already been told its attribute name, do so.
  86. if not field_prepared:
  87. field.set_attributes_from_name(field_name)
  88. # hook for the field to do any resolution prior to it's attributes being queried
  89. if hasattr(field, 'south_init'):
  90. field.south_init()
  91. # Possible hook to fiddle with the fields (e.g. defaults & TEXT on MySQL)
  92. field = self._field_sanity(field)
  93. try:
  94. sql = field.db_type(connection=self._get_connection())
  95. except TypeError:
  96. sql = field.db_type()
  97. if sql:
  98. # Some callers, like the sqlite stuff, just want the extended type.
  99. if with_name:
  100. field_output = [self.quote_name(field.column), sql]
  101. else:
  102. field_output = [sql]
  103. if field.primary_key:
  104. field_output.append('NOT NULL PRIMARY KEY')
  105. elif field.unique:
  106. # Just use UNIQUE (no indexes any more, we have delete_unique)
  107. field_output.append('UNIQUE')
  108. sql = ' '.join(field_output)
  109. sqlparams = ()
  110. # if the field is "NOT NULL" and a default value is provided, create the column with it
  111. # this allows the addition of a NOT NULL field to a table with existing rows
  112. if not getattr(field, '_suppress_default', False):
  113. if field.has_default():
  114. default = field.get_default()
  115. # If the default is actually None, don't add a default term
  116. if default is not None:
  117. # If the default is a callable, then call it!
  118. if callable(default):
  119. default = default()
  120. # Now do some very cheap quoting. TODO: Redesign return values to avoid this.
  121. if isinstance(default, basestring):
  122. default = "'%s'" % default.replace("'", "''")
  123. elif isinstance(default, (datetime.date, datetime.time, datetime.datetime)):
  124. default = "'%s'" % default
  125. elif isinstance(default, bool):
  126. default = int(default)
  127. # Escape any % signs in the output (bug #317)
  128. if isinstance(default, basestring):
  129. default = default.replace("%", "%%")
  130. # Add it in
  131. sql += " DEFAULT %s"
  132. sqlparams = (default)
  133. elif (not field.null and field.blank) or (field.get_default() == ''):
  134. if field.empty_strings_allowed and self._get_connection().features.interprets_empty_strings_as_nulls:
  135. sql += " DEFAULT ''"
  136. # Error here would be nice, but doesn't seem to play fair.
  137. #else:
  138. # raise ValueError("Attempting to add a non null column that isn't character based without an explicit default value.")
  139. # Firebird need set not null after of default value keyword
  140. if not field.primary_key and not field.null:
  141. sql += ' NOT NULL'
  142. if field.rel and self.supports_foreign_keys:
  143. self.add_deferred_sql(
  144. self.foreign_key_sql(
  145. table_name,
  146. field.column,
  147. field.rel.to._meta.db_table,
  148. field.rel.to._meta.get_field(field.rel.field_name).column
  149. )
  150. )
  151. # Things like the contrib.gis module fields have this in 1.1 and below
  152. if hasattr(field, 'post_create_sql'):
  153. for stmt in field.post_create_sql(no_style(), table_name):
  154. self.add_deferred_sql(stmt)
  155. # In 1.2 and above, you have to ask the DatabaseCreation stuff for it.
  156. # This also creates normal indexes in 1.1.
  157. if hasattr(self._get_connection().creation, "sql_indexes_for_field"):
  158. # Make a fake model to pass in, with only db_table
  159. model = self.mock_model("FakeModelForGISCreation", table_name)
  160. for stmt in self._get_connection().creation.sql_indexes_for_field(model, field, no_style()):
  161. self.add_deferred_sql(stmt)
  162. if sql:
  163. return sql % sqlparams
  164. else:
  165. return None
  166. def _drop_constraints(self, table_name, name, field):
  167. if self.has_check_constraints:
  168. check_constraints = self._constraints_affecting_columns(table_name, [name], "CHECK")
  169. for constraint in check_constraints:
  170. self.execute(self.delete_check_sql % {
  171. 'table': self.quote_name(table_name),
  172. 'constraint': self.quote_name(constraint),
  173. })
  174. # Drop or add UNIQUE constraint
  175. unique_constraint = list(self._constraints_affecting_columns(table_name, [name], "UNIQUE"))
  176. if field.unique and not unique_constraint:
  177. self.create_unique(table_name, [name])
  178. elif not field.unique and unique_constraint:
  179. self.delete_unique(table_name, [name])
  180. # Drop all foreign key constraints
  181. try:
  182. self.delete_foreign_key(table_name, name)
  183. except ValueError:
  184. # There weren't any
  185. pass
  186. @generic.invalidate_table_constraints
  187. def alter_column(self, table_name, name, field, explicit_name=True, ignore_constraints=False):
  188. """
  189. Alters the given column name so it will match the given field.
  190. Note that conversion between the two by the database must be possible.
  191. Will not automatically add _id by default; to have this behavour, pass
  192. explicit_name=False.
  193. @param table_name: The name of the table to add the column to
  194. @param name: The name of the column to alter
  195. @param field: The new field definition to use
  196. """
  197. if self.dry_run:
  198. return
  199. # hook for the field to do any resolution prior to it's attributes being queried
  200. if hasattr(field, 'south_init'):
  201. field.south_init()
  202. # Add _id or whatever if we need to
  203. field.set_attributes_from_name(name)
  204. if not explicit_name:
  205. name = field.column
  206. else:
  207. field.column = name
  208. if not ignore_constraints:
  209. # Drop all check constraints. Note that constraints will be added back
  210. # with self.alter_string_set_type and self.alter_string_drop_null.
  211. self._drop_constraints(table_name, name, field)
  212. # First, change the type
  213. params = {
  214. "column": self.quote_name(name),
  215. "type": self._db_type_for_alter_column(field),
  216. "table_name": table_name
  217. }
  218. # SQLs is a list of (SQL, values) pairs.
  219. sqls = []
  220. sqls_extra = []
  221. # Only alter the column if it has a type (Geometry ones sometimes don't)
  222. if params["type"] is not None:
  223. sqls.append((self.alter_string_set_type % params, []))
  224. # Add any field- and backend- specific modifications
  225. self._alter_add_column_mods(field, name, params, sqls)
  226. # Next, nullity: modified, firebird doesn't support DROP NOT NULL
  227. sqls_extra.append(self._alter_column_set_null(table_name, name, field.null))
  228. # Next, set any default
  229. self._alter_set_defaults(field, name, params, sqls)
  230. # Finally, actually change the column
  231. if self.allows_combined_alters:
  232. sqls, values = zip(*sqls)
  233. self.execute(
  234. "ALTER TABLE %s %s;" % (self.quote_name(table_name), ", ".join(sqls)),
  235. generic.flatten(values),
  236. )
  237. else:
  238. # Databases like e.g. MySQL don't like more than one alter at once.
  239. for sql, values in sqls:
  240. try:
  241. self.execute("ALTER TABLE %s %s;" % (self.quote_name(table_name), sql), values)
  242. except DatabaseError, e:
  243. print e
  244. # Execute extra sql, which don't need ALTER TABLE statement
  245. for sql in sqls_extra:
  246. self.execute(sql)
  247. if not ignore_constraints:
  248. # Add back FK constraints if needed
  249. if field.rel and self.supports_foreign_keys:
  250. self.execute(
  251. self.foreign_key_sql(
  252. table_name,
  253. field.column,
  254. field.rel.to._meta.db_table,
  255. field.rel.to._meta.get_field(field.rel.field_name).column
  256. )
  257. )
  258. @generic.copy_column_constraints
  259. @generic.delete_column_constraints
  260. def rename_column(self, table_name, old, new):
  261. if old == new:
  262. # Short-circuit out
  263. return []
  264. self.execute('ALTER TABLE %s ALTER %s TO %s;' % (
  265. self.quote_name(table_name),
  266. self.quote_name(old),
  267. self.quote_name(new),
  268. ))