Skip to content

Commit

Permalink
some fixes for different tests
Browse files Browse the repository at this point in the history
  • Loading branch information
daimor committed Jan 16, 2025
1 parent 591986c commit 72dcf5b
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 57 deletions.
44 changes: 43 additions & 1 deletion django_iris/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
from django.db.models.functions.datetime import Now
from django.db.models.expressions import Exists, Func, Value, Col, OrderBy
from django.db.models.functions.text import Chr, ConcatPair, StrIndex
from django.db.models.functions import Cast
from django.db.models.fields import TextField, CharField
from django.db.models.lookups import BuiltinLookup
from django.db.models.fields.json import (
KeyTransform,
KeyTransformExact,
compile_json_path,
)

from django_iris.compiler import SQLCompiler

Expand Down Expand Up @@ -65,7 +72,8 @@ def convert_streams(expressions):

@as_intersystems(Exists)
def exists_as_intersystems(self, compiler, connection, template=None, **extra_context):
template = "(SELECT COUNT(*) FROM (%(subquery)s))"
# template = "(SELECT COUNT(*) FROM (%(subquery)s))"
template = "EXISTS %(subquery)s"
return self.as_sql(compiler, connection, template, **extra_context)


Expand Down Expand Up @@ -151,3 +159,37 @@ def orderby_as_intersystems(self, compiler, connection, **extra_context):
# IRIS does not support order NULL
copy.nulls_first = copy.nulls_last = False
return copy.as_sql(compiler, connection, **extra_context)


@as_intersystems(KeyTransformExact)
def json_KeyTransformExact_as_intersystems(self, compiler, connection):
return self.as_sql(compiler, connection)


@as_intersystems(KeyTransform)
def json_KeyTransform_as_intersystems(self, compiler, connection):
# breakpoint()
# json_path = compile_json_path(key_transforms)
return f"{self.field.name}__{self.key_name}", []


@as_intersystems(BuiltinLookup)
def BuiltinLookup_as_intersystems(self, compiler, connection):
sql, params = self.as_sql(compiler, connection)
if compiler.in_get_order_by:
return "CASE WHEN %s THEN 1 ELSE 0 END" % (sql,), params
# if not compiler.in_get_select and not compiler.in_get_order_by:
return sql, params


@as_intersystems(Cast)
def cast_as_intersystems(self, compiler, connection, **extra_context):
if hasattr(self.source_expressions[0], "lookup_name"):
if self.source_expressions[0].lookup_name in ["gt", "gte", "lt", "lte"]:
return self.as_sql(
compiler,
connection,
template="CASE WHEN %(expressions)s THEN 1 ELSE 0 END",
**extra_context,
)
return self.as_sql(compiler, connection, **extra_context)
104 changes: 93 additions & 11 deletions django_iris/compiler.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,81 @@
import itertools

from django.core.exceptions import EmptyResultSet, FullResultSet
from django.db.models.expressions import Col, Value
from django.db.models.expressions import RawSQL
from django.db.models.sql.where import AND
from django.db.models.sql import compiler
from django.db.models.fields.json import KeyTransform
from django.db.models.expressions import DatabaseDefault


class Flag:
value = False

def __init__(self, value):
self.value = value

def __enter__(self):
self.value = True
return True

def __exit__(self, *args):
self.value = False

def __bool__(self):
return self.value


class SQLCompiler(compiler.SQLCompiler):
in_get_select = Flag(False)
in_get_order_by = Flag(False)
# def get_from_clause(self):
# result, params = super().get_from_clause()
# jsoncolumns = {}
# for column in self.query.select + tuple(
# [column for column in (col.lhs for col in self.query.where.children)]
# ):
# if isinstance(column, KeyTransform):
# if column.field.name not in jsoncolumns:
# jsoncolumns[column.field.name] = {}
# jsoncolumns[column.field.name][
# column.key_name
# ] = f"{column.field.name}__{column.key_name}"
# []
# for field in jsoncolumns:
# self.query.where.add(RawSQL("%s is not null" % (field,), []), AND)
# cols = ", ".join(
# [
# f"{jsoncolumns[field][col_name]} VARCHAR PATH '$.{col_name}'"
# for col_name in jsoncolumns[field]
# ]
# )
# result.append(
# f"""
# , JSON_TABLE("{column.field.name}", '$' COLUMNS(
# {cols}
# ))
# """
# )

# if "model_fields_nullablejsonmodel" in self.query.alias_map:
# breakpoint()
# return result, params

def get_select(self, with_col_aliases=False):
with self.in_get_select:
return super().get_select(with_col_aliases)

def get_order_by(self):
with self.in_get_order_by:
return super().get_order_by()

def as_sql(self, with_limits=True, with_col_aliases=False):
with_limit_offset = (with_limits or self.query.is_sliced) and (
self.query.high_mark is not None or self.query.low_mark > 0
)
if self.query.select_for_update or not with_limit_offset:
return super().as_sql(with_limits, with_col_aliases)
query, params = super().as_sql(with_limits, with_col_aliases)
return query, params
try:
extra_select, order_by, group_by = self.pre_sql_setup()

