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

60 statements  

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

1import operator 

2 

3from plain.models import transaction 

4from plain.models.backends.base.features import BaseDatabaseFeatures 

5from plain.models.db import OperationalError 

6from plain.utils.functional import cached_property 

7 

8from .base import Database 

9 

10 

11class DatabaseFeatures(BaseDatabaseFeatures): 

12 minimum_database_version = (3, 21) 

13 test_db_allows_multiple_connections = False 

14 supports_unspecified_pk = True 

15 supports_timezones = False 

16 max_query_params = 999 

17 supports_transactions = True 

18 atomic_transactions = False 

19 can_rollback_ddl = True 

20 can_create_inline_fk = False 

21 requires_literal_defaults = True 

22 can_clone_databases = True 

23 supports_temporal_subtraction = True 

24 ignores_table_name_case = True 

25 supports_cast_with_precision = False 

26 time_cast_precision = 3 

27 can_release_savepoints = True 

28 has_case_insensitive_like = True 

29 # Is "ALTER TABLE ... RENAME COLUMN" supported? 

30 can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0) 

31 # Is "ALTER TABLE ... DROP COLUMN" supported? 

32 can_alter_table_drop_column = Database.sqlite_version_info >= (3, 35, 5) 

33 supports_parentheses_in_compound = False 

34 can_defer_constraint_checks = True 

35 supports_over_clause = Database.sqlite_version_info >= (3, 25, 0) 

36 supports_frame_range_fixed_distance = Database.sqlite_version_info >= (3, 28, 0) 

37 supports_aggregate_filter_clause = Database.sqlite_version_info >= (3, 30, 1) 

38 supports_order_by_nulls_modifier = Database.sqlite_version_info >= (3, 30, 0) 

39 # NULLS LAST/FIRST emulation on < 3.30 requires subquery wrapping. 

40 requires_compound_order_by_subquery = Database.sqlite_version_info < (3, 30) 

41 order_by_nulls_first = True 

42 supports_json_field_contains = False 

43 supports_update_conflicts = Database.sqlite_version_info >= (3, 24, 0) 

44 supports_update_conflicts_with_target = supports_update_conflicts 

45 test_collations = { 

46 "ci": "nocase", 

47 "cs": "binary", 

48 "non_default": "nocase", 

49 } 

50 create_test_table_with_composite_primary_key = """ 

51 CREATE TABLE test_table_composite_pk ( 

52 column_1 INTEGER NOT NULL, 

53 column_2 INTEGER NOT NULL, 

54 PRIMARY KEY(column_1, column_2) 

55 ) 

56 """ 

57 

58 @cached_property 

59 def supports_atomic_references_rename(self): 

60 return Database.sqlite_version_info >= (3, 26, 0) 

61 

62 @cached_property 

63 def introspected_field_types(self): 

64 return { 

65 **super().introspected_field_types, 

66 "BigAutoField": "AutoField", 

67 "DurationField": "BigIntegerField", 

68 "GenericIPAddressField": "CharField", 

69 "SmallAutoField": "AutoField", 

70 } 

71 

72 @cached_property 

73 def supports_json_field(self): 

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

75 try: 

76 with transaction.atomic(self.connection.alias): 

77 cursor.execute('SELECT JSON(\'{"a": "b"}\')') 

78 except OperationalError: 

79 return False 

80 return True 

81 

82 can_introspect_json_field = property(operator.attrgetter("supports_json_field")) 

83 has_json_object_function = property(operator.attrgetter("supports_json_field")) 

84 

85 @cached_property 

86 def can_return_columns_from_insert(self): 

87 return Database.sqlite_version_info >= (3, 35) 

88 

89 can_return_rows_from_bulk_insert = property( 

90 operator.attrgetter("can_return_columns_from_insert") 

91 )