Coverage for /Users/davegaeddert/Development/dropseed/plain/plain-models/plain/models/backends/base/features.py: 91%

1 from plain.models.db import ProgrammingError

2 from plain.utils.functional import cached_property

3

4

5 class BaseDatabaseFeatures:

6 # An optional tuple indicating the minimum supported database version.

7 minimum_database_version = None

8 gis_enabled = False

9 # Oracle can't group by LOB (large object) data types.

10 allows_group_by_lob = True

11 allows_group_by_selected_pks = False

12 allows_group_by_select_index = True

13 empty_fetchmany_value = []

14 update_can_self_select = True

15

16 # Does the backend distinguish between '' and None?

17 interprets_empty_strings_as_nulls = False

18

19 # Does the backend allow inserting duplicate NULL rows in a nullable

20 # unique field? All core backends implement this correctly, but other

21 # databases such as SQL Server do not.

22 supports_nullable_unique_constraints = True

23

24 # Does the backend support initially deferrable unique constraints?

25 supports_deferrable_unique_constraints = False

26

27 can_use_chunked_reads = True

28 can_return_columns_from_insert = False

29 can_return_rows_from_bulk_insert = False

30 has_bulk_insert = True

31 uses_savepoints = True

32 can_release_savepoints = False

33

34 # If True, don't use integer foreign keys referring to, e.g., positive

35 # integer primary keys.

36 related_fields_match_type = False

37 allow_sliced_subqueries_with_in = True

38 has_select_for_update = False

39 has_select_for_update_nowait = False

40 has_select_for_update_skip_locked = False

41 has_select_for_update_of = False

42 has_select_for_no_key_update = False

43 # Does the database's SELECT FOR UPDATE OF syntax require a column rather

44 # than a table?

45 select_for_update_of_column = False

46

47 # Does the default test database allow multiple connections?

48 # Usually an indication that the test database is in-memory

49 test_db_allows_multiple_connections = True

50

51 # Can an object be saved without an explicit primary key?

52 supports_unspecified_pk = False

53

54 # Can a fixture contain forward references? i.e., are

55 # FK constraints checked at the end of transaction, or

56 # at the end of each save operation?

57 supports_forward_references = True

58

59 # Does the backend truncate names properly when they are too long?

60 truncates_names = False

61

62 # Is there a REAL datatype in addition to floats/doubles?

63 has_real_datatype = False

64 supports_subqueries_in_group_by = True

65

66 # Does the backend ignore unnecessary ORDER BY clauses in subqueries?

67 ignores_unnecessary_order_by_in_subqueries = True

68

69 # Is there a true datatype for uuid?

70 has_native_uuid_field = False

71

72 # Is there a true datatype for timedeltas?

73 has_native_duration_field = False

74

75 # Does the database driver supports same type temporal data subtraction

76 # by returning the type used to store duration field?

77 supports_temporal_subtraction = False

78

79 # Does the __regex lookup support backreferencing and grouping?

80 supports_regex_backreferencing = True

81

82 # Can date/datetime lookups be performed using a string?

83 supports_date_lookup_using_string = True

84

85 # Can datetimes with timezones be used?

86 supports_timezones = True

87

88 # Does the database have a copy of the zoneinfo database?

89 has_zoneinfo_database = True

90

91 # When performing a GROUP BY, is an ORDER BY NULL required

92 # to remove any ordering?

93 requires_explicit_null_ordering_when_grouping = False

94

95 # Does the backend order NULL values as largest or smallest?

96 nulls_order_largest = False

97

98 # Does the backend support NULLS FIRST and NULLS LAST in ORDER BY?

99 supports_order_by_nulls_modifier = True

100

101 # Does the backend orders NULLS FIRST by default?

102 order_by_nulls_first = False

103

104 # The database's limit on the number of query parameters.

105 max_query_params = None

106

107 # Can an object have an autoincrement primary key of 0?

108 allows_auto_pk_0 = True

109

110 # Do we need to NULL a ForeignKey out, or can the constraint check be

111 # deferred

112 can_defer_constraint_checks = False

113

114 # Does the backend support tablespaces? Default to False because it isn't

115 # in the SQL standard.

116 supports_tablespaces = False

117

118 # Does the backend reset sequences between tests?

119 supports_sequence_reset = True

120

121 # Can the backend introspect the default value of a column?

122 can_introspect_default = True

123

124 # Confirm support for introspected foreign keys

125 # Every database can do this reliably, except MySQL,

126 # which can't do it for MyISAM tables

127 can_introspect_foreign_keys = True

128

129 # Map fields which some backends may not be able to differentiate to the

130 # field it's introspected as.