Expand Down Expand Up @@ -79,7 +145,10 @@ def as_sql(self, with_limits=True, with_col_aliases=False):
order_by_result = "ORDER BY %s" % first_col

if offset:
out_cols.append("ROW_NUMBER() %s AS row_number" % ("OVER (%s)" % order_by_result if order_by_result else ""))
out_cols.append(
"ROW_NUMBER() %s AS row_number"
% ("OVER (%s)" % order_by_result if order_by_result else "")
)

result += [", ".join(out_cols), "FROM", *from_]
params.extend(f_params)
Expand Down Expand Up @@ -154,19 +223,32 @@ def as_sql(self, with_limits=True, with_col_aliases=False):
), tuple(sub_params + params)

if offset:
query = "SELECT * FROM (%s) WHERE row_number between %d AND %d ORDER BY row_number" % (
query,
offset,
limit,
query = (
"SELECT * FROM (%s) WHERE row_number between %d AND %d ORDER BY row_number"
% (
query,
offset,
limit,
)
)
return query, tuple(params)
except:
return super().as_sql(with_limits, with_col_aliases)
except Exception:
query, params = super().as_sql(with_limits, with_col_aliases)
return query, params


class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):

def as_sql(self):

if self.query.fields:
fields = self.query.fields
self.query.fields = [
field
for field in fields
if not isinstance(self.pre_save_val(field, self.query.objs[0]), DatabaseDefault)
]

if self.query.fields:
return super().as_sql()

Expand Down Expand Up @@ -195,7 +277,7 @@ def as_sql(self):
if self.connection._disable_constraint_checking:
sql = "UPDATE %%NOCHECK" + sql[6:]
return sql, params


class SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler):
pass
32 changes: 29 additions & 3 deletions django_iris/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
only_supports_unbounded_with_preceding_and_following = False

# Does the backend support JSONField?
supports_json_field = False
supports_json_field = True
# Can the backend introspect a JSONField?
can_introspect_json_field = False
# Does the backend support primitives in JSONField?
Expand All @@ -106,13 +106,15 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_collation_on_charfield = True
supports_collation_on_textfield = False

supports_boolean_expr_in_select_clause = False

# Collation names for use by the Django test suite.
test_collations = {
# "ci": None, # Case-insensitive.
"cs": "EXACT", # Case-sensitive.
# "non_default": None, # Non-default.
# "swedish_ci": None, # Swedish case-insensitive.
"virtual": None
"virtual": None,
}

@cached_property
Expand Down Expand Up @@ -162,12 +164,23 @@ def django_test_skips(self):
# "datetimes.tests.DateTimesTests.test_datetimes_ambiguous_and_invalid_times",
# },
"IRIS does not have check contsraints": {
"model_fields.test_jsonfield.JSONFieldTests.test_db_check_constraints",
"constraints.tests.CheckConstraintTests.test_validate",
"constraints.tests.CheckConstraintTests.test_validate_boolean_expressions",
"constraints.tests.UniqueConstraintTests.test_validate_expression_condition",
},
"Does not support expressions in default": {
"field_defaults.tests.DefaultTests.test_full_clean",
"basic.tests.ModelInstanceCreationTests.test_save_primary_with_db_default",
},
"Regex not supported": {
"lookup.tests.LookupTests.test_regex",
"lookup.tests.LookupTests.test_regex_backreferencing",
"lookup.tests.LookupTests.test_regex_non_ascii",
"lookup.tests.LookupTests.test_regex_non_string",
"lookup.tests.LookupTests.test_regex_null",
},
}

)
return skips

Expand All @@ -186,6 +199,19 @@ def django_test_skips(self):
"schema.tests.SchemaTests.test_alter_text_field_to_time_field",
"schema.tests.SchemaTests.test_alter_text_field_to_datetime_field",
"schema.tests.SchemaTests.test_alter_text_field_to_date_field",
#
"lookup.tests.LookupQueryingTests.test_filter_exists_lhs",
"lookup.tests.LookupQueryingTests.test_filter_lookup_lhs",
"lookup.tests.LookupQueryingTests.test_filter_subquery_lhs",
"lookup.tests.LookupQueryingTests.test_filter_wrapped_lookup_lhs",
"lookup.tests.LookupTests.test_lookup_rhs",

"lookup.tests.LookupTests.test_regex",
"lookup.tests.LookupTests.test_regex_backreferencing",
"lookup.tests.LookupTests.test_regex_non_ascii",
"lookup.tests.LookupTests.test_regex_non_string",
"lookup.tests.LookupTests.test_regex_null",

}

# django_test_skips["IRIS Bugs"] = django_test_expected_failures
Expand Down
Loading

0 comments on commit 72dcf5b

Please sign in to comment.