@@ -15,6 +15,7 @@ import (
1515 "go.temporal.io/sdk/log"
1616
1717 "github.com/PeerDB-io/peerdb/flow/generated/protos"
18+ "github.com/PeerDB-io/peerdb/flow/internal"
1819 "github.com/PeerDB-io/peerdb/flow/model"
1920 "github.com/PeerDB-io/peerdb/flow/shared"
2021 "github.com/PeerDB-io/peerdb/flow/shared/datatypes"
@@ -24,19 +25,20 @@ import (
2425type QRepQueryExecutor struct {
2526 * PostgresConnector
2627 logger log.Logger
28+ env map [string ]string
2729 snapshot string
2830 flowJobName string
2931 partitionID string
3032 version uint32
3133}
3234
33- func (c * PostgresConnector ) NewQRepQueryExecutor (ctx context.Context , version uint32 ,
35+ func (c * PostgresConnector ) NewQRepQueryExecutor (ctx context.Context , env map [ string ] string , version uint32 ,
3436 flowJobName string , partitionID string ,
3537) (* QRepQueryExecutor , error ) {
36- return c .NewQRepQueryExecutorSnapshot (ctx , version , "" , flowJobName , partitionID )
38+ return c .NewQRepQueryExecutorSnapshot (ctx , env , version , "" , flowJobName , partitionID )
3739}
3840
39- func (c * PostgresConnector ) NewQRepQueryExecutorSnapshot (ctx context.Context , version uint32 ,
41+ func (c * PostgresConnector ) NewQRepQueryExecutorSnapshot (ctx context.Context , env map [ string ] string , version uint32 ,
4042 snapshot string , flowJobName string , partitionID string ,
4143) (* QRepQueryExecutor , error ) {
4244 if _ , err := c .fetchCustomTypeMapping (ctx ); err != nil {
@@ -49,6 +51,7 @@ func (c *PostgresConnector) NewQRepQueryExecutorSnapshot(ctx context.Context, ve
4951 flowJobName : flowJobName ,
5052 partitionID : partitionID ,
5153 logger : log .With (c .logger , slog .String (string (shared .PartitionIDKey ), partitionID )),
54+ env : env ,
5255 version : version ,
5356 }, nil
5457}
@@ -73,13 +76,21 @@ func (qe *QRepQueryExecutor) cursorToSchema(
7376 num uint16
7477 }
7578
79+ strictNullable , err := internal .PeerDBNullableStrict (ctx , qe .env )
80+ if err != nil {
81+ return types.QRecordSchema {}, err
82+ }
83+
7684 rows , err := tx .Query (ctx , "FETCH 0 FROM " + cursorName )
7785 if err != nil {
7886 return types.QRecordSchema {}, fmt .Errorf ("failed to fetch 0 for field descriptions: %w" , err )
7987 }
8088 fds := rows .FieldDescriptions ()
8189 tableOIDset := make (map [uint32 ]struct {})
82- nullPointers := make (map [attId ]* bool , len (fds ))
90+ var nullPointers map [attId ]* bool
91+ if strictNullable {
92+ nullPointers = make (map [attId ]* bool , len (fds ))
93+ }
8394 qfields := make ([]types.QField , len (fds ))
8495 for i , fd := range fds {
8596 tableOIDset [fd .TableOID ] = struct {}{}
@@ -89,38 +100,42 @@ func (qe *QRepQueryExecutor) cursorToSchema(
89100 qfields [i ] = types.QField {
90101 Name : fd .Name ,
91102 Type : ctype ,
92- Nullable : false ,
103+ Nullable : ! strictNullable ,
93104 Precision : precision ,
94105 Scale : scale ,
95106 }
96107 } else {
97108 qfields [i ] = types.QField {
98109 Name : fd .Name ,
99110 Type : ctype ,
100- Nullable : false ,
111+ Nullable : ! strictNullable ,
101112 }
102113 }
103- nullPointers [attId {
104- relid : fd .TableOID ,
105- num : fd .TableAttributeNumber ,
106- }] = & qfields [i ].Nullable
114+ if nullPointers != nil {
115+ nullPointers [attId {
116+ relid : fd .TableOID ,
117+ num : fd .TableAttributeNumber ,
118+ }] = & qfields [i ].Nullable
119+ }
107120 }
108121 rows .Close ()
109- tableOIDs := slices .Collect (maps .Keys (tableOIDset ))
110122
111- rows , err = tx .Query (ctx , "SELECT a.attrelid,a.attnum FROM pg_attribute a WHERE a.attrelid = ANY($1) AND NOT a.attnotnull" , tableOIDs )
112- if err != nil {
113- return types.QRecordSchema {}, fmt .Errorf ("failed to query schema for field descriptions: %w" , err )
114- }
123+ if nullPointers != nil {
124+ tableOIDs := slices .Collect (maps .Keys (tableOIDset ))
125+ rows , err = tx .Query (ctx , "SELECT a.attrelid,a.attnum FROM pg_attribute a WHERE a.attrelid = ANY($1) AND NOT a.attnotnull" , tableOIDs )
126+ if err != nil {
127+ return types.QRecordSchema {}, fmt .Errorf ("failed to query schema for field descriptions: %w" , err )
128+ }
115129
116- var att attId
117- if _ , err := pgx .ForEachRow (rows , []any {& att .relid , & att .num }, func () error {
118- if nullPointer , ok := nullPointers [att ]; ok {
119- * nullPointer = true
130+ var att attId
131+ if _ , err := pgx .ForEachRow (rows , []any {& att .relid , & att .num }, func () error {
132+ if nullPointer , ok := nullPointers [att ]; ok {
133+ * nullPointer = true
134+ }
135+ return nil
136+ }); err != nil {
137+ return types.QRecordSchema {}, fmt .Errorf ("failed to process schema for field descriptions: %w" , err )
120138 }
121- return nil
122- }); err != nil {
123- return types.QRecordSchema {}, fmt .Errorf ("failed to process schema for field descriptions: %w" , err )
124139 }
125140
126141 return types .NewQRecordSchema (qfields ), nil
0 commit comments