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

149 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-10-16 22:04 -0500

1from plain.models.db import ProgrammingError 

2from plain.utils.functional import cached_property 

3 

4 

5class 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