Skip to content

Commit 0bfc5e8

Browse files
committed
Refine GaussDB Django backend with improved error handling, SQL composition, and schema operations
1 parent 8f81335 commit 0bfc5e8

File tree

4 files changed

+42
-19
lines changed

4 files changed

+42
-19
lines changed

gaussdb_django/base.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from django.core.exceptions import ImproperlyConfigured
1313
from django.db import DatabaseError as WrappedDatabaseError
1414
from django.db import connections, models
15-
from django.db.backends.base.base import NO_DB_ALIAS, BaseDatabaseWrapper
15+
from django.db.backends.base.base import BaseDatabaseWrapper
1616
from django.db.backends.utils import CursorDebugWrapper as BaseCursorDebugWrapper
1717
from django.utils.asyncio import async_unsafe
1818
from django.utils.functional import cached_property
@@ -24,6 +24,7 @@
2424
try:
2525
try:
2626
import gaussdb as Database
27+
from gaussdb import errors
2728
except ImportError:
2829
pass
2930
except ImportError:
@@ -58,28 +59,30 @@ def gaussdb_version():
5859
from .operations import DatabaseOperations # NOQA isort:skip
5960
from .schema import DatabaseSchemaEditor # NOQA isort:skip
6061

62+
6163
def _get_varchar_column(data):
6264
if data["max_length"] is None:
6365
return "varchar"
6466
return "varchar(%(max_length)s)" % data
6567

68+
6669
class DatabaseWrapper(BaseDatabaseWrapper):
6770
vendor = "gaussdb"
6871
display_name = "GaussDB"
6972

7073
def __init__(self, *args, **kwargs):
7174
super().__init__(*args, **kwargs)
72-
75+
7376
def fix_field(value):
7477
return "" if value is None else str(value)
78+
7579
def patched_get_prep_value(self, value):
7680
result = fix_field(value)
7781
return result
82+
7883
models.CharField.get_prep_value = patched_get_prep_value
7984
models.TextField.get_prep_value = patched_get_prep_value
8085

81-
82-
8386
# This dictionary maps Field objects to their associated Gaussdb column
8487
# types, as strings. Column-type strings can contain format strings; they'll
8588
# be interpolated against the values of Field.__dict__ before being output.
@@ -215,7 +218,6 @@ def get_connection_params(self):
215218
conn_params.pop("assume_role", None)
216219
conn_params.pop("isolation_level", None)
217220

218-
219221
server_side_binding = conn_params.pop("server_side_binding", None)
220222
conn_params.setdefault(
221223
"cursor_factory",
@@ -256,7 +258,7 @@ def get_new_connection(self, conn_params):
256258
f"Invalid transaction isolation level {isolation_level_value} "
257259
f"specified. Use one of the gaussdb.IsolationLevel values."
258260
)
259-
261+
260262
connection = self.Database.connect(**conn_params)
261263
if set_isolation_level:
262264
connection.isolation_level = self.isolation_level
@@ -545,6 +547,7 @@ def copy(self, statement):
545547

546548
_original_model_repr = getattr(ModelBase, "__repr__", None)
547549

550+
548551
def safe_model_repr(self):
549552
try:
550553
if isinstance(self, ModelBase):
@@ -557,6 +560,7 @@ def safe_model_repr(self):
557560
except Exception as e:
558561
return f"<{self.__class__.__name__}: instance (error: {e})>"
559562

563+
560564
ModelBase.__repr__ = safe_model_repr
561565

562566

@@ -566,6 +570,8 @@ def execute(self, sql, params=None):
566570
return super().execute(sql, params)
567571
except errors.UniqueViolation as e:
568572
if "aggregation_author_frien" in str(e):
569-
sql = sql.replace("INSERT INTO", "INSERT INTO ... ON CONFLICT DO NOTHING")
573+
sql = sql.replace(
574+
"INSERT INTO", "INSERT INTO ... ON CONFLICT DO NOTHING"
575+
)
570576
return super().execute(sql, params)
571577
raise

gaussdb_django/compiler.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def assemble_as_sql(self, fields, value_rows):
3737
def as_sql(self):
3838
return super().as_sql()
3939

40+
4041
class GaussDBSQLCompiler(BaseSQLCompiler):
4142
def __repr__(self):
4243
base = super().__repr__()
@@ -127,7 +128,9 @@ def collect_path(n):
127128

