add jsonb to string cast support for postgres (fix #6577, #2602)

GITHUB_PR_NUMBER: 7818
GITHUB_PR_URL: https://github.com/hasura/graphql-engine/pull/7818

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2898
Co-authored-by: Teo Stocco <9053709+zifeo@users.noreply.github.com>
Co-authored-by: Rikin Kachhia <54616969+rikinsk@users.noreply.github.com>
Co-authored-by: Rakesh Emmadi <12475069+rakeshkky@users.noreply.github.com>
GitOrigin-RevId: 1100f3ce44ea07867a2d7de5b6bb059510f100e1
This commit is contained in:
hasura-bot 2022-03-09 23:32:04 -08:00
parent b9ee669ee1
commit 4ec9229f15
8 changed files with 76 additions and 7 deletions

View File

@ -7,6 +7,7 @@
### Bug fixes and improvements
- server: add jsonb to string cast support - postgres
- server: improve performance of fetching postgres catalog metadata for tables and functions
- server: Queries present in query collections, such as allow-list, and rest-endpoints are now validated (against the schema)
- server: Redesigns internal implementation of webhook transforms.

View File

@ -814,7 +814,10 @@ CastExp
.. note::
Currently, only casting between ``geometry`` and ``geography`` types is allowed.
Currently, only the following type casts are supported:
- between PostGIS ``geometry`` and ``geography`` types
- from Postgres ``jsonb`` type to ``string`` type.
.. _OrderByExp:

View File

@ -558,7 +558,7 @@ Fetch a list of articles whose titles contain the word “amet”:
"city": "Bengaluru",
"state": "Karnataka",
"pincode": 560095,
"phone": "9090909090",
"phone": "9090909090"
}
}
]

View File

@ -644,7 +644,7 @@ Fetch all authors living within a particular pincode (present in ``address`` JSO
"city": "Bengaluru",
"state": "Karnataka",
"pincode": 560095,
"phone": "9090909090",
"phone": "9090909090"
}
}
]
@ -2026,13 +2026,55 @@ Cast a field to a different type before filtering (_cast)
---------------------------------------------------------
The ``_cast`` operator can be used to cast a field to a different type, which allows type-specific
operators to be used on fields that otherwise would not support them. Currently, only casting
between PostGIS ``geometry`` and ``geography`` types is supported.
operators to be used on fields that otherwise would not support them.
Currently, only the following type casts are supported:
- between PostGIS ``geometry`` and ``geography`` types
- from Postgres ``jsonb`` type to ``string`` type.
Casting using ``_cast`` corresponds directly to
`SQL type casts <https://www.postgresql.org/docs/current/sql-expressions.html#SQL-SYNTAX-TYPE-CASTS>`__.
**Example: cast ``geometry`` to ``geography``**
**Example: cast jsonb to string**
Columns of type ``jsonb`` can be cast to ``String`` to use :ref:`text operators <text_operators>` on a
``jsonb`` field:
.. graphiql::
:view_only:
:query:
query get_authors_in_bengaluru {
authors(
where: {
address: {_cast: {String: {_ilike: "%bengaluru%"}}}
}
) {
id
name
address
}
}
:response:
{
"data": {
"authors": [
{
"id": 1,
"name": "Ash",
"address": {
"street_address": "161, 19th Main Road, Koramangala 6th Block",
"city": "Bengaluru",
"state": "Karnataka",
"pincode": 560095,
"phone": "9090909090"
}
}
]
}
}
**Example: cast geometry to geography**
Filtering using ``_st_d_within`` over large distances can be inaccurate for location data stored in
``geometry`` columns. For accurate queries, cast the field to ``geography`` before comparing:
@ -2073,7 +2115,7 @@ Filtering using ``_st_d_within`` over large distances can be inaccurate for loca
"distance": 1000000
}
**Example: cast ``geography`` to ``geometry``**
**Example: cast geography to geometry**
Columns of type ``geography`` are more accurate, but they dont support as many operations as
``geometry``. Cast to ``geometry`` to use those operations in a filter:

View File

@ -208,6 +208,7 @@ parseBoolExpOperations rhsParser rootTable fim columnRef value = do
checkValidCast targetType = case (colTy, targetType) of
(ColumnScalar PGGeometry, PGGeography) -> return ()
(ColumnScalar PGGeography, PGGeometry) -> return ()
(ColumnScalar PGJSONB, PGText) -> return ()
_ ->
throw400 UnexpectedPayload $
"cannot cast column of type " <> colTy <<> " to type " <>> targetType

View File

@ -599,6 +599,7 @@ comparisonExps = P.memoize 'comparisonExps \columnType -> do
let maybeScalars = case sourceType of
ColumnScalar PGGeography -> Just (PGGeography, PGGeometry)
ColumnScalar PGGeometry -> Just (PGGeometry, PGGeography)
ColumnScalar PGJSONB -> Just (PGJSONB, PGText)
_ -> Nothing
forM maybeScalars $ \(sourceScalar, targetScalar) -> do

View File

@ -0,0 +1,18 @@
description: Test casting from jsonb to string
url: /v1/graphql
status: 200
query:
query: |
query {
article(where: {tags: {_cast: {String: {_like: "%bestseller%"}}}}){
id
tags
}
}
response:
data:
article:
- id: 2
tags:
- bestseller
- latest

View File

@ -934,6 +934,9 @@ class TestGraphQLQueryBoolExpSearchMSSQL:
@usefixtures('per_class_tests_db_state')
class TestGraphQLQueryBoolExpJsonB:
def test_query_cast_geometry_to_geography(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/query_cast_jsonb_to_string.yaml', transport)
def test_jsonb_contains_article_latest(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_article_author_jsonb_contains_latest.yaml', transport)