131 introspected_field_types = {

132 "AutoField": "AutoField",

133 "BigAutoField": "BigAutoField",

134 "BigIntegerField": "BigIntegerField",

135 "BinaryField": "BinaryField",

136 "BooleanField": "BooleanField",

137 "CharField": "CharField",

138 "DurationField": "DurationField",

139 "GenericIPAddressField": "GenericIPAddressField",

140 "IntegerField": "IntegerField",

141 "PositiveBigIntegerField": "PositiveBigIntegerField",

142 "PositiveIntegerField": "PositiveIntegerField",

143 "PositiveSmallIntegerField": "PositiveSmallIntegerField",

144 "SmallAutoField": "SmallAutoField",

145 "SmallIntegerField": "SmallIntegerField",

146 "TimeField": "TimeField",

147 }

148

149 # Can the backend introspect the column order (ASC/DESC) for indexes?

150 supports_index_column_ordering = True

151

152 # Does the backend support introspection of materialized views?

153 can_introspect_materialized_views = False

154

155 # Support for the DISTINCT ON clause

156 can_distinct_on_fields = False

157

158 # Does the backend prevent running SQL queries in broken transactions?

159 atomic_transactions = True

160

161 # Can we roll back DDL in a transaction?

162 can_rollback_ddl = False

163

164 schema_editor_uses_clientside_param_binding = False

165

166 # Does it support operations requiring references rename in a transaction?

167 supports_atomic_references_rename = True

168

169 # Can we issue more than one ALTER COLUMN clause in an ALTER TABLE?

170 supports_combined_alters = False

171

172 # Does it support foreign keys?

173 supports_foreign_keys = True

174

175 # Can it create foreign key constraints inline when adding columns?

176 can_create_inline_fk = True

177

178 # Can an index be renamed?

179 can_rename_index = False

180

181 # Does it automatically index foreign keys?

182 indexes_foreign_keys = True

183

184 # Does it support CHECK constraints?

185 supports_column_check_constraints = True

186 supports_table_check_constraints = True

187 # Does the backend support introspection of CHECK constraints?

188 can_introspect_check_constraints = True

189

190 # Does the backend support 'pyformat' style ("... %(name)s ...", {'name': value})

191 # parameter passing? Note this can be provided by the backend even if not

192 # supported by the Python driver

193 supports_paramstyle_pyformat = True

194

195 # Does the backend require literal defaults, rather than parameterized ones?

196 requires_literal_defaults = False

197

198 # Does the backend require a connection reset after each material schema change?

199 connection_persists_old_columns = False

200

201 # What kind of error does the backend throw when accessing closed cursor?

202 closed_cursor_error_class = ProgrammingError

203

204 # Does 'a' LIKE 'A' match?

205 has_case_insensitive_like = False

206

207 # Suffix for backends that don't support "SELECT xxx;" queries.

208 bare_select_suffix = ""

209

210 # If NULL is implied on columns without needing to be explicitly specified

211 implied_column_null = False

212

213 # Does the backend support "select for update" queries with limit (and offset)?

214 supports_select_for_update_with_limit = True

215

216 # Does the backend ignore null expressions in GREATEST and LEAST queries unless

217 # every expression is null?

218 greatest_least_ignores_nulls = False

219

220 # Can the backend clone databases for parallel test execution?

221 # Defaults to False to allow third-party backends to opt-in.

222 can_clone_databases = False

223

224 # Does the backend consider table names with different casing to

225 # be equal?

226 ignores_table_name_case = False

227

228 # Place FOR UPDATE right after FROM clause. Used on MSSQL.

229 for_update_after_from = False

230

231 # Combinatorial flags

232 supports_select_union = True

233 supports_select_intersection = True

234 supports_select_difference = True

235 supports_slicing_ordering_in_compound = False

236 supports_parentheses_in_compound = True

237 requires_compound_order_by_subquery = False

238

239 # Does the database support SQL 2003 FILTER (WHERE ...) in aggregate

240 # expressions?

241 supports_aggregate_filter_clause = False

242

243 # Does the backend support indexing a TextField?

244 supports_index_on_text_field = True

245

246 # Does the backend support window expressions (expression OVER (...))?

247 supports_over_clause = False

248 supports_frame_range_fixed_distance = False

249 only_supports_unbounded_with_preceding_and_following = False

250

251 # Does the backend support CAST with precision?

252 supports_cast_with_precision = True

253

254 # How many second decimals does the database return when casting a value to

255 # a type with time?

256 time_cast_precision = 6

257

258 # SQL to create a procedure for use by the Plain test suite. The

259 # functionality of the procedure isn't important.

260 create_test_procedure_without_params_sql = None

261 create_test_procedure_with_int_param_sql = None