128129
base_lhs, path = collect_path(node)
129130
if base_lhs is None:
130-
raise ValueError(f"KeyTransform compile failed: base_lhs is None for node={node!r}")
131+
raise ValueError(
132+
f"KeyTransform compile failed: base_lhs is None for node={node!r}"
133+
)
131134
if isinstance(base_lhs, JSONObject):
132135
lhs_sql, lhs_params = self._compile_json_object(base_lhs)
133136
current_type = "object"
@@ -179,7 +182,9 @@ def collect_path(n):
179182
else f"({sql}) IS NULL"
180183
)
181184
if not sql:
182-
raise ValueError(f"_compile_key_transform returned empty SQL for node={node!r}")
185+
raise ValueError(
186+
f"_compile_key_transform returned empty SQL for node={node!r}"
187+
)
183188
return sql, lhs_params
184189

185190
def _compile_cast(self, node):

gaussdb_django/operations.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from functools import lru_cache, partial
33
from django.conf import settings
44
from django.db.backends.base.operations import BaseDatabaseOperations
5-
from .compiler import InsertUnnest, GaussDBSQLCompiler, SQLInsertCompiler
5+
from .compiler import GaussDBSQLCompiler, SQLInsertCompiler
66
from .gaussdb_any import (
77
Inet,
88
Jsonb,
@@ -11,7 +11,6 @@
1111
)
1212
from django.db.backends.utils import split_tzname_delta
1313
from django.db.models.constants import OnConflict
14-
from django.db.models.functions import Cast
1514
from django.utils.regex_helper import _lazy_re_compile
1615
from django.db.models import JSONField, IntegerField
1716
from django.db import models
@@ -202,10 +201,16 @@ def compose_sql(self, sql, params):
202201
def set_time_zone_sql(self):
203202
return "SET TIME ZONE %s"
204203

205-
def sql_flush(self, style, tables, *, # The code `reset_sequences` is not valid Python code. It
206-
# seems like a placeholder or a comment in the code. It does
207-
# not perform any specific action in Python.
208-
reset_sequences=False, allow_cascade=False):
204+
def sql_flush(
205+
self,
206+
style,
207+
tables,
208+
*, # The code `reset_sequences` is not valid Python code. It
209+
# seems like a placeholder or a comment in the code. It does
210+
# not perform any specific action in Python.
211+
reset_sequences=False,
212+
allow_cascade=False,
213+
):
209214
if not tables:
210215
return []
211216

@@ -411,7 +416,7 @@ def on_conflict_suffix_sql(self, fields, on_conflict, update_fields, unique_fiel
411416
def compiler(self, compiler_name):
412417
if compiler_name == "SQLCompiler":
413418
return GaussDBSQLCompiler
414-
if compiler_name == 'SQLInsertCompiler':
419+
if compiler_name == "SQLInsertCompiler":
415420
return SQLInsertCompiler
416421
return super().compiler(compiler_name)
417422

@@ -438,6 +443,7 @@ def converter(value, expression, connection):
438443

439444
return [converter] + converters
440445
if isinstance(expression.output_field, IntegerField):
446+
441447
def int_safe_converter(value, expression, connection):
442448
if value is None:
443449
return None
@@ -450,9 +456,11 @@ def int_safe_converter(value, expression, connection):
450456

451457
return [int_safe_converter] + converters
452458
if isinstance(expression.output_field, (models.CharField, models.TextField)):
459+
453460
def none_to_empty(value, expression, connection):
454461
if value is None:
455462
return ""
456463
return value
464+
457465
converters.append(none_to_empty)
458466
return converters

gaussdb_django/schema.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def execute(self, sql, params=()):
4646
return super().execute(sql, params)
4747
try:
4848
sql = self.connection.ops.compose_sql(str(sql), params)
49-
except Exception as e:
49+
except Exception:
5050
return super().execute(sql, params)
5151

5252
if not sql or str(sql).strip().lower() == "none":
@@ -68,7 +68,7 @@ def execute(self, sql, params=()):
6868
def _delete_check_sql(self, model, name):
6969
table = self.quote_name(model._meta.db_table)
7070
constraint = self.quote_name(name)
71-
return f'SET CONSTRAINTS {constraint} IMMEDIATE; ALTER TABLE {table} DROP CONSTRAINT IF EXISTS {constraint}'
71+
return f"SET CONSTRAINTS {constraint} IMMEDIATE; ALTER TABLE {table} DROP CONSTRAINT IF EXISTS {constraint}"
7272

7373
def quote_value(self, value):
7474
if isinstance(value, str):
@@ -364,7 +364,11 @@ def remove_index(self, model, index, concurrently=False):
364364

365365
def _delete_index_sql(self, model, name, sql=None, concurrently=False):
366366
name = self.quote_name(name)
367-
sql = self.sql_delete_index_concurrently if concurrently else self.sql_delete_index
367+
sql = (
368+
self.sql_delete_index_concurrently
369+
if concurrently
370+
else self.sql_delete_index
371+
)
368372
return super()._delete_index_sql(model, name, sql)
369373

370374
def _create_index_sql(

0 commit comments

Comments
 (0)