summaryrefslogtreecommitdiff
path: root/django/db/backends/oracle/features.py
blob: 05dc552a986d4695b6ef481803c60ba8ab7bd764 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
from django.db import DatabaseError, InterfaceError
from django.db.backends.base.features import BaseDatabaseFeatures
from django.utils.functional import cached_property


class DatabaseFeatures(BaseDatabaseFeatures):
    minimum_database_version = (19,)
    # Oracle crashes with "ORA-00932: inconsistent datatypes: expected - got
    # BLOB" when grouping by LOBs (#24096).
    allows_group_by_lob = False
    allows_group_by_select_index = False
    interprets_empty_strings_as_nulls = True
    has_select_for_update = True
    has_select_for_update_nowait = True
    has_select_for_update_skip_locked = True
    has_select_for_update_of = True
    select_for_update_of_column = True
    can_return_columns_from_insert = True
    supports_subqueries_in_group_by = False
    ignores_unnecessary_order_by_in_subqueries = False
    supports_transactions = True
    supports_timezones = False
    has_native_duration_field = True
    can_defer_constraint_checks = True
    supports_partially_nullable_unique_constraints = False
    supports_deferrable_unique_constraints = True
    truncates_names = True
    supports_comments = True
    supports_tablespaces = True
    supports_sequence_reset = False
    can_introspect_materialized_views = True
    atomic_transactions = False
    nulls_order_largest = True
    requires_literal_defaults = True
    closed_cursor_error_class = InterfaceError
    bare_select_suffix = " FROM DUAL"
    # Select for update with limit can be achieved on Oracle, but not with the
    # current backend.
    supports_select_for_update_with_limit = False
    supports_temporal_subtraction = True
    # Oracle doesn't ignore quoted identifiers case but the current backend
    # does by uppercasing all identifiers.
    ignores_table_name_case = True
    supports_index_on_text_field = False
    create_test_procedure_without_params_sql = """
        CREATE PROCEDURE "TEST_PROCEDURE" AS
            V_I INTEGER;
        BEGIN
            V_I := 1;
        END;
    """
    create_test_procedure_with_int_param_sql = """
        CREATE PROCEDURE "TEST_PROCEDURE" (P_I INTEGER) AS
            V_I INTEGER;
        BEGIN
            V_I := P_I;
        END;
    """
    create_test_table_with_composite_primary_key = """
        CREATE TABLE test_table_composite_pk (
            column_1 NUMBER(11) NOT NULL,
            column_2 NUMBER(11) NOT NULL,
            PRIMARY KEY (column_1, column_2)
        )
    """
    supports_callproc_kwargs = True
    supports_over_clause = True
    supports_frame_range_fixed_distance = True
    supports_ignore_conflicts = False
    max_query_params = 2**16 - 1
    supports_partial_indexes = False
    can_rename_index = True
    supports_slicing_ordering_in_compound = True
    requires_compound_order_by_subquery = True
    allows_multiple_constraints_on_same_fields = False
    supports_boolean_expr_in_select_clause = False
    supports_comparing_boolean_expr = False
    supports_primitives_in_json_field = False
    supports_json_field_contains = False
    supports_collation_on_textfield = False
    test_collations = {
        "ci": "BINARY_CI",
        "cs": "BINARY",
        "non_default": "SWEDISH_CI",
        "swedish_ci": "SWEDISH_CI",
    }
    test_now_utc_template = "CURRENT_TIMESTAMP AT TIME ZONE 'UTC'"

    django_test_skips = {
        "Oracle doesn't support SHA224.": {
            "db_functions.text.test_sha224.SHA224Tests.test_basic",
            "db_functions.text.test_sha224.SHA224Tests.test_transform",
        },
        "Oracle doesn't correctly calculate ISO 8601 week numbering before "
        "1583 (the Gregorian calendar was introduced in 1582).": {
            "db_functions.datetime.test_extract_trunc.DateFunctionTests."
            "test_trunc_week_before_1000",
            "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
            "test_trunc_week_before_1000",
        },
        "Oracle extracts seconds including fractional seconds (#33517).": {
            "db_functions.datetime.test_extract_trunc.DateFunctionTests."
            "test_extract_second_func_no_fractional",
            "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests."
            "test_extract_second_func_no_fractional",
        },
        "Oracle doesn't support bitwise XOR.": {
            "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor",
            "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_null",
            "expressions.tests.ExpressionOperatorTests."
            "test_lefthand_bitwise_xor_right_null",
        },
        "Oracle requires ORDER BY in row_number, ANSI:SQL doesn't.": {
            "expressions_window.tests.WindowFunctionTests.test_row_number_no_ordering",
        },
        "Raises ORA-00600: internal error code.": {
            "model_fields.test_jsonfield.TestQuerying.test_usage_in_subquery",
        },
        "Oracle doesn't support changing collations on indexed columns (#33671).": {
            "migrations.test_operations.OperationTests."
            "test_alter_field_pk_fk_db_collation",
        },
        "Oracle doesn't support comparing NCLOB to NUMBER.": {
            "generic_relations_regress.tests.GenericRelationTests.test_textlink_filter",
        },
    }
    django_test_expected_failures = {
        # A bug in Django/cx_Oracle with respect to string handling (#23843).
        "annotations.tests.NonAggregateAnnotationTestCase.test_custom_functions",
        "annotations.tests.NonAggregateAnnotationTestCase."
        "test_custom_functions_can_ref_other_functions",
    }

    @cached_property
    def introspected_field_types(self):
        return {
            **super().introspected_field_types,
            "GenericIPAddressField": "CharField",
            "PositiveBigIntegerField": "BigIntegerField",
            "PositiveIntegerField": "IntegerField",
            "PositiveSmallIntegerField": "IntegerField",
            "SmallIntegerField": "IntegerField",
            "TimeField": "DateTimeField",
        }

    @cached_property
    def supports_collation_on_charfield(self):
        with self.connection.cursor() as cursor:
            try:
                cursor.execute("SELECT CAST('a' AS VARCHAR2(4001)) FROM dual")
            except DatabaseError as e:
                if e.args[0].code == 910:
                    return False
                raise
            return True