262

263 # SQL to create a table with a composite primary key for use by the Plain

264 # test suite.

265 create_test_table_with_composite_primary_key = None

266

267 # Does the backend support keyword parameters for cursor.callproc()?

268 supports_callproc_kwargs = False

269

270 # What formats does the backend EXPLAIN syntax support?

271 supported_explain_formats = set()

272

273 # Does the backend support the default parameter in lead() and lag()?

274 supports_default_in_lead_lag = True

275

276 # Does the backend support ignoring constraint or uniqueness errors during

277 # INSERT?

278 supports_ignore_conflicts = True

279 # Does the backend support updating rows on constraint or uniqueness errors

280 # during INSERT?

281 supports_update_conflicts = False

282 supports_update_conflicts_with_target = False

283

284 # Does this backend require casting the results of CASE expressions used

285 # in UPDATE statements to ensure the expression has the correct type?

286 requires_casted_case_in_updates = False

287

288 # Does the backend support partial indexes (CREATE INDEX ... WHERE ...)?

289 supports_partial_indexes = True

290 supports_functions_in_partial_indexes = True

291 # Does the backend support covering indexes (CREATE INDEX ... INCLUDE ...)?

292 supports_covering_indexes = False

293 # Does the backend support indexes on expressions?

294 supports_expression_indexes = True

295 # Does the backend treat COLLATE as an indexed expression?

296 collate_as_index_expression = False

297

298 # Does the backend support boolean expressions in SELECT and GROUP BY

299 # clauses?

300 supports_boolean_expr_in_select_clause = True

301 # Does the backend support comparing boolean expressions in WHERE clauses?

302 # Eg: WHERE (price > 0) IS NOT NULL

303 supports_comparing_boolean_expr = True

304

305 # Does the backend support JSONField?

306 supports_json_field = True

307 # Can the backend introspect a JSONField?

308 can_introspect_json_field = True

309 # Does the backend support primitives in JSONField?

310 supports_primitives_in_json_field = True

311 # Is there a true datatype for JSON?

312 has_native_json_field = False

313 # Does the backend use PostgreSQL-style JSON operators like '->'?

314 has_json_operators = False

315 # Does the backend support __contains and __contained_by lookups for

316 # a JSONField?

317 supports_json_field_contains = True

318 # Does value__d__contains={'f': 'g'} (without a list around the dict) match

319 # {'d': [{'f': 'g'}]}?

320 json_key_contains_list_matching_requires_list = False

321 # Does the backend support JSONObject() database function?

322 has_json_object_function = True

323

324 # Does the backend support column collations?

325 supports_collation_on_charfield = True

326 supports_collation_on_textfield = True

327 # Does the backend support non-deterministic collations?

328 supports_non_deterministic_collations = True

329

330 # Does the backend support column and table comments?

331 supports_comments = False

332 # Does the backend support column comments in ADD COLUMN statements?

333 supports_comments_inline = False

334

335 # Does the backend support the logical XOR operator?

336 supports_logical_xor = False

337

338 # Set to (exception, message) if null characters in text are disallowed.

339 prohibits_null_characters_in_text_exception = None

340

341 # Does the backend support unlimited character columns?

342 supports_unlimited_charfield = False

343

344 # Collation names for use by the Plain test suite.

345 test_collations = {

346 "ci": None, # Case-insensitive.

347 "cs": None, # Case-sensitive.

348 "non_default": None, # Non-default.

349 "swedish_ci": None, # Swedish case-insensitive.

350 }

351 # SQL template override for tests.aggregation.tests.NowUTC

352 test_now_utc_template = None

353

354 def __init__(self, connection):

355 self.connection = connection

356

357 @cached_property

358 def supports_explaining_query_execution(self):

359 """Does this backend support explaining query execution?"""

360 return self.connection.ops.explain_prefix is not None

361

362 @cached_property

363 def supports_transactions(self):

364 """Confirm support for transactions."""

365 with self.connection.cursor() as cursor:

366 cursor.execute("CREATE TABLE ROLLBACK_TEST (X INT)")

367 self.connection.set_autocommit(False)

368 cursor.execute("INSERT INTO ROLLBACK_TEST (X) VALUES (8)")

369 self.connection.rollback()

370 self.connection.set_autocommit(True)

371 cursor.execute("SELECT COUNT(X) FROM ROLLBACK_TEST")

372 (count,) = cursor.fetchone()

373 cursor.execute("DROP TABLE ROLLBACK_TEST")

374 return count == 0

375

376 def allows_group_by_selected_pks_on_model(self, model):

377 if not self.allows_group_by_selected_pks:

378 return False

379 return model._meta.managed