mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
server: fix referenced session vars for live queries when UDF has specified session argument
GitOrigin-RevId: 23efdf4d3b3902b5ce7ec14061faa53b18258e86
This commit is contained in:
parent
2a24947e57
commit
63594e1828
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
### Bug fixes and improvements
|
### Bug fixes and improvements
|
||||||
|
|
||||||
|
- server: fix subscriptions with session argument in user-defined function (fix #6657)
|
||||||
- server: MSSQL: Support ORDER BY for text/ntext types.
|
- server: MSSQL: Support ORDER BY for text/ntext types.
|
||||||
- server: MSSQL: Support _lt, _eq, etc. for text/ntext types.
|
- server: MSSQL: Support _lt, _eq, etc. for text/ntext types.
|
||||||
- server: MSSQL: Fix offset when there's no order by.
|
- server: MSSQL: Fix offset when there's no order by.
|
||||||
|
@ -151,8 +151,8 @@ mkMultiplexedQuery rootFields = MultiplexedQuery . Q.fromBuilder . toSQL $ S.mkS
|
|||||||
-- about various parameters of the query along the way.
|
-- about various parameters of the query along the way.
|
||||||
resolveMultiplexedValue
|
resolveMultiplexedValue
|
||||||
:: (MonadState (QueryParametersInfo ('Postgres pgKind)) m)
|
:: (MonadState (QueryParametersInfo ('Postgres pgKind)) m)
|
||||||
=> UnpreparedValue ('Postgres pgKind) -> m S.SQLExp
|
=> SessionVariables -> UnpreparedValue ('Postgres pgKind) -> m S.SQLExp
|
||||||
resolveMultiplexedValue = \case
|
resolveMultiplexedValue allSessionVars = \case
|
||||||
UVParameter varM colVal -> do
|
UVParameter varM colVal -> do
|
||||||
varJsonPath <- case fmap PS.getName varM of
|
varJsonPath <- case fmap PS.getName varM of
|
||||||
Just varName -> do
|
Just varName -> do
|
||||||
@ -167,7 +167,10 @@ resolveMultiplexedValue = \case
|
|||||||
modifying qpiReferencedSessionVariables (Set.insert sessVar)
|
modifying qpiReferencedSessionVariables (Set.insert sessVar)
|
||||||
pure $ fromResVars ty ["session", sessionVariableToText sessVar]
|
pure $ fromResVars ty ["session", sessionVariableToText sessVar]
|
||||||
UVLiteral sqlExp -> pure sqlExp
|
UVLiteral sqlExp -> pure sqlExp
|
||||||
UVSession -> pure $ fromResVars (CollectableTypeScalar PGJSON) ["session"]
|
UVSession -> do
|
||||||
|
-- if the entire session is referenced, then add all session vars in referenced vars
|
||||||
|
modifying qpiReferencedSessionVariables (const $ getSessionVariablesSet allSessionVars)
|
||||||
|
pure $ fromResVars (CollectableTypeScalar PGJSON) ["session"]
|
||||||
where
|
where
|
||||||
fromResVars pgType jPath = addTypeAnnotation pgType $ S.SEOpApp (S.SQLOp "#>>")
|
fromResVars pgType jPath = addTypeAnnotation pgType $ S.SEOpApp (S.SQLOp "#>>")
|
||||||
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier (Identifier "_subs") Nothing) (Identifier "result_vars")
|
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier (Identifier "_subs") Nothing) (Identifier "result_vars")
|
||||||
|
@ -272,7 +272,7 @@ pgDBSubscriptionPlan
|
|||||||
-> m (LiveQueryPlan ('Postgres pgKind) (MultiplexedQuery ('Postgres pgKind)))
|
-> m (LiveQueryPlan ('Postgres pgKind) (MultiplexedQuery ('Postgres pgKind)))
|
||||||
pgDBSubscriptionPlan userInfo _sourceName sourceConfig unpreparedAST = do
|
pgDBSubscriptionPlan userInfo _sourceName sourceConfig unpreparedAST = do
|
||||||
(preparedAST, PGL.QueryParametersInfo{..}) <- flip runStateT mempty $
|
(preparedAST, PGL.QueryParametersInfo{..}) <- flip runStateT mempty $
|
||||||
for unpreparedAST $ traverseQueryDB PGL.resolveMultiplexedValue
|
for unpreparedAST $ traverseQueryDB (PGL.resolveMultiplexedValue $ _uiSession userInfo)
|
||||||
let multiplexedQuery = PGL.mkMultiplexedQuery preparedAST
|
let multiplexedQuery = PGL.mkMultiplexedQuery preparedAST
|
||||||
roleName = _uiRole userInfo
|
roleName = _uiRole userInfo
|
||||||
parameterizedPlan = ParameterizedLiveQueryPlan roleName multiplexedQuery
|
parameterizedPlan = ParameterizedLiveQueryPlan roleName multiplexedQuery
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
type: bulk
|
||||||
|
args:
|
||||||
|
|
||||||
|
- type: run_sql
|
||||||
|
args:
|
||||||
|
sql: |
|
||||||
|
CREATE TABLE profile (
|
||||||
|
id TEXT,
|
||||||
|
name TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO profile (id, name) VALUES ('10', 'Miles'), ('42', 'Charlie');
|
||||||
|
|
||||||
|
CREATE FUNCTION me(hasura_session json)
|
||||||
|
RETURNS SETOF profile AS $$
|
||||||
|
SELECT * FROM profile
|
||||||
|
WHERE id = hasura_session ->> 'x-hasura-user-id'
|
||||||
|
$$ LANGUAGE sql STABLE;
|
||||||
|
|
||||||
|
- type: track_table
|
||||||
|
args:
|
||||||
|
schema: public
|
||||||
|
name: profile
|
||||||
|
|
||||||
|
- type: create_select_permission
|
||||||
|
args:
|
||||||
|
table: profile
|
||||||
|
role: user
|
||||||
|
permission:
|
||||||
|
columns: [id, name]
|
||||||
|
filter: {}
|
||||||
|
|
||||||
|
- type: track_function
|
||||||
|
version: 2
|
||||||
|
args:
|
||||||
|
function:
|
||||||
|
name: me
|
||||||
|
schema: public
|
||||||
|
configuration:
|
||||||
|
session_argument: hasura_session
|
@ -0,0 +1,8 @@
|
|||||||
|
type: bulk
|
||||||
|
args:
|
||||||
|
- type: run_sql
|
||||||
|
args:
|
||||||
|
cascade: true
|
||||||
|
sql: |
|
||||||
|
drop function me(json) cascade;
|
||||||
|
drop table profile cascade;
|
@ -314,3 +314,35 @@ class TestSubscriptionMultiplexing:
|
|||||||
sql = response['sql']
|
sql = response['sql']
|
||||||
assert isinstance(sql, str), response
|
assert isinstance(sql, str), response
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("backend", ['mssql', 'postgres'])
|
||||||
|
@usefixtures('per_class_tests_db_state', 'per_backend_tests', 'ws_conn_init')
|
||||||
|
class TestSubscriptionUDFWithSessionArg:
|
||||||
|
"""
|
||||||
|
Test a user-defined function which uses the entire session variables as argument
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = """
|
||||||
|
subscription {
|
||||||
|
me {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dir(cls):
|
||||||
|
return 'queries/subscriptions/udf_session_args'
|
||||||
|
|
||||||
|
def test_user_defined_function_with_session_argument(self, hge_ctx, ws_client):
|
||||||
|
ws_client.init_as_admin()
|
||||||
|
headers = {'x-hasura-role': 'user', 'x-hasura-user-id': '42'}
|
||||||
|
if hge_ctx.hge_key is not None:
|
||||||
|
headers['X-Hasura-Admin-Secret'] = hge_ctx.hge_key
|
||||||
|
payload = {'query': self.query}
|
||||||
|
resp = ws_client.send_query(payload, headers=headers, timeout=15)
|
||||||
|
ev = next(resp)
|
||||||
|
assert ev['type'] == 'data', ev
|
||||||
|
assert ev['payload']['data'] == {'me': [{'id': '42', 'name': 'Charlie'}]}, ev['payload']['data']
|
||||||
|
Loading…
Reference in New Issue
Block a user