Skip to content

Commit

Permalink
Fix Postgres issues
Browse files Browse the repository at this point in the history
  • Loading branch information
henadzit committed Nov 18, 2024
1 parent f926567 commit ca5e37d
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 13 deletions.
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions tests/test_queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ async def test_force_index_available_in_more_query(self):
sql_ExistsQuery = IntFields.filter(pk=1).force_index("index_name").exists().sql()
self.assertEqual(
sql_ExistsQuery,
"SELECT %s FROM `intfields` FORCE INDEX (`index_name`) WHERE `id`=%s LIMIT %s",
"SELECT 1 FROM `intfields` FORCE INDEX (`index_name`) WHERE `id`=%s LIMIT %s",
)

@test.requireCapability(support_index_hint=True)
Expand Down Expand Up @@ -662,7 +662,7 @@ async def test_use_index_available_in_more_query(self):
sql_ExistsQuery = IntFields.filter(pk=1).use_index("index_name").exists().sql()
self.assertEqual(
sql_ExistsQuery,
"SELECT %s FROM `intfields` USE INDEX (`index_name`) WHERE `id`=%s LIMIT %s",
"SELECT 1 FROM `intfields` USE INDEX (`index_name`) WHERE `id`=%s LIMIT %s",
)

@test.requireCapability(support_for_update=True)
Expand Down
18 changes: 12 additions & 6 deletions tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ def test_annotate(self):
expected = "SELECT `id`,CONCAT(`id`,%s) `id_plus_one` FROM `charpkmodel`"
elif self.dialect == "postgres":
if self.is_psycopg:
expected = 'SELECT "id",CONCAT("id",%s) "id_plus_one" FROM "charpkmodel"'
expected = (
'SELECT "id",CONCAT("id"::text,%s::text) "id_plus_one" FROM "charpkmodel"'
)
else:
expected = 'SELECT "id",CONCAT("id",$1) "id_plus_one" FROM "charpkmodel"'
expected = (
'SELECT "id",CONCAT("id"::text,$1::text) "id_plus_one" FROM "charpkmodel"'
)
else:
expected = 'SELECT "id",CONCAT("id",?) "id_plus_one" FROM "charpkmodel"'
self.assertEqual(sql, expected)
Expand Down Expand Up @@ -93,14 +97,16 @@ def test_values_list(self):
def test_exists(self):
sql = IntFields.filter(intnum=1).exists().sql()
if self.dialect == "mysql":
expected = "SELECT %s FROM `intfields` WHERE `intnum`=%s LIMIT %s"
expected = "SELECT 1 FROM `intfields` WHERE `intnum`=%s LIMIT %s"
elif self.dialect == "postgres":
if self.is_psycopg:
expected = 'SELECT %s FROM "intfields" WHERE "intnum"=%s LIMIT %s'
expected = 'SELECT 1 FROM "intfields" WHERE "intnum"=%s LIMIT %s'
else:
expected = 'SELECT $1 FROM "intfields" WHERE "intnum"=$2 LIMIT $3'
expected = 'SELECT 1 FROM "intfields" WHERE "intnum"=$1 LIMIT $2'
elif self.dialect == "mssql":
expected = 'SELECT 1 FROM "intfields" WHERE "intnum"=? ORDER BY (SELECT 0) OFFSET 0 ROWS FETCH NEXT ? ROWS ONLY'
else:
expected = 'SELECT ? FROM "intfields" WHERE "intnum"=? LIMIT ?'
expected = 'SELECT 1 FROM "intfields" WHERE "intnum"=? LIMIT ?'
self.assertEqual(sql, expected)

def test_count(self):
Expand Down
12 changes: 10 additions & 2 deletions tortoise/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,22 @@ def is_in(field: Term, value: Any) -> Criterion:
if value:
return field.isin(value)
# SQL has no False, so we return 1=0
return BasicCriterion(Equality.eq, ValueWrapper("1"), ValueWrapper("0"))
return BasicCriterion(
Equality.eq,
ValueWrapper(1, allow_parametrize=False),
ValueWrapper(0, allow_parametrize=False),
)


def not_in(field: Term, value: Any) -> Criterion:
if value:
return field.notin(value) | field.isnull()
# SQL has no True, so we return 1=1
return BasicCriterion(Equality.eq, ValueWrapper("1"), ValueWrapper("1"))
return BasicCriterion(
Equality.eq,
ValueWrapper(1, allow_parametrize=False),
ValueWrapper(1, allow_parametrize=False),
)


def between_and(field: Term, value: Tuple[Any, Any]) -> Criterion:
Expand Down
14 changes: 13 additions & 1 deletion tortoise/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ class Upper(Function):
database_func = functions.Upper


class _Concat(functions.Concat): # type: ignore
@staticmethod
def get_arg_sql(arg, **kwargs):
sql = arg.get_sql(with_alias=False, **kwargs) if hasattr(arg, "get_sql") else str(arg)
# explicitly convert to text for postgres to avoid errors like
# "could not determine data type of parameter $1"
dialect = kwargs.get("dialect", None)
if dialect and dialect.value == "postgresql":
return f"{sql}::text"
return sql


class Concat(Function):
"""
Concate field or constant text.
Expand All @@ -65,7 +77,7 @@ class Concat(Function):
:samp:`Concat("{FIELD_NAME}", {ANOTHER_FIELD_NAMES or CONSTANT_TEXT}, *args)`
"""

database_func = functions.Concat
database_func = _Concat


##############################################################################
Expand Down
2 changes: 1 addition & 1 deletion tortoise/queryset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ def _make_query(self, **pypika_kwargs) -> Tuple[str, List[Any]]:
self.query = copy(self.model._meta.basequery)
self.resolve_filters()
self.query._limit = self.query._wrapper_cls(1)
self.query._select_other(ValueWrapper(1))
self.query._select_other(ValueWrapper(1, allow_parametrize=False))

if self._force_indexes:
self.query._force_indexes = []
Expand Down

0 comments on commit ca5e37d

Please sign in to comment.