From 398d36f8bf49d8a78cd938268a49246d60b7c7cd Mon Sep 17 00:00:00 2001 From: Taimoor Zaeem Date: Thu, 23 Jul 2026 13:25:31 +0500 Subject: [PATCH] Revert "fix: handle queries on non-existing table gracefully" This reverts commit 390ba199329c75f034e23e3c9029fdb22ec8ff2c. Signed-off-by: Taimoor Zaeem --- src/library/PostgREST/Error.hs | 19 ++------- src/library/PostgREST/Error/Types.hs | 3 +- src/library/PostgREST/Plan.hs | 38 +++++++---------- src/library/PostgREST/Response.hs | 4 +- src/library/PostgREST/SchemaCache.hs | 29 ++++--------- test/io/postgrest.py | 2 +- test/io/test_big_schema.py | 24 +---------- test/io/test_io.py | 8 ++-- test/spec/Feature/ConcurrentSpec.hs | 2 +- test/spec/Feature/Query/DeleteSpec.hs | 2 +- test/spec/Feature/Query/ErrorSpec.hs | 41 ++++--------------- test/spec/Feature/Query/InsertSpec.hs | 2 +- test/spec/Feature/Query/MultipleSchemaSpec.hs | 2 +- test/spec/Feature/Query/QuerySpec.hs | 12 +++--- 14 files changed, 52 insertions(+), 136 deletions(-) diff --git a/src/library/PostgREST/Error.hs b/src/library/PostgREST/Error.hs index fe2c2de5ba..b3ba84371b 100644 --- a/src/library/PostgREST/Error.hs +++ b/src/library/PostgREST/Error.hs @@ -3,7 +3,6 @@ Module : PostgREST.Error Description : PostgREST error HTTP responses -} {-# OPTIONS_GHC -fno-warn-orphans #-} -{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} module PostgREST.Error @@ -45,7 +44,6 @@ import PostgREST.MediaType (MediaType (..)) import qualified PostgREST.MediaType as MediaType import PostgREST.Config (Verbosity (..)) -import PostgREST.SchemaCache (SchemaCache (SchemaCache, dbTablesFuzzyIndex)) import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..), Schema) import PostgREST.SchemaCache.Relationship (Cardinality (..), Junction (..), Relationship (..), RelationshipsMap) @@ -252,7 +250,7 @@ instance ErrorBody SchemaCacheError where fmtPrms p = if null argumentKeys then " without parameters" else p message (AmbiguousRpc procs) = "Could not choose the best candidate function between: " <> T.intercalate ", " [pdSchema p <> "." <> pdName p <> "(" <> T.intercalate ", " [ppName a <> " => " <> ppType a | a <- pdParams p] <> ")" | p <- procs] message (ColumnNotFound rel col) = "Could not find the '" <> col <> "' column of '" <> rel <> "' in the schema cache" - message (TableNotFound schemaName relName _) = "Could not find the table '" <> schemaName <> "." <> relName <> "' in the schema cache" + message (TableNotFound qi) = "Could not find the table '" <> qiSchema qi <> "." <> qiName qi <> "' in the schema cache" details (NoRelBetween parent child embedHint schema _) = Just $ JSON.String $ "Searched for a foreign key relationship between '" <> parent <> "' and '" <> child <> maybe mempty ("' using the hint '" <>) embedHint <> "' in the schema '" <> schema <> "', but no matches were found." details (AmbiguousRelBetween _ _ rels) = Just $ JSON.toJSONList (compressedRel <$> rels) @@ -283,7 +281,6 @@ instance ErrorBody SchemaCacheError where where onlySingleParams = isInvPost && contentType `elem` [MTTextPlain, MTTextXML, MTOctetStream] hint (AmbiguousRpc _) = Just "Try renaming the parameters or the function itself in the database so function overloading can be resolved" - hint (TableNotFound schemaName relName schemaCache) = JSON.String <$> tableNotFoundHint schemaName relName schemaCache hint _ = Nothing @@ -381,25 +378,15 @@ noRpcHint schema procName params allProcs overloadedProcs = | null overloadedProcs = getFuzzyHint HintProcedure fuzzySetOfProcs procName | otherwise = (procName <>) <$> getFuzzyHint HintParams fuzzySetOfParams (listToText params) --- | --- Do a fuzzy search in all tables in the same schema and return closest result -tableNotFoundHint :: Text -> Text -> SchemaCache -> Maybe Text -tableNotFoundHint schema tblName SchemaCache{dbTablesFuzzyIndex} - = fmap (\tbl -> "Perhaps you meant the table '" <> schema <> "." <> tbl <> "'") perhapsTable - where - perhapsTable = (\fuzzySet -> getFuzzyHint HintTable fuzzySet tblName) =<< HM.lookup schema dbTablesFuzzyIndex - data HintType - = HintTable - | HintProcedure + = HintProcedure | HintParams -- | Get hint using Fuzzy Search with at least 0.75 similarity score getFuzzyHint :: HintType -> Fuzzy.FuzzySet -> Text -> Maybe Text getFuzzyHint hintType = - let minScore = 0.75 :: Double -- used for table and procedure name hints + let minScore = 0.75 :: Double -- used for procedure name hints in case hintType of - HintTable -> Fuzzy.getOneWithMinScore minScore HintProcedure -> Fuzzy.getOneWithMinScore minScore HintParams -> Fuzzy.getOne -- For params, we stick to `getOne` which defaults to 0.33 min score, not a security risk to reveal params diff --git a/src/library/PostgREST/Error/Types.hs b/src/library/PostgREST/Error/Types.hs index 31e66e7180..deed2dd9a2 100644 --- a/src/library/PostgREST/Error/Types.hs +++ b/src/library/PostgREST/Error/Types.hs @@ -20,7 +20,6 @@ module PostgREST.Error.Types import qualified Hasql.Pool as SQL import PostgREST.MediaType (MediaType (..)) -import PostgREST.SchemaCache (SchemaCache (..)) import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) import PostgREST.SchemaCache.Relationship (Relationship (..), RelationshipsMap) import PostgREST.SchemaCache.Routine (Routine (..)) @@ -84,7 +83,7 @@ data SchemaCacheError | NoRelBetween Text Text (Maybe Text) Text RelationshipsMap | NoRpc Text Text [Text] MediaType Bool [QualifiedIdentifier] [Routine] | ColumnNotFound Text Text - | TableNotFound Text Text SchemaCache + | TableNotFound QualifiedIdentifier deriving Show -- JWT ERRORS: PGRST3XX diff --git a/src/library/PostgREST/Plan.hs b/src/library/PostgREST/Plan.hs index 4cec7f0600..20743b74d8 100644 --- a/src/library/PostgREST/Plan.hs +++ b/src/library/PostgREST/Plan.hs @@ -36,7 +36,6 @@ import qualified PostgREST.SchemaCache.Routine as Routine import Data.Either.Combinators (mapLeft, mapRight) import Data.List (delete, lookup) -import Data.Maybe (fromJust) import Data.Tree (Tree (..)) import PostgREST.ApiRequest (ApiRequest (..)) @@ -193,20 +192,18 @@ dbActionPlan dbAct conf apiReq sCache = case dbAct of wrappedReadPlan :: QualifiedIdentifier -> AppConfig -> SchemaCache -> ApiRequest -> Bool -> Either Error CrudPlan wrappedReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferences{..},..} headersOnly = do - qi <- findTable identifier sCache - rPlan <- readPlan qi conf sCache apiRequest - (handler, mediaType) <- mapLeft ApiRequestErr $ negotiateContent conf apiRequest qi iAcceptMediaType (dbMediaHandlers sCache) (hasDefaultSelect rPlan) + rPlan <- readPlan identifier conf sCache apiRequest + (handler, mediaType) <- mapLeft ApiRequestErr $ negotiateContent conf apiRequest identifier iAcceptMediaType (dbMediaHandlers sCache) (hasDefaultSelect rPlan) if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestErr $ InvalidPreferences invalidPrefs else Right () - return $ WrappedReadPlan rPlan SQL.Read handler mediaType headersOnly qi + return $ WrappedReadPlan rPlan SQL.Read handler mediaType headersOnly identifier mutateReadPlan :: Mutation -> ApiRequest -> QualifiedIdentifier -> AppConfig -> SchemaCache -> Either Error CrudPlan mutateReadPlan mutation apiRequest@ApiRequest{iPreferences=Preferences{..},..} identifier conf sCache = do - qi <- findTable identifier sCache - rPlan <- readPlan qi conf sCache apiRequest - mPlan <- mutatePlan mutation qi apiRequest sCache rPlan + rPlan <- readPlan identifier conf sCache apiRequest + mPlan <- mutatePlan mutation identifier apiRequest sCache rPlan if not (null invalidPrefs) && preferHandling == Just Strict then Left $ ApiRequestErr $ InvalidPreferences invalidPrefs else Right () - (handler, mediaType) <- mapLeft ApiRequestErr $ negotiateContent conf apiRequest qi iAcceptMediaType (dbMediaHandlers sCache) (hasDefaultSelect rPlan) - return $ MutateReadPlan rPlan mPlan SQL.Write handler mediaType mutation qi + (handler, mediaType) <- mapLeft ApiRequestErr $ negotiateContent conf apiRequest identifier iAcceptMediaType (dbMediaHandlers sCache) (hasDefaultSelect rPlan) + return $ MutateReadPlan rPlan mPlan SQL.Write handler mediaType mutation identifier callReadPlan :: QualifiedIdentifier -> AppConfig -> SchemaCache -> ApiRequest -> InvokeMethod -> Either Error CrudPlan callReadPlan identifier conf sCache apiRequest@ApiRequest{iPreferences=Preferences{preferHandling, invalidPrefs, preferMaxAffected},..} invMethod = do @@ -832,13 +829,6 @@ validateAggFunctions aggFunctionsAllowed (Node rp@ReadPlan {select} forest) | not aggFunctionsAllowed && any (isJust . csAggFunction) select = Left $ ApiRequestErr AggregatesNotAllowed | otherwise = Node rp <$> traverse (validateAggFunctions aggFunctionsAllowed) forest --- | Lookup table in the schema cache before creating read plan -findTable :: QualifiedIdentifier -> SchemaCache -> Either Error QualifiedIdentifier -findTable qi@QualifiedIdentifier{..} sc@SchemaCache{dbTables} = - case HM.lookup qi dbTables of - Nothing -> Left $ SchemaCacheErr $ TableNotFound qiSchema qiName sc - Just _ -> Right qi - addFilters :: ResolverContext -> ApiRequest -> Bool -> ReadPlanTree -> Either Error ReadPlanTree addFilters ctx ApiRequest{..} useTargetNames rReq = foldr addFilterToNode (Right rReq) flts @@ -1066,18 +1056,18 @@ mutatePlan mutation qi ApiRequest{iPreferences=Preferences{..}, ..} SchemaCache{ if preferRepresentation == Just None || isNothing preferRepresentation then [] else S.toList $ inferColsEmbedNeeds readReq pkCols - -- TODO: remove fromJust by refactoring later - -- we can use fromJust, we have already looked up the table before building mutatePlan - tbl = fromJust $ HM.lookup qi dbTables - pkCols = maybe mempty tablePKCols (Just tbl) + tbl = HM.lookup qi dbTables + pkCols = maybe mempty tablePKCols tbl logic = map (resolveLogicTree ctx . snd) qsLogic combinedLogic = foldr (addFilterToLogicForest . resolveFilter ctx) logic qsFiltersRoot body = payRaw <$> iPayload -- the body is assumed to be json at this stage(ApiRequest validates) applyDefaults = preferMissing == Just ApplyDefaults - typedColumnsOrError = resolveOrError ctx tbl `traverse` S.toList iColumns + typedColumnsOrError = resolveOrError ctx tbl qi `traverse` S.toList iColumns -resolveOrError :: ResolverContext -> Table -> FieldName -> Either Error CoercibleField -resolveOrError ctx table field = case resolveTableFieldName table field Nothing of +resolveOrError :: ResolverContext -> Maybe Table -> QualifiedIdentifier -> FieldName -> Either Error CoercibleField +resolveOrError _ Nothing qi _ = Left $ SchemaCacheErr $ TableNotFound qi +resolveOrError ctx (Just table) _ field = + case resolveTableFieldName table field Nothing of CoercibleField{cfIRType=""} -> Left $ SchemaCacheErr $ ColumnNotFound (tableName table) field cf -> Right $ withJsonParse ctx cf diff --git a/src/library/PostgREST/Response.hs b/src/library/PostgREST/Response.hs index 89f431a98d..4048390d5b 100644 --- a/src/library/PostgREST/Response.hs +++ b/src/library/PostgREST/Response.hs @@ -207,10 +207,10 @@ actionResponse (MaybeDbResult InspectPlan{ipHdrsOnly=headersOnly} body) ApiReque in Right $ PgrstResponse HTTP.status200 (MediaType.toContentType MTOpenAPI : cLHeader ++ maybeToList (profileHeader iSchema iNegotiatedByProfile)) rsBody -actionResponse (NoDbResult (RelInfoPlan qi@QualifiedIdentifier{..})) _ _ _ sc@SchemaCache{dbTables} = +actionResponse (NoDbResult (RelInfoPlan qi)) _ _ _ SchemaCache{dbTables} = case HM.lookup qi dbTables of Just tbl -> respondInfo $ allowH tbl - Nothing -> Left $ Error.SchemaCacheErr $ Error.TableNotFound qiSchema qiName sc + Nothing -> Left $ Error.SchemaCacheErr $ Error.TableNotFound qi where allowH table = let hasPK = not . null $ tablePKCols table in diff --git a/src/library/PostgREST/SchemaCache.hs b/src/library/PostgREST/SchemaCache.hs index 31aaf6e075..d0441cc0ff 100644 --- a/src/library/PostgREST/SchemaCache.hs +++ b/src/library/PostgREST/SchemaCache.hs @@ -72,20 +72,16 @@ import Protolude type TablesFuzzyIndex = HM.HashMap Schema Fuzzy.FuzzySet data SchemaCache = SchemaCache - { dbTables :: TablesMap - , dbRelationships :: RelationshipsMap - , dbRoutines :: RoutineMap - , dbRepresentations :: RepresentationsMap - , dbMediaHandlers :: MediaHandlerMap - , dbTimezones :: TimezoneNames - -- Memoized fuzzy index of table names per schema to support approximate matching - -- Since index construction can be expensive, we build it once and store in the SchemaCache - -- Haskell lazy evaluation ensures it's only built on first use and memoized afterwards - , dbTablesFuzzyIndex :: TablesFuzzyIndex + { dbTables :: TablesMap + , dbRelationships :: RelationshipsMap + , dbRoutines :: RoutineMap + , dbRepresentations :: RepresentationsMap + , dbMediaHandlers :: MediaHandlerMap + , dbTimezones :: TimezoneNames } deriving (Show) instance JSON.ToJSON SchemaCache where - toJSON (SchemaCache tabs rels routs reps hdlers tzs _) = JSON.object [ + toJSON (SchemaCache tabs rels routs reps hdlers tzs) = JSON.object [ "dbTables" .= JSON.toJSON tabs , "dbRelationships" .= JSON.toJSON rels , "dbRoutines" .= JSON.toJSON routs @@ -95,7 +91,7 @@ instance JSON.ToJSON SchemaCache where ] showSummary :: SchemaCache -> Text -showSummary (SchemaCache tbls rels routs reps mediaHdlrs tzs _) = +showSummary (SchemaCache tbls rels routs reps mediaHdlrs tzs) = T.intercalate ", " [ show (HM.size tbls) <> " Relations" , show (HM.size rels) <> " Relationships" @@ -143,9 +139,6 @@ data KeyDep -- | A SQL query that can be executed independently type SqlQuery = ByteString -maxDbTablesForFuzzySearch :: Int -maxDbTablesForFuzzySearch = 500 - querySchemaCache :: AppConfig -> SQL.Transaction (SchemaCache, Maybe QueryTimings) querySchemaCache conf@AppConfig{..} = do SQL.sql "set local schema ''" -- This voids the search path. The following queries need this for getting the fully qualified name(schema.name) of every db object @@ -180,11 +173,6 @@ querySchemaCache conf@AppConfig{..} = do , dbRepresentations = reps , dbMediaHandlers = HM.union mHdlers initialMediaHandlers -- the custom handlers will override the initial ones , dbTimezones = tzones - - , dbTablesFuzzyIndex = - -- Only build fuzzy index for schemas with a reasonable number of tables - -- Fuzzy.FuzzySet is memory heavy we just don't use it for large schemas - Fuzzy.fromList <$> HM.filter ((< maxDbTablesForFuzzySearch) . length) (HM.fromListWith (<>) ((qiSchema &&& pure . qiName) <$> HM.keys tabsWViewsPks)) }, qsTime) where schemas = toList configDbSchemas @@ -223,7 +211,6 @@ removeInternal schemas dbStruct = , dbRepresentations = dbRepresentations dbStruct -- no need to filter, not directly exposed through the API , dbMediaHandlers = dbMediaHandlers dbStruct , dbTimezones = dbTimezones dbStruct - , dbTablesFuzzyIndex = dbTablesFuzzyIndex dbStruct } where hasInternalJunction ComputedRelationship{} = False diff --git a/test/io/postgrest.py b/test/io/postgrest.py index 07e974393d..66bb39a8c9 100644 --- a/test/io/postgrest.py +++ b/test/io/postgrest.py @@ -70,7 +70,7 @@ class PostgrestProcess: def read_stdout(self, nlines=1): "Wait for line(s) on standard output." output = [] - for _ in range(10): + for _ in range(15): self.process.stdout.flush() line = self.process.stdout.readline() if line: diff --git a/test/io/test_big_schema.py b/test/io/test_big_schema.py index 500087edf4..7b7c2c2742 100644 --- a/test/io/test_big_schema.py +++ b/test/io/test_big_schema.py @@ -97,26 +97,6 @@ def test_should_not_fail_with_stack_overflow(defaultenv): with run(env=env, wait_max_seconds=30) as postgrest: response = postgrest.session.get("/unknown-table?select=unknown-rel(*)") - assert response.status_code == 404 + assert response.status_code == 400 data = response.json() - assert data["code"] == "PGRST205" - - -def test_second_request_for_non_existent_table_should_be_quick(defaultenv): - "requesting a non-existent relationship should be quick after the fuzzy search index is loaded (2nd request)" - - env = { - **defaultenv, - "PGRST_DB_SCHEMAS": "fuzzysearch", - "PGRST_DB_POOL": "2", - "PGRST_DB_ANON_ROLE": "postgrest_test_anonymous", - } - - with run(env=env, wait_max_seconds=30) as postgrest: - response = postgrest.session.get("/unknown-table") - assert response.status_code == 404 - data = response.json() - assert data["code"] == "PGRST205" - first_duration = response.elapsed.total_seconds() - response = postgrest.session.get("/unknown-table") - assert response.elapsed.total_seconds() < first_duration / 2 + assert data["code"] == "PGRST200" diff --git a/test/io/test_io.py b/test/io/test_io.py index cdaf8cfa73..472f998fce 100644 --- a/test/io/test_io.py +++ b/test/io/test_io.py @@ -727,7 +727,7 @@ def test_log_level(level, defaultenv): response = postgrest.session.get("/") assert response.status_code == 200 - output = postgrest.read_stdout(nlines=9) + output = postgrest.read_stdout(nlines=13) if level == "crit": assert len(output) == 0 @@ -765,7 +765,7 @@ def test_log_level(level, defaultenv): r'- - postgrest_test_anonymous \[.+\] "GET / HTTP/1.1" 200 \d+ "" "python-requests/.+"', ], ) - assert len(output) == 9 + assert len(output) == 13 assert any("Connection" and "is available" in line for line in output) assert any("Connection" and "is used" in line for line in output) @@ -1118,10 +1118,10 @@ def test_stale_schema_cache_dropped_table_returns_database_error(defaultenv): response = postgrest.session.get("/stale_schema_cache_items") payload = response.json() assert response.status_code == 404 - assert payload["code"] == "PGRST205" + assert payload["code"] == "42P01" assert ( payload["message"] - == "Could not find the table 'public.stale_schema_cache_items' in the schema cache" + == 'relation "public.stale_schema_cache_items" does not exist' ) finally: psql_as_superuser("drop table if exists stale_schema_cache_items;") diff --git a/test/spec/Feature/ConcurrentSpec.hs b/test/spec/Feature/ConcurrentSpec.hs index b8fcc446a6..49770d5042 100644 --- a/test/spec/Feature/ConcurrentSpec.hs +++ b/test/spec/Feature/ConcurrentSpec.hs @@ -25,7 +25,7 @@ spec withConfig = withConfig baseCfg $ raceTest 10 $ get "/fakefake" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.fakefake' in the schema cache"} |] + [json| {"code":"42P01","details":null,"hint":null,"message":"relation \"test.fakefake\" does not exist"} |] { matchStatus = 404 , matchHeaders = [] } diff --git a/test/spec/Feature/Query/DeleteSpec.hs b/test/spec/Feature/Query/DeleteSpec.hs index 37bc284c2c..be1d8c803f 100644 --- a/test/spec/Feature/Query/DeleteSpec.hs +++ b/test/spec/Feature/Query/DeleteSpec.hs @@ -114,7 +114,7 @@ spec withConfig = withConfig baseCfg $ it "fails with 404" $ request methodDelete "/foozle?id=eq.101" [] "" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.foozle' in the schema cache"} |] + [json| {"code":"42P01","details":null,"hint":null,"message":"relation \"test.foozle\" does not exist"} |] { matchStatus = 404 , matchHeaders = [] } diff --git a/test/spec/Feature/Query/ErrorSpec.hs b/test/spec/Feature/Query/ErrorSpec.hs index 38259c3094..2b4fde2d43 100644 --- a/test/spec/Feature/Query/ErrorSpec.hs +++ b/test/spec/Feature/Query/ErrorSpec.hs @@ -40,12 +40,12 @@ spec withConfig = do } it "works with SchemaCache error" $ - get "/non_existent_table" + get "/items?nonexistent=eq.1" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.non_existent_table' in the schema cache"} |] - { matchStatus = 404 - , matchHeaders = [ "Proxy-Status" <:> "PostgREST; error=PGRST205" - , "Content-Length" <:> "129" ] + [json| {"code":"42703","details":null,"hint":null,"message":"column items.nonexistent does not exist"} |] + { matchStatus = 400 + , matchHeaders = [ "Proxy-Status" <:> "PostgREST; error=42703" + , "Content-Length" <:> "95" ] } it "works with Jwt error" $ do @@ -76,33 +76,6 @@ spec withConfig = do , "Content-Length" <:> "59" ] } - context "show hint on PGRST205 table not found error" $ do - it "show hint when similarity score is at least 75%" $ do - get "/projectx" -- at least 75% similar to "projects" - `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":"Perhaps you meant the table 'test.projects'","message":"Could not find the table 'test.projectx' in the schema cache"} |] - { matchStatus = 404 - , matchHeaders = [ "Proxy-Status" <:> "PostgREST; error=PGRST205" - , "Content-Length" <:> "160" ] - } - - get "/projecxx" -- at least 75% similar to "projects" - `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":"Perhaps you meant the table 'test.projects'","message":"Could not find the table 'test.projecxx' in the schema cache"} |] - { matchStatus = 404 - , matchHeaders = [ "Proxy-Status" <:> "PostgREST; error=PGRST205" - , "Content-Length" <:> "160" ] - } - - it "don't show hint when similarity score is less than 75%" $ - get "/projxxxx" -- less than 75% similar to "projects" - `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.projxxxx' in the schema cache"} |] - { matchStatus = 404 - , matchHeaders = [ "Proxy-Status" <:> "PostgREST; error=PGRST205" - , "Content-Length" <:> "119" ] - } - context "JWT Errors" $ do it "error on jwt encoded with wrong secret" $ do let jwtPayload = [json|{}|] @@ -231,7 +204,7 @@ spec withConfig = do request methodGet "/itemsx" [] "" `shouldRespondWith` [json|{ - "code":"PGRST205", - "message":"Could not find the table 'test.itemsx' in the schema cache" + "code":"42P01", + "message":"relation \"test.itemsx\" does not exist" }|] { matchStatus = 404 } diff --git a/test/spec/Feature/Query/InsertSpec.hs b/test/spec/Feature/Query/InsertSpec.hs index 97ebe6774a..6d71c2a072 100644 --- a/test/spec/Feature/Query/InsertSpec.hs +++ b/test/spec/Feature/Query/InsertSpec.hs @@ -480,7 +480,7 @@ spec withConfig = withConfig baseCfg $ do {"id": 204, "body": "yyy"}, {"id": 205, "body": "zzz"}]|] `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.garlic' in the schema cache"} |] + [json|{"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.garlic' in the schema cache"}|] { matchStatus = 404 , matchHeaders = [] } diff --git a/test/spec/Feature/Query/MultipleSchemaSpec.hs b/test/spec/Feature/Query/MultipleSchemaSpec.hs index 3de964b4ad..e2f6542580 100644 --- a/test/spec/Feature/Query/MultipleSchemaSpec.hs +++ b/test/spec/Feature/Query/MultipleSchemaSpec.hs @@ -69,7 +69,7 @@ spec withConfig = withConfig (baseCfg { configDbSchemas = fromList ["v1", "v2", request methodGet "/another_table" [("Accept-Profile", "v1")] "" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'v1.another_table' in the schema cache"} |] + [json| {"code":"42P01","details":null,"hint":null,"message":"relation \"v1.another_table\" does not exist"} |] { matchStatus = 404 , matchHeaders = [] } diff --git a/test/spec/Feature/Query/QuerySpec.hs b/test/spec/Feature/Query/QuerySpec.hs index 4282e9162a..f8a970bdb4 100644 --- a/test/spec/Feature/Query/QuerySpec.hs +++ b/test/spec/Feature/Query/QuerySpec.hs @@ -28,9 +28,9 @@ spec actualPgVersion withConfig = withConfig baseCfg $ do it "causes a 404" $ get "/faketable" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.faketable' in the schema cache"} |] + [json|{"code":"42P01","details":null,"hint":null,"message":"relation \"test.faketable\" does not exist"}|] { matchStatus = 404 - , matchHeaders = ["Content-Length" <:> "120"] + , matchHeaders = ["Content-Length" <:> "98"] } describe "Filtering response" $ do @@ -854,8 +854,8 @@ spec actualPgVersion withConfig = withConfig baseCfg $ do -- the existence of first table, #3869 it "table not found error if first table does not exist" $ get "/car_model_sales_202101?select=id,name,car_models(id,name)&order=id.asc" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.car_model_sales_202101' in the schema cache"} |] - { matchStatus = 404 + [json|{"code":"PGRST200","details":"Searched for a foreign key relationship between 'car_model_sales_202101' and 'car_models' in the schema 'test', but no matches were found.","hint":"Perhaps you meant 'car_model_sales' instead of 'car_model_sales_202101'.","message":"Could not find a relationship between 'car_model_sales_202101' and 'car_models' in the schema cache"}|] + { matchStatus = 400 , matchHeaders = [matchContentTypeJson] } @@ -872,8 +872,8 @@ spec actualPgVersion withConfig = withConfig baseCfg $ do it "table not found error if first table does not exist" $ get "/car_models_default?select=id,name,car_model_sales(id,name)&order=id.asc" `shouldRespondWith` - [json| {"code":"PGRST205","details":null,"hint":null,"message":"Could not find the table 'test.car_models_default' in the schema cache"} |] - { matchStatus = 404 + [json| {"code":"PGRST200","details":"Searched for a foreign key relationship between 'car_models_default' and 'car_model_sales' in the schema 'test', but no matches were found.","hint":"Perhaps you meant 'car_model_sales' instead of 'car_models_default'.","message":"Could not find a relationship between 'car_models_default' and 'car_model_sales' in the schema cache"} |] + { matchStatus = 400 , matchHeaders = [matchContentTypeJson] }