mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 08:02:15 +03:00
Fix Postgres not padding timestamps correctly (fix hasura/graphql-engine#8096)
## Description As identified in hasura/graphql-engine#8096, the format string we used for timestamps was incorrect; we were using `%F`, which expands to `%Y-%m-%d`; but that meant that the year was not padded to four digits: `0001` would be represented simply as `1`. However, Postgres inteprets that `1` as `2001`, probably due to interpretation rules about two-digit years (in `25/12/01`, `01` is indeed `2001`). ``` # create table timestamp_test ( test timestamptz ); CREATE TABLE # insert into timestamp_test values ('1-01-01T00:00:57Z'); INSERT 0 1 # select * from timestamp_test; test ------------------------ 2001-01-01 00:00:57+00 (1 row) ``` To fix this, this PR changes the format string to use `%0Y`, which always pads the year number with zeroes. ## Remaining work - [x] write Changelog entry - [ ] copy timestamp tests from the python suite into the hspec tests PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3536 GitOrigin-RevId: fa144111358339fd4a35b32d888c1d2c5b418ea6
This commit is contained in:
parent
d1f8b9a87d
commit
697137dd77
@ -4,6 +4,7 @@
|
||||
|
||||
### Bug fixes and improvements
|
||||
|
||||
- server: fixed a bug where timestamp values sent to postgres would erroneously trim leading zeroes (#8096)
|
||||
- server: fix bug when event triggers where defined on tables that contained non lower-case alphabet characters
|
||||
- server: avoid encoding 'varchar' values to UTF8 in MSSQL backends
|
||||
- server: add support for MSSQL event triggers (#7228)
|
||||
|
@ -1091,9 +1091,9 @@ test-suite tests-hspec
|
||||
Harness.Backend.Sqlserver
|
||||
|
||||
-- Harness.Test
|
||||
Harness.Test.BackendType
|
||||
Harness.Test.Context
|
||||
Harness.Test.Schema
|
||||
Harness.Test.BackendType
|
||||
|
||||
-- Harness.Quoter
|
||||
Harness.Quoter.Graphql
|
||||
@ -1107,30 +1107,31 @@ test-suite tests-hspec
|
||||
Test.CustomFieldNamesSpec
|
||||
Test.DirectivesSpec
|
||||
Test.HelloWorldSpec
|
||||
Test.InsertCheckPermissionSpec
|
||||
Test.InsertEnumColumnSpec
|
||||
Test.LimitOffsetSpec
|
||||
Test.NestedRelationshipsSpec
|
||||
Test.ObjectRelationshipsLimitSpec
|
||||
Test.ObjectRelationshipsSpec
|
||||
Test.OrderingSpec
|
||||
Test.PostgresTypesSpec
|
||||
Test.PrimaryKeySpec
|
||||
Test.RemoteRelationship.MetadataAPI.Common
|
||||
Test.RemoteRelationship.FromRemoteSchemaSpec
|
||||
Test.RemoteRelationship.MetadataAPI.ClearMetadataSpec
|
||||
Test.RemoteRelationship.MetadataAPI.Common
|
||||
Test.RemoteRelationship.MetadataAPI.DropSource.DBtoDBRelationshipSpec
|
||||
Test.RemoteRelationship.MetadataAPI.DropSource.RSToDBRelationshipSpec
|
||||
Test.RemoteRelationship.FromRemoteSchemaSpec
|
||||
Test.RemoteRelationship.XToDBArrayRelationshipSpec
|
||||
Test.RemoteRelationship.XToDBObjectRelationshipSpec
|
||||
Test.RemoteRelationship.XToRemoteSchemaRelationshipSpec
|
||||
Test.RequestHeadersSpec
|
||||
Test.SerializationSpec
|
||||
Test.RunSQLSpec
|
||||
Test.SQLServer.InsertVarcharColumnSpec
|
||||
Test.SelectSpec
|
||||
Test.SerializationSpec
|
||||
Test.ServiceLivenessSpec
|
||||
Test.ViewsSpec
|
||||
Test.WhereSpec
|
||||
Test.RunSQLSpec
|
||||
Test.InsertCheckPermissionSpec
|
||||
Test.InsertEnumColumnSpec
|
||||
Test.SQLServer.InsertVarcharColumnSpec
|
||||
|
||||
test-suite tests-dc-api
|
||||
import: common-all, common-exe
|
||||
|
@ -120,10 +120,8 @@ pgScalarValueToJson = \case
|
||||
PGValText t -> toJSON t
|
||||
PGValCitext t -> toJSON t
|
||||
PGValDate d -> toJSON d
|
||||
PGValTimeStamp u ->
|
||||
toJSON $ formatTime defaultTimeLocale "%FT%T%QZ" u
|
||||
PGValTimeStampTZ u ->
|
||||
toJSON $ formatTime defaultTimeLocale "%FT%T%QZ" u
|
||||
PGValTimeStamp u -> String $ formatTimestamp u
|
||||
PGValTimeStampTZ u -> String $ formatTimestamp u
|
||||
PGValTimeTZ (ZonedTimeOfDay tod tz) ->
|
||||
toJSON (show tod ++ timeZoneOffsetString tz)
|
||||
PGNull _ -> Null
|
||||
@ -243,10 +241,8 @@ txtEncodedVal = \case
|
||||
PGValText t -> TELit t
|
||||
PGValCitext t -> TELit t
|
||||
PGValDate d -> TELit $ T.pack $ showGregorian d
|
||||
PGValTimeStamp u ->
|
||||
TELit $ T.pack $ formatTime defaultTimeLocale "%FT%T%QZ" u
|
||||
PGValTimeStampTZ u ->
|
||||
TELit $ T.pack $ formatTime defaultTimeLocale "%FT%T%QZ" u
|
||||
PGValTimeStamp u -> TELit $ formatTimestamp u
|
||||
PGValTimeStampTZ u -> TELit $ formatTimestamp u
|
||||
PGValTimeTZ (ZonedTimeOfDay tod tz) ->
|
||||
TELit $ T.pack (show tod ++ timeZoneOffsetString tz)
|
||||
PGNull _ ->
|
||||
@ -332,6 +328,9 @@ binEncoder = \case
|
||||
PGValLtxtquery t -> Q.toPrepVal t
|
||||
PGValUnknown t -> (PTI.auto, Just (TE.encodeUtf8 t, PQ.Text))
|
||||
|
||||
formatTimestamp :: FormatTime t => t -> Text
|
||||
formatTimestamp = T.pack . formatTime defaultTimeLocale "%0Y-%m-%dT%T%QZ"
|
||||
|
||||
txtEncoder :: PGScalarValue -> S.SQLExp
|
||||
txtEncoder colVal = case txtEncodedVal colVal of
|
||||
TENull -> S.SENull
|
||||
|
97
server/tests-hspec/Test/PostgresTypesSpec.hs
Normal file
97
server/tests-hspec/Test/PostgresTypesSpec.hs
Normal file
@ -0,0 +1,97 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
{-# LANGUAGE RecordWildCards #-}
|
||||
|
||||
-- | Tests around Postgres-specific database types
|
||||
module Test.PostgresTypesSpec (spec) where
|
||||
|
||||
import Harness.Backend.Postgres as Postgres
|
||||
import Harness.GraphqlEngine qualified as GraphqlEngine
|
||||
import Harness.Quoter.Graphql
|
||||
import Harness.Quoter.Sql
|
||||
import Harness.Quoter.Yaml
|
||||
import Harness.Test.Context qualified as Context
|
||||
import Harness.TestEnvironment (TestEnvironment)
|
||||
import Test.Hspec
|
||||
import Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Preamble
|
||||
|
||||
spec :: SpecWith TestEnvironment
|
||||
spec =
|
||||
Context.run
|
||||
[ Context.Context
|
||||
{ name = Context.Backend Context.Postgres,
|
||||
mkLocalTestEnvironment = Context.noLocalTestEnvironment,
|
||||
setup = postgresSetup,
|
||||
teardown = postgresTeardown,
|
||||
customOptions = Nothing
|
||||
}
|
||||
]
|
||||
tests
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Postgres
|
||||
|
||||
postgresSetup :: (TestEnvironment, ()) -> IO ()
|
||||
postgresSetup (testEnvironment, _) = do
|
||||
-- Clear and reconfigure the metadata
|
||||
GraphqlEngine.setSource testEnvironment Postgres.defaultSourceMetadata
|
||||
|
||||
-- Setup tables
|
||||
Postgres.run_
|
||||
[sql|
|
||||
create table timestamp_test (
|
||||
id serial primary key,
|
||||
time timestamptz
|
||||
);
|
||||
|]
|
||||
|
||||
-- Track the tables
|
||||
GraphqlEngine.post_
|
||||
testEnvironment
|
||||
"/v1/metadata"
|
||||
[yaml|
|
||||
type: postgres_track_table
|
||||
args:
|
||||
source: postgres
|
||||
table:
|
||||
schema: hasura
|
||||
name: timestamp_test
|
||||
|]
|
||||
|
||||
postgresTeardown :: (TestEnvironment, ()) -> IO ()
|
||||
postgresTeardown _ = do
|
||||
Postgres.run_
|
||||
[sql|
|
||||
DROP TABLE hasura.timestamp_test;
|
||||
|]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Tests
|
||||
|
||||
tests :: Context.Options -> SpecWith TestEnvironment
|
||||
tests opts = do
|
||||
it "doesn't mess up timestamps on insertion" $ \testEnvironment ->
|
||||
shouldReturnYaml
|
||||
opts
|
||||
( GraphqlEngine.postGraphql
|
||||
testEnvironment
|
||||
[graphql|
|
||||
mutation {
|
||||
insert_hasura_timestamp_test(objects:[{
|
||||
time: "0001-01-01T00:00:57Z"
|
||||
}]) {
|
||||
returning {
|
||||
time
|
||||
}
|
||||
}
|
||||
}
|
||||
|]
|
||||
)
|
||||
[yaml|
|
||||
data:
|
||||
insert_hasura_timestamp_test:
|
||||
returning:
|
||||
- time: "0001-01-01T00:00:57+00:00"
|
||||
|]
|
Loading…
Reference in New Issue
Block a user