features.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. from django.db import DatabaseError, InterfaceError
  2. from django.db.backends.base.features import BaseDatabaseFeatures
  3. from django.utils.functional import cached_property
  4. class DatabaseFeatures(BaseDatabaseFeatures):
  5. interprets_empty_strings_as_nulls = True
  6. has_select_for_update = True
  7. has_select_for_update_nowait = True
  8. has_select_for_update_skip_locked = True
  9. has_select_for_update_of = True
  10. select_for_update_of_column = True
  11. can_return_columns_from_insert = True
  12. supports_subqueries_in_group_by = False
  13. supports_transactions = True
  14. supports_timezones = False
  15. has_native_duration_field = True
  16. can_defer_constraint_checks = True
  17. supports_partially_nullable_unique_constraints = False
  18. supports_deferrable_unique_constraints = True
  19. truncates_names = True
  20. supports_tablespaces = True
  21. supports_sequence_reset = False
  22. can_introspect_materialized_views = True
  23. atomic_transactions = False
  24. supports_combined_alters = False
  25. nulls_order_largest = True
  26. requires_literal_defaults = True
  27. closed_cursor_error_class = InterfaceError
  28. bare_select_suffix = " FROM DUAL"
  29. # select for update with limit can be achieved on Oracle, but not with the current backend.
  30. supports_select_for_update_with_limit = False
  31. supports_temporal_subtraction = True
  32. # Oracle doesn't ignore quoted identifiers case but the current backend
  33. # does by uppercasing all identifiers.
  34. ignores_table_name_case = True
  35. supports_index_on_text_field = False
  36. has_case_insensitive_like = False
  37. create_test_procedure_without_params_sql = """
  38. CREATE PROCEDURE "TEST_PROCEDURE" AS
  39. V_I INTEGER;
  40. BEGIN
  41. V_I := 1;
  42. END;
  43. """
  44. create_test_procedure_with_int_param_sql = """
  45. CREATE PROCEDURE "TEST_PROCEDURE" (P_I INTEGER) AS
  46. V_I INTEGER;
  47. BEGIN
  48. V_I := P_I;
  49. END;
  50. """
  51. supports_callproc_kwargs = True
  52. supports_over_clause = True
  53. supports_frame_range_fixed_distance = True
  54. supports_ignore_conflicts = False
  55. max_query_params = 2**16 - 1
  56. supports_partial_indexes = False
  57. supports_slicing_ordering_in_compound = True
  58. allows_multiple_constraints_on_same_fields = False
  59. supports_boolean_expr_in_select_clause = False
  60. supports_primitives_in_json_field = False
  61. supports_json_field_contains = False
  62. supports_collation_on_textfield = False
  63. test_collations = {
  64. 'ci': 'BINARY_CI',
  65. 'cs': 'BINARY',
  66. 'non_default': 'SWEDISH_CI',
  67. 'swedish_ci': 'SWEDISH_CI',
  68. }
  69. @cached_property
  70. def introspected_field_types(self):
  71. return {
  72. **super().introspected_field_types,
  73. 'GenericIPAddressField': 'CharField',
  74. 'PositiveBigIntegerField': 'BigIntegerField',
  75. 'PositiveIntegerField': 'IntegerField',
  76. 'PositiveSmallIntegerField': 'IntegerField',
  77. 'SmallIntegerField': 'IntegerField',
  78. 'TimeField': 'DateTimeField',
  79. }
  80. @cached_property
  81. def supports_collation_on_charfield(self):
  82. with self.connection.cursor() as cursor:
  83. try:
  84. cursor.execute("SELECT CAST('a' AS VARCHAR2(4001)) FROM dual")
  85. except DatabaseError as e:
  86. if e.args[0].code == 910:
  87. return False
  88. raise
  89. return True