From 4ca16947cf9a697160f26ec026e9df9235a270fe Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Sun, 21 Jul 2024 14:51:00 +0700 Subject: [PATCH 01/11] supports array data type for RPC requests --- rpc.go | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 188 insertions(+), 2 deletions(-) diff --git a/rpc.go b/rpc.go index 7386876b..8f3e3b7c 100644 --- a/rpc.go +++ b/rpc.go @@ -29,6 +29,7 @@ const ( RpcParamDataTypeBigInt RpcParamDataType = "BIGINT" RpcParamDataTypeReal RpcParamDataType = "REAL" RpcParamDataTypeDoublePreci RpcParamDataType = "DOUBLE PRECISION" + RpcParamDataTypeNumeric RpcParamDataType = "NUMERIC" RpcParamDataTypeText RpcParamDataType = "TEXT" RpcParamDataTypeVarchar RpcParamDataType = "CHARACTER VARYING" RpcParamDataTypeVarcharAlias RpcParamDataType = "VARCHAR" @@ -40,6 +41,24 @@ const ( RpcParamDataTypeTimestampTZAlias RpcParamDataType = "TIMESTAMPZ" RpcParamDataTypeJSON RpcParamDataType = "JSON" RpcParamDataTypeJSONB RpcParamDataType = "JSONB" + + // ARRAY TYPES + RpcParamDataTypeArrayInteger RpcParamDataType = "INTEGER[]" + RpcParamDataTypeArrayBigInt RpcParamDataType = "BIGINT[]" + RpcParamDataTypeArrayReal RpcParamDataType = "REAL[]" + RpcParamDataTypeArrayDoublePreci RpcParamDataType = "DOUBLE PRECISION[]" + RpcParamDataTypeArrayNumeric RpcParamDataType = "NUMERIC[]" + RpcParamDataTypeArrayText RpcParamDataType = "TEXT[]" + RpcParamDataTypeArrayVarchar RpcParamDataType = "CHARACTER VARYING[]" + RpcParamDataTypeArrayVarcharAlias RpcParamDataType = "VARCHAR[]" + RpcParamDataTypeArrayBoolean RpcParamDataType = "BOOLEAN[]" + RpcParamDataTypeArrayBytea RpcParamDataType = "BYTEA[]" + RpcParamDataTypeArrayTimestamp RpcParamDataType = "TIMESTAMP WITHOUT TIME ZONE[]" + RpcParamDataTypeArrayTimestampAlias RpcParamDataType = "TIMESTAMP[]" + RpcParamDataTypeArrayTimestampTZ RpcParamDataType = "TIMESTAMP WITH TIME ZONE[]" + RpcParamDataTypeArrayTimestampTZAlias RpcParamDataType = "TIMESTAMPZ[]" + RpcParamDataTypeArrayJSON RpcParamDataType = "JSON[]" + RpcParamDataTypeArrayJSONB RpcParamDataType = "JSONB[]" ) // Define constants for rpc return data type @@ -48,6 +67,7 @@ const ( RpcReturnDataTypeBigInt RpcReturnDataType = "BIGINT" RpcReturnDataTypeReal RpcReturnDataType = "REAL" RpcReturnDataTypeDoublePreci RpcReturnDataType = "DOUBLE PRECISION" + RpcReturnDataTypeNumeric RpcReturnDataType = "NUMERIC" RpcReturnDataTypeText RpcReturnDataType = "TEXT" RpcReturnDataTypeVarchar RpcReturnDataType = "CHARACTER VARYING" RpcReturnDataTypeVarcharAlias RpcReturnDataType = "VARCHAR" @@ -63,6 +83,24 @@ const ( RpcReturnDataTypeTable RpcReturnDataType = "TABLE" RpcReturnDataTypeSetOf RpcReturnDataType = "SETOF" RpcReturnDataTypeVoid RpcReturnDataType = "VOID" + + // ARRAY TYPES + RpcReturnDataTypeArrayInteger RpcReturnDataType = "INTEGER[]" + RpcReturnDataTypeArrayBigInt RpcReturnDataType = "BIGINT[]" + RpcReturnDataTypeArrayReal RpcReturnDataType = "REAL[]" + RpcReturnDataTypeArrayDoublePreci RpcReturnDataType = "DOUBLE PRECISION[]" + RpcReturnDataTypeArrayNumeric RpcReturnDataType = "NUMERIC[]" + RpcReturnDataTypeArrayText RpcReturnDataType = "TEXT[]" + RpcReturnDataTypeArrayVarchar RpcReturnDataType = "CHARACTER VARYING[]" + RpcReturnDataTypeArrayVarcharAlias RpcReturnDataType = "VARCHAR[]" + RpcReturnDataTypeArrayBoolean RpcReturnDataType = "BOOLEAN[]" + RpcReturnDataTypeArrayBytea RpcReturnDataType = "BYTEA[]" + RpcReturnDataTypeArrayTimestamp RpcReturnDataType = "TIMESTAMP WITHOUT TIME ZONE[]" + RpcReturnDataTypeArrayTimestampAlias RpcReturnDataType = "TIMESTAMP[]" + RpcReturnDataTypeArrayTimestampTZ RpcReturnDataType = "TIMESTAMP WITH TIME ZONE[]" + RpcReturnDataTypeArrayTimestampTZAlias RpcReturnDataType = "TIMESTAMPZ[]" + RpcReturnDataTypeArrayJSON RpcReturnDataType = "JSON[]" + RpcReturnDataTypeArrayJSONB RpcReturnDataType = "JSONB[]" ) func RpcParamToGoType(dataType RpcParamDataType) string { @@ -71,7 +109,7 @@ func RpcParamToGoType(dataType RpcParamDataType) string { return "int64" case RpcParamDataTypeReal: return "float32" - case RpcParamDataTypeDoublePreci: + case RpcParamDataTypeDoublePreci, RpcParamDataTypeNumeric: return "float64" case RpcParamDataTypeText, RpcParamDataTypeVarchar, RpcParamDataTypeVarcharAlias: return "string" @@ -83,6 +121,23 @@ func RpcParamToGoType(dataType RpcParamDataType) string { return "time.Time" case RpcParamDataTypeJSON, RpcParamDataTypeJSONB: return "map[string]interface{}" + // ARRAY TYPES + case RpcParamDataTypeArrayInteger, RpcParamDataTypeArrayBigInt: + return "[]int64" + case RpcParamDataTypeArrayReal: + return "[]float32" + case RpcParamDataTypeArrayDoublePreci, RpcParamDataTypeArrayNumeric: + return "[]float64" + case RpcParamDataTypeArrayText, RpcParamDataTypeArrayVarchar, RpcParamDataTypeArrayVarcharAlias: + return "[]string" + case RpcParamDataTypeArrayBoolean: + return "[]bool" + case RpcParamDataTypeArrayBytea: + return "[][]byte" + case RpcParamDataTypeArrayTimestamp, RpcParamDataTypeArrayTimestampTZ, RpcParamDataTypeArrayTimestampAlias, RpcParamDataTypeArrayTimestampTZAlias: + return "[]time.Time" + case RpcParamDataTypeArrayJSON, RpcParamDataTypeArrayJSONB: + return "[]map[string]interface{}" default: return "interface{}" // Return interface{} for unknown types } @@ -99,6 +154,8 @@ func GetValidRpcParamType(pType string, returnAlias bool) (RpcParamDataType, err return RpcParamDataTypeReal, nil case RpcParamDataTypeDoublePreci: return RpcParamDataTypeDoublePreci, nil + case RpcParamDataTypeNumeric: + return RpcParamDataTypeNumeric, nil case RpcParamDataTypeText: return RpcParamDataTypeText, nil case RpcParamDataTypeVarchar, RpcParamDataTypeVarcharAlias: @@ -124,6 +181,42 @@ func GetValidRpcParamType(pType string, returnAlias bool) (RpcParamDataType, err return RpcParamDataTypeJSON, nil case RpcParamDataTypeJSONB: return RpcParamDataTypeJSONB, nil + // ARRAY TYPES + case RpcParamDataTypeArrayInteger: + return RpcParamDataTypeArrayInteger, nil + case RpcParamDataTypeArrayBigInt: + return RpcParamDataTypeArrayBigInt, nil + case RpcParamDataTypeArrayReal: + return RpcParamDataTypeArrayReal, nil + case RpcParamDataTypeArrayDoublePreci: + return RpcParamDataTypeArrayDoublePreci, nil + case RpcParamDataTypeArrayNumeric: + return RpcParamDataTypeArrayNumeric, nil + case RpcParamDataTypeArrayText: + return RpcParamDataTypeArrayText, nil + case RpcParamDataTypeArrayVarchar, RpcParamDataTypeArrayVarcharAlias: + if returnAlias { + return RpcParamDataTypeArrayVarcharAlias, nil + } + return RpcParamDataTypeArrayVarchar, nil + case RpcParamDataTypeArrayBoolean: + return RpcParamDataTypeArrayBoolean, nil + case RpcParamDataTypeArrayBytea: + return RpcParamDataTypeArrayBytea, nil + case RpcParamDataTypeArrayTimestamp, RpcParamDataTypeArrayTimestampAlias: + if returnAlias { + return RpcParamDataTypeArrayTimestampAlias, nil + } + return RpcParamDataTypeArrayTimestamp, nil + case RpcParamDataTypeArrayTimestampTZ, RpcParamDataTypeArrayTimestampTZAlias: + if returnAlias { + return RpcParamDataTypeArrayTimestampTZAlias, nil + } + return RpcParamDataTypeArrayTimestampTZ, nil + case RpcParamDataTypeArrayJSON: + return RpcParamDataTypeArrayJSON, nil + case RpcParamDataTypeArrayJSONB: + return RpcParamDataTypeArrayJSONB, nil default: return "", fmt.Errorf("unsupported rpc param type : %s", pCheckType) } @@ -135,7 +228,7 @@ func RpcReturnToGoType(dataType RpcReturnDataType) string { return "int64" case RpcReturnDataTypeReal: return "float32" - case RpcReturnDataTypeDoublePreci: + case RpcReturnDataTypeDoublePreci, RpcReturnDataTypeNumeric: return "float64" case RpcReturnDataTypeText, RpcReturnDataTypeVarchar: return "string" @@ -147,6 +240,23 @@ func RpcReturnToGoType(dataType RpcReturnDataType) string { return "time.Time" case RpcReturnDataTypeJSON, RpcReturnDataTypeJSONB: return "map[string]interface{}" + // ARRAY TYPES + case RpcReturnDataTypeArrayInteger, RpcReturnDataTypeArrayBigInt: + return "[]int64" + case RpcReturnDataTypeArrayReal: + return "[]float32" + case RpcReturnDataTypeArrayDoublePreci, RpcReturnDataTypeArrayNumeric: + return "[]float64" + case RpcReturnDataTypeArrayText, RpcReturnDataTypeArrayVarchar: + return "[]string" + case RpcReturnDataTypeArrayBoolean: + return "[]bool" + case RpcReturnDataTypeArrayBytea: + return "[][]byte" + case RpcReturnDataTypeArrayTimestamp, RpcReturnDataTypeArrayTimestampTZ: + return "[]time.Time" + case RpcReturnDataTypeArrayJSON, RpcReturnDataTypeArrayJSONB: + return "[]map[string]interface{}" default: return "interface{}" // Return interface{} for unknown types } @@ -163,6 +273,8 @@ func GetValidRpcReturnType(pType string, returnAlias bool) (RpcReturnDataType, e return RpcReturnDataTypeReal, nil case RpcReturnDataTypeDoublePreci: return RpcReturnDataTypeDoublePreci, nil + case RpcReturnDataTypeNumeric: + return RpcReturnDataTypeNumeric, nil case RpcReturnDataTypeText: return RpcReturnDataTypeText, nil case RpcReturnDataTypeVarchar, RpcReturnDataTypeVarcharAlias: @@ -194,6 +306,42 @@ func GetValidRpcReturnType(pType string, returnAlias bool) (RpcReturnDataType, e return RpcReturnDataTypeTable, nil case RpcReturnDataTypeVoid: return RpcReturnDataTypeVoid, nil + // ARRAY TYPES + case RpcReturnDataTypeArrayInteger: + return RpcReturnDataTypeArrayInteger, nil + case RpcReturnDataTypeArrayBigInt: + return RpcReturnDataTypeArrayBigInt, nil + case RpcReturnDataTypeArrayReal: + return RpcReturnDataTypeArrayReal, nil + case RpcReturnDataTypeArrayDoublePreci: + return RpcReturnDataTypeArrayDoublePreci, nil + case RpcReturnDataTypeArrayNumeric: + return RpcReturnDataTypeArrayNumeric, nil + case RpcReturnDataTypeArrayText: + return RpcReturnDataTypeArrayText, nil + case RpcReturnDataTypeArrayVarchar, RpcReturnDataTypeArrayVarcharAlias: + if returnAlias { + return RpcReturnDataTypeArrayVarcharAlias, nil + } + return RpcReturnDataTypeArrayVarchar, nil + case RpcReturnDataTypeArrayBoolean: + return RpcReturnDataTypeArrayBoolean, nil + case RpcReturnDataTypeArrayBytea: + return RpcReturnDataTypeArrayBytea, nil + case RpcReturnDataTypeArrayTimestamp, RpcReturnDataTypeArrayTimestampAlias: + if returnAlias { + return RpcReturnDataTypeArrayTimestampAlias, nil + } + return RpcReturnDataTypeArrayTimestamp, nil + case RpcReturnDataTypeArrayTimestampTZ, RpcReturnDataTypeArrayTimestampTZAlias: + if returnAlias { + return RpcReturnDataTypeArrayTimestampTZAlias, nil + } + return RpcReturnDataTypeArrayTimestampTZ, nil + case RpcReturnDataTypeArrayJSON: + return RpcReturnDataTypeArrayJSON, nil + case RpcReturnDataTypeArrayJSONB: + return RpcReturnDataTypeArrayJSONB, nil default: return "", fmt.Errorf("unsupported rpc return type : %s", pCheckType) } @@ -209,6 +357,8 @@ func GetValidRpcReturnNameDecl(pType RpcReturnDataType, returnAlias bool) (strin return "RpcReturnDataTypeReal", nil case RpcReturnDataTypeDoublePreci: return "RpcReturnDataTypeDoublePreci", nil + case RpcReturnDataTypeNumeric: + return "RpcReturnDataTypeNumeric", nil case RpcReturnDataTypeText: return "RpcReturnDataTypeText", nil case RpcReturnDataTypeVarchar, RpcReturnDataTypeVarcharAlias: @@ -240,6 +390,42 @@ func GetValidRpcReturnNameDecl(pType RpcReturnDataType, returnAlias bool) (strin return "RpcReturnDataTypeTable", nil case RpcReturnDataTypeVoid: return "RpcReturnDataTypeVoid", nil + // ARRAY TYPES + case RpcReturnDataTypeArrayInteger: + return "RpcReturnDataTypeArrayInteger", nil + case RpcReturnDataTypeArrayBigInt: + return "RpcReturnDataTypeArrayBigInt", nil + case RpcReturnDataTypeArrayReal: + return "RpcReturnDataTypeArrayReal", nil + case RpcReturnDataTypeArrayDoublePreci: + return "RpcReturnDataTypeArrayDoublePreci", nil + case RpcReturnDataTypeArrayNumeric: + return "RpcReturnDataTypeArrayNumeric", nil + case RpcReturnDataTypeArrayText: + return "RpcReturnDataTypeArrayText", nil + case RpcReturnDataTypeArrayVarchar, RpcReturnDataTypeArrayVarcharAlias: + if returnAlias { + return "RpcReturnDataTypeArrayVarcharAlias", nil + } + return "RpcReturnDataTypeArrayVarchar", nil + case RpcReturnDataTypeArrayBoolean: + return "RpcReturnDataTypeArrayBoolean", nil + case RpcReturnDataTypeArrayBytea: + return "RpcReturnDataTypeArrayBytea", nil + case RpcReturnDataTypeArrayTimestamp: + if returnAlias { + return "RpcReturnDataTypeArrayTimestampAlias", nil + } + return "RpcReturnDataTypeArrayTimestamp", nil + case RpcReturnDataTypeArrayTimestampTZ: + if returnAlias { + return "RpcReturnDataTypeArrayTimestampTZAlias", nil + } + return "RpcReturnDataTypeArrayTimestampTZ", nil + case RpcReturnDataTypeArrayJSON: + return "RpcReturnDataTypeArrayJSON", nil + case RpcReturnDataTypeArrayJSONB: + return "RpcReturnDataTypeArrayJSONB", nil default: return "", fmt.Errorf("unsupported rpc return name declaration : %s", pType) } From c655c0d421c69f625b43817af5b72c8e19aec8b3 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Mon, 22 Jul 2024 13:27:11 +0700 Subject: [PATCH 02/11] add test --- rpc_test.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/rpc_test.go b/rpc_test.go index 3a1a0699..9fe1a8ba 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -106,6 +106,7 @@ func TestRpcParamToGoType(t *testing.T) { {raiden.RpcParamDataTypeBigInt, "int64"}, {raiden.RpcParamDataTypeReal, "float32"}, {raiden.RpcParamDataTypeDoublePreci, "float64"}, + {raiden.RpcParamDataTypeNumeric, "float64"}, {raiden.RpcParamDataTypeText, "string"}, {raiden.RpcParamDataTypeVarchar, "string"}, {raiden.RpcParamDataTypeVarcharAlias, "string"}, @@ -115,6 +116,20 @@ func TestRpcParamToGoType(t *testing.T) { {raiden.RpcParamDataTypeTimestampTZ, "time.Time"}, {raiden.RpcParamDataTypeJSON, "map[string]interface{}"}, {raiden.RpcParamDataTypeJSONB, "map[string]interface{}"}, + {raiden.RpcParamDataTypeArrayInteger, "[]int64"}, + {raiden.RpcParamDataTypeArrayBigInt, "[]int64"}, + {raiden.RpcParamDataTypeArrayReal, "[]float32"}, + {raiden.RpcParamDataTypeArrayDoublePreci, "[]float64"}, + {raiden.RpcParamDataTypeArrayNumeric, "[]float64"}, + {raiden.RpcParamDataTypeArrayText, "[]string"}, + {raiden.RpcParamDataTypeArrayVarchar, "[]string"}, + {raiden.RpcParamDataTypeArrayVarcharAlias, "[]string"}, + {raiden.RpcParamDataTypeArrayBoolean, "[]bool"}, + {raiden.RpcParamDataTypeArrayBytea, "[][]byte"}, + {raiden.RpcParamDataTypeArrayTimestamp, "[]time.Time"}, + {raiden.RpcParamDataTypeArrayTimestampTZ, "[]time.Time"}, + {raiden.RpcParamDataTypeArrayJSON, "[]map[string]interface{}"}, + {raiden.RpcParamDataTypeArrayJSONB, "[]map[string]interface{}"}, } for _, tt := range tests { @@ -133,11 +148,22 @@ func TestGetValidRpcParamType(t *testing.T) { {"bigint", false, raiden.RpcParamDataTypeBigInt, false}, {"real", false, raiden.RpcParamDataTypeReal, false}, {"double precision", false, raiden.RpcParamDataTypeDoublePreci, false}, + {"numeric", false, raiden.RpcParamDataTypeNumeric, false}, {"varchar", false, raiden.RpcParamDataTypeVarchar, false}, {"varchar", true, raiden.RpcParamDataTypeVarcharAlias, false}, {"boolean", true, raiden.RpcParamDataTypeBoolean, false}, {"bytea", true, raiden.RpcParamDataTypeBytea, false}, {"timestamp", true, raiden.RpcParamDataTypeTimestampAlias, false}, + {"integer[]", false, raiden.RpcParamDataTypeArrayInteger, false}, + {"bigint[]", false, raiden.RpcParamDataTypeArrayBigInt, false}, + {"real[]", false, raiden.RpcParamDataTypeArrayReal, false}, + {"double precision[]", false, raiden.RpcParamDataTypeArrayDoublePreci, false}, + {"numeric[]", false, raiden.RpcParamDataTypeArrayNumeric, false}, + {"varchar[]", false, raiden.RpcParamDataTypeArrayVarchar, false}, + {"varchar[]", true, raiden.RpcParamDataTypeArrayVarcharAlias, false}, + {"boolean[]", true, raiden.RpcParamDataTypeArrayBoolean, false}, + {"bytea[]", true, raiden.RpcParamDataTypeArrayBytea, false}, + {"timestamp[]", true, raiden.RpcParamDataTypeArrayTimestampAlias, false}, {"unsupported", false, "", true}, } @@ -161,6 +187,7 @@ func TestRpcReturnToGoType(t *testing.T) { {raiden.RpcReturnDataTypeBigInt, "int64"}, {raiden.RpcReturnDataTypeReal, "float32"}, {raiden.RpcReturnDataTypeDoublePreci, "float64"}, + {raiden.RpcReturnDataTypeNumeric, "float64"}, {raiden.RpcReturnDataTypeText, "string"}, {raiden.RpcReturnDataTypeVarchar, "string"}, {raiden.RpcReturnDataTypeBoolean, "bool"}, @@ -169,6 +196,19 @@ func TestRpcReturnToGoType(t *testing.T) { {raiden.RpcReturnDataTypeTimestampTZ, "time.Time"}, {raiden.RpcReturnDataTypeJSON, "map[string]interface{}"}, {raiden.RpcReturnDataTypeJSONB, "map[string]interface{}"}, + {raiden.RpcReturnDataTypeArrayInteger, "[]int64"}, + {raiden.RpcReturnDataTypeArrayBigInt, "[]int64"}, + {raiden.RpcReturnDataTypeArrayReal, "[]float32"}, + {raiden.RpcReturnDataTypeArrayDoublePreci, "[]float64"}, + {raiden.RpcReturnDataTypeArrayNumeric, "[]float64"}, + {raiden.RpcReturnDataTypeArrayText, "[]string"}, + {raiden.RpcReturnDataTypeArrayVarchar, "[]string"}, + {raiden.RpcReturnDataTypeArrayBoolean, "[]bool"}, + {raiden.RpcReturnDataTypeArrayBytea, "[][]byte"}, + {raiden.RpcReturnDataTypeArrayTimestamp, "[]time.Time"}, + {raiden.RpcReturnDataTypeArrayTimestampTZ, "[]time.Time"}, + {raiden.RpcReturnDataTypeArrayJSON, "[]map[string]interface{}"}, + {raiden.RpcReturnDataTypeArrayJSONB, "[]map[string]interface{}"}, } for _, tt := range tests { @@ -192,6 +232,15 @@ func TestGetValidRpcReturnType(t *testing.T) { {"boolean", true, raiden.RpcReturnDataTypeBoolean, false}, {"bytea", true, raiden.RpcReturnDataTypeBytea, false}, {"timestamp", true, raiden.RpcReturnDataTypeTimestampAlias, false}, + {"integer[]", false, raiden.RpcReturnDataTypeArrayInteger, false}, + {"bigint[]", false, raiden.RpcReturnDataTypeArrayBigInt, false}, + {"real[]", false, raiden.RpcReturnDataTypeArrayReal, false}, + {"double precision[]", false, raiden.RpcReturnDataTypeArrayDoublePreci, false}, + {"varchar[]", false, raiden.RpcReturnDataTypeArrayVarchar, false}, + {"varchar[]", true, raiden.RpcReturnDataTypeArrayVarcharAlias, false}, + {"boolean[]", true, raiden.RpcReturnDataTypeArrayBoolean, false}, + {"bytea[]", true, raiden.RpcReturnDataTypeArrayBytea, false}, + {"timestamp[]", true, raiden.RpcReturnDataTypeArrayTimestampAlias, false}, {"unsupported", false, "", true}, } From 67d4971e379b490fe0f54ff507f682d6c2db5934 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Mon, 22 Jul 2024 15:04:54 +0700 Subject: [PATCH 03/11] improve test coverage --- rpc_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/rpc_test.go b/rpc_test.go index 9fe1a8ba..4138a937 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -151,9 +151,15 @@ func TestGetValidRpcParamType(t *testing.T) { {"numeric", false, raiden.RpcParamDataTypeNumeric, false}, {"varchar", false, raiden.RpcParamDataTypeVarchar, false}, {"varchar", true, raiden.RpcParamDataTypeVarcharAlias, false}, + {"text", false, raiden.RpcParamDataTypeText, false}, {"boolean", true, raiden.RpcParamDataTypeBoolean, false}, {"bytea", true, raiden.RpcParamDataTypeBytea, false}, {"timestamp", true, raiden.RpcParamDataTypeTimestampAlias, false}, + {"timestamp without time zone", false, raiden.RpcParamDataTypeTimestamp, false}, + {"timestampz", true, raiden.RpcParamDataTypeTimestampTZAlias, false}, + {"timestamp with time zone", false, raiden.RpcParamDataTypeTimestampTZ, false}, + {"json", false, raiden.RpcParamDataTypeJSON, false}, + {"jsonb", false, raiden.RpcParamDataTypeJSONB, false}, {"integer[]", false, raiden.RpcParamDataTypeArrayInteger, false}, {"bigint[]", false, raiden.RpcParamDataTypeArrayBigInt, false}, {"real[]", false, raiden.RpcParamDataTypeArrayReal, false}, @@ -161,9 +167,15 @@ func TestGetValidRpcParamType(t *testing.T) { {"numeric[]", false, raiden.RpcParamDataTypeArrayNumeric, false}, {"varchar[]", false, raiden.RpcParamDataTypeArrayVarchar, false}, {"varchar[]", true, raiden.RpcParamDataTypeArrayVarcharAlias, false}, + {"text[]", false, raiden.RpcParamDataTypeArrayText, false}, {"boolean[]", true, raiden.RpcParamDataTypeArrayBoolean, false}, {"bytea[]", true, raiden.RpcParamDataTypeArrayBytea, false}, {"timestamp[]", true, raiden.RpcParamDataTypeArrayTimestampAlias, false}, + {"timestamp without time zone[]", false, raiden.RpcParamDataTypeArrayTimestamp, false}, + {"timestampz[]", true, raiden.RpcParamDataTypeArrayTimestampTZAlias, false}, + {"timestamp with time zone[]", false, raiden.RpcParamDataTypeArrayTimestampTZ, false}, + {"json[]", false, raiden.RpcParamDataTypeArrayJSON, false}, + {"jsonb[]", false, raiden.RpcParamDataTypeArrayJSONB, false}, {"unsupported", false, "", true}, } @@ -227,20 +239,30 @@ func TestGetValidRpcReturnType(t *testing.T) { {"bigint", false, raiden.RpcReturnDataTypeBigInt, false}, {"real", false, raiden.RpcReturnDataTypeReal, false}, {"double precision", false, raiden.RpcReturnDataTypeDoublePreci, false}, + {"numeric", false, raiden.RpcReturnDataTypeNumeric, false}, {"varchar", false, raiden.RpcReturnDataTypeVarchar, false}, {"varchar", true, raiden.RpcReturnDataTypeVarcharAlias, false}, + {"text", false, raiden.RpcReturnDataTypeText, false}, {"boolean", true, raiden.RpcReturnDataTypeBoolean, false}, {"bytea", true, raiden.RpcReturnDataTypeBytea, false}, {"timestamp", true, raiden.RpcReturnDataTypeTimestampAlias, false}, + {"timestamp without time zone", false, raiden.RpcReturnDataTypeTimestamp, false}, + {"timestampz", true, raiden.RpcReturnDataTypeTimestampTZAlias, false}, + {"timestamp with time zone", false, raiden.RpcReturnDataTypeTimestampTZ, false}, {"integer[]", false, raiden.RpcReturnDataTypeArrayInteger, false}, {"bigint[]", false, raiden.RpcReturnDataTypeArrayBigInt, false}, {"real[]", false, raiden.RpcReturnDataTypeArrayReal, false}, {"double precision[]", false, raiden.RpcReturnDataTypeArrayDoublePreci, false}, + {"numeric[]", false, raiden.RpcReturnDataTypeArrayNumeric, false}, {"varchar[]", false, raiden.RpcReturnDataTypeArrayVarchar, false}, {"varchar[]", true, raiden.RpcReturnDataTypeArrayVarcharAlias, false}, + {"text[]", false, raiden.RpcReturnDataTypeArrayText, false}, {"boolean[]", true, raiden.RpcReturnDataTypeArrayBoolean, false}, {"bytea[]", true, raiden.RpcReturnDataTypeArrayBytea, false}, {"timestamp[]", true, raiden.RpcReturnDataTypeArrayTimestampAlias, false}, + {"timestamp without time zone[]", false, raiden.RpcReturnDataTypeArrayTimestamp, false}, + {"timestampz[]", true, raiden.RpcReturnDataTypeArrayTimestampTZAlias, false}, + {"timestamp with time zone[]", false, raiden.RpcReturnDataTypeArrayTimestampTZ, false}, {"unsupported", false, "", true}, } From 2409d6886289b7eabf1712174ca21303ab061966 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Fri, 26 Jul 2024 02:18:03 +0700 Subject: [PATCH 04/11] ignore typecast symbol --- pkg/state/rpc.go | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/pkg/state/rpc.go b/pkg/state/rpc.go index 9c534cb8..683f956d 100644 --- a/pkg/state/rpc.go +++ b/pkg/state/rpc.go @@ -62,13 +62,28 @@ func BindRpcFunction(rpc raiden.Rpc, fn *objects.Function) (err error) { fn.CompleteStatement = rpc.GetCompleteStmt() // validate definition query - matches := regexp.MustCompile(`:\w+`).FindAllString(fn.CompleteStatement, -1) - if len(matches) > 0 { + allMatches := regexp.MustCompile(`:\w+`).FindAllString(fn.CompleteStatement, -1) + allExcludes := regexp.MustCompile(`::\w+`).FindAllString(fn.CompleteStatement, -1) + + // Filter out double colon string that work as postgre typecast + validMatches := []string{} + excludeSet := make(map[string]bool) + for _, exclude := range allExcludes { + excludeSet[exclude] = true + } + + for _, match := range allMatches { + if !excludeSet[fmt.Sprintf(":%s", match)] { + validMatches = append(validMatches, match) + } + } + + if len(validMatches) > 0 { var errMsg string - if len(matches) > 1 { - errMsg = fmt.Sprintf("rpc %q is invalid, There are %q keys that are not mapped with any parameters or models.", rpc.GetName(), strings.Join(matches, ",")) + if len(validMatches) > 1 { + errMsg = fmt.Sprintf("rpc %q is invalid, There are %q keys that are not mapped with any parameters or models.", rpc.GetName(), strings.Join(validMatches, ",")) } else { - errMsg = fmt.Sprintf("rpc %q is invalid, There is %q key that is not mapped with any parameters or models.", rpc.GetName(), matches[0]) + errMsg = fmt.Sprintf("rpc %q is invalid, There is %q key that is not mapped with any parameters or models.", rpc.GetName(), validMatches[0]) } return errors.New(errMsg) } @@ -88,3 +103,19 @@ func (er ExtractRpcResult) ToDeleteFlatMap() map[string]*objects.Function { return mapData } + +// Helper function to check if the index is inside a string literal +func isInsideStringLiteral(s string, index int) bool { + inSingleQuote := false + inDoubleQuote := false + + for i := 0; i < index; i++ { + if s[i] == '\'' && !inDoubleQuote { + inSingleQuote = !inSingleQuote + } + if s[i] == '"' && !inSingleQuote { + inDoubleQuote = !inDoubleQuote + } + } + return inSingleQuote || inDoubleQuote +} From d588771a31de02d9a7b1f5d5286eed6424d21cf5 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Fri, 26 Jul 2024 02:18:50 +0700 Subject: [PATCH 05/11] fix duplicate --- rpc.go | 1 - 1 file changed, 1 deletion(-) diff --git a/rpc.go b/rpc.go index c2aa366a..2a6984f1 100644 --- a/rpc.go +++ b/rpc.go @@ -30,7 +30,6 @@ const ( RpcParamDataTypeBigInt RpcParamDataType = "BIGINT" RpcParamDataTypeReal RpcParamDataType = "REAL" RpcParamDataTypeDoublePreci RpcParamDataType = "DOUBLE PRECISION" - RpcParamDataTypeNumeric RpcParamDataType = "NUMERIC" RpcParamDataTypeText RpcParamDataType = "TEXT" RpcParamDataTypeVarchar RpcParamDataType = "CHARACTER VARYING" RpcParamDataTypeVarcharAlias RpcParamDataType = "VARCHAR" From 604bdacd252ac22f8bfc338b5be9fbb1b3d1f35f Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Fri, 26 Jul 2024 02:19:06 +0700 Subject: [PATCH 06/11] allow redirect for GET method --- pkg/supabase/client/client.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/supabase/client/client.go b/pkg/supabase/client/client.go index b12d5236..00d2b6bc 100644 --- a/pkg/supabase/client/client.go +++ b/pkg/supabase/client/client.go @@ -113,16 +113,20 @@ func SendRequest(method string, url string, body []byte, timeout time.Duration, statusCode := resp.StatusCode() if !strings.HasPrefix(strconv.Itoa(statusCode), "2") { - err = fmt.Errorf("invalid HTTP response code: %d", statusCode) - if resp.Body() != nil && len(resp.Body()) > 0 { - Logger.Error(string(resp.Body())) - sendErr := ReqError{ - Message: err.Error(), - Body: resp.Body(), + // Allow redirect for GET Method + if method != fasthttp.MethodGet && !strings.HasPrefix(strconv.Itoa(statusCode), "3") { + err = fmt.Errorf("invalid HTTP response code: %d", statusCode) + if resp.Body() != nil && len(resp.Body()) > 0 { + Logger.Error(string(resp.Body())) + sendErr := ReqError{ + Message: err.Error(), + Body: resp.Body(), + } + return nil, sendErr } - return nil, sendErr + return nil, err } - return nil, err + } if resInterceptor != nil { From e03442ad94d675830f188139a74e3fb6b7090b19 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Mon, 5 Aug 2024 18:00:15 +0700 Subject: [PATCH 07/11] remove unused --- pkg/state/rpc.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pkg/state/rpc.go b/pkg/state/rpc.go index 683f956d..5c16a098 100644 --- a/pkg/state/rpc.go +++ b/pkg/state/rpc.go @@ -103,19 +103,3 @@ func (er ExtractRpcResult) ToDeleteFlatMap() map[string]*objects.Function { return mapData } - -// Helper function to check if the index is inside a string literal -func isInsideStringLiteral(s string, index int) bool { - inSingleQuote := false - inDoubleQuote := false - - for i := 0; i < index; i++ { - if s[i] == '\'' && !inDoubleQuote { - inSingleQuote = !inSingleQuote - } - if s[i] == '"' && !inSingleQuote { - inDoubleQuote = !inDoubleQuote - } - } - return inSingleQuote || inDoubleQuote -} From cc6141f408290e633df1fd68fd8097aedb6764d3 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Wed, 28 Aug 2024 17:03:56 +0700 Subject: [PATCH 08/11] configurable server max request body size --- config.go | 49 +++++++++++++++++++++++++++---------------------- server.go | 8 +++++--- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/config.go b/config.go index 61e9c61c..f412ba7d 100644 --- a/config.go +++ b/config.go @@ -16,28 +16,29 @@ const ( ) type Config struct { - AccessToken string `mapstructure:"ACCESS_TOKEN"` - AnonKey string `mapstructure:"ANON_KEY"` - BreakerEnable bool `mapstructure:"BREAKER_ENABLE"` - CorsAllowedOrigins string `mapstructure:"CORS_ALLOWED_ORIGINS"` - CorsAllowedMethods string `mapstructure:"CORS_ALLOWED_METHODS"` - CorsAllowedHeaders string `mapstructure:"CORS_ALLOWED_HEADERS"` - CorsAllowCredentials bool `mapstructure:"CORS_ALLOWED_CREDENTIALS"` - DeploymentTarget DeploymentTarget `mapstructure:"DEPLOYMENT_TARGET"` - Environment string `mapstructure:"ENVIRONMENT"` - ProjectId string `mapstructure:"PROJECT_ID"` - ProjectName string `mapstructure:"PROJECT_NAME"` - ServiceKey string `mapstructure:"SERVICE_KEY"` - ServerHost string `mapstructure:"SERVER_HOST"` - ServerPort string `mapstructure:"SERVER_PORT"` - SupabaseApiUrl string `mapstructure:"SUPABASE_API_URL"` - SupabaseApiBasePath string `mapstructure:"SUPABASE_API_BASE_PATH"` - SupabasePublicUrl string `mapstructure:"SUPABASE_PUBLIC_URL"` - ScheduleStatus ScheduleStatus `mapstructure:"SCHEDULE_STATUS"` - TraceEnable bool `mapstructure:"TRACE_ENABLE"` - TraceCollector string `mapstructure:"TRACE_COLLECTOR"` - TraceCollectorEndpoint string `mapstructure:"TRACE_COLLECTOR_ENDPOINT"` - Version string `mapstructure:"VERSION"` + AccessToken string `mapstructure:"ACCESS_TOKEN"` + AnonKey string `mapstructure:"ANON_KEY"` + BreakerEnable bool `mapstructure:"BREAKER_ENABLE"` + CorsAllowedOrigins string `mapstructure:"CORS_ALLOWED_ORIGINS"` + CorsAllowedMethods string `mapstructure:"CORS_ALLOWED_METHODS"` + CorsAllowedHeaders string `mapstructure:"CORS_ALLOWED_HEADERS"` + CorsAllowCredentials bool `mapstructure:"CORS_ALLOWED_CREDENTIALS"` + DeploymentTarget DeploymentTarget `mapstructure:"DEPLOYMENT_TARGET"` + Environment string `mapstructure:"ENVIRONMENT"` + ProjectId string `mapstructure:"PROJECT_ID"` + ProjectName string `mapstructure:"PROJECT_NAME"` + ServiceKey string `mapstructure:"SERVICE_KEY"` + ServerHost string `mapstructure:"SERVER_HOST"` + ServerPort string `mapstructure:"SERVER_PORT"` + SupabaseApiUrl string `mapstructure:"SUPABASE_API_URL"` + SupabaseApiBasePath string `mapstructure:"SUPABASE_API_BASE_PATH"` + SupabasePublicUrl string `mapstructure:"SUPABASE_PUBLIC_URL"` + ScheduleStatus ScheduleStatus `mapstructure:"SCHEDULE_STATUS"` + TraceEnable bool `mapstructure:"TRACE_ENABLE"` + TraceCollector string `mapstructure:"TRACE_COLLECTOR"` + TraceCollectorEndpoint string `mapstructure:"TRACE_COLLECTOR_ENDPOINT"` + Version string `mapstructure:"VERSION"` + MaxServerRequestBodySize int `mapstructure:"MAX_SERVER_REQUEST_BODY_SIZE"` } // The function `LoadConfig` loads a configuration file based on the provided path or uses default @@ -93,6 +94,10 @@ func LoadConfig(path *string) (*Config, error) { config.SupabaseApiBasePath = "/" + config.SupabaseApiBasePath } + if config.MaxServerRequestBodySize == 0 { + config.MaxServerRequestBodySize = 8 * 1024 * 1024 // Default 8 MB + } + return &config, nil } diff --git a/server.go b/server.go index 7f35b962..144d462f 100644 --- a/server.go +++ b/server.go @@ -34,9 +34,11 @@ type Server struct { func NewServer(config *Config) *Server { return &Server{ - Config: config, - Router: NewRouter(config), - HttpServer: &fasthttp.Server{}, + Config: config, + Router: NewRouter(config), + HttpServer: &fasthttp.Server{ + MaxRequestBodySize: config.MaxServerRequestBodySize, + }, } } From 1895b013df994a32ede4f8c4f2ead5479d1030e3 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Wed, 16 Oct 2024 13:30:20 +0700 Subject: [PATCH 09/11] fix typo --- rpc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc.go b/rpc.go index 5abb7143..72289592 100644 --- a/rpc.go +++ b/rpc.go @@ -227,7 +227,7 @@ func GetValidRpcParamType(pType string, returnAlias bool) (RpcParamDataType, err case RpcParamDataTypeArrayJSONB: return RpcParamDataTypeArrayJSONB, nil case RpcParamDataTypeArrayUuid: - return RpcParamDataTypeArrayUuid + return RpcParamDataTypeArrayUuid, nil default: return "", fmt.Errorf("unsupported rpc param type : %s", pCheckType) } From 3fb4c1c53e3236102b5f415b3254fe0768630efd Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Wed, 16 Oct 2024 16:02:06 +0700 Subject: [PATCH 10/11] configurable max server read buffer size --- config.go | 5 +++++ pkg/generator/config.go | 5 +++++ server.go | 1 + 3 files changed, 11 insertions(+) diff --git a/config.go b/config.go index 1f609057..e76ba0b5 100644 --- a/config.go +++ b/config.go @@ -39,6 +39,7 @@ type Config struct { TraceCollectorEndpoint string `mapstructure:"TRACE_COLLECTOR_ENDPOINT"` Version string `mapstructure:"VERSION"` MaxServerRequestBodySize int `mapstructure:"MAX_SERVER_REQUEST_BODY_SIZE"` + MaxServerReadBufferSize int `mapstructure:"MAX_SERVER_READ_BUFFER_SIZE"` } // The function `LoadConfig` loads a configuration file based on the provided path or uses default @@ -98,6 +99,10 @@ func LoadConfig(path *string) (*Config, error) { config.MaxServerRequestBodySize = 8 * 1024 * 1024 // Default Max: 8 MB } + if config.MaxServerReadBufferSize == 0 { + config.MaxServerReadBufferSize = 8 * 1024 * 1024 // Default Max: 8 MB + } + return &config, nil } diff --git a/pkg/generator/config.go b/pkg/generator/config.go index 6d3c79cc..4457397c 100644 --- a/pkg/generator/config.go +++ b/pkg/generator/config.go @@ -44,6 +44,7 @@ TRACE_COLLECTOR: {{ .TraceCollector}} TRACE_COLLECTOR_ENDPOINT: {{ .TraceCollectorEndpoint }} MAX_SERVER_REQUEST_BODY_SIZE: {{ .MaxServerRequestBodySize }} +MAX_SERVER_READ_BUFFER_SIZE: {{ .MaxServerReadBufferSize }} CORS_ALLOWED_ORIGINS: CORS_ALLOWED_METHODS: @@ -75,6 +76,10 @@ func GenerateConfig(basePath string, config *raiden.Config, generateFn GenerateF config.MaxServerRequestBodySize = 8 * 1024 * 1024 } + if config.MaxServerReadBufferSize == 0 { + config.MaxServerReadBufferSize = 8 * 1024 * 1024 + } + input := GenerateInput{ BindData: config, Template: ConfigTemplate, diff --git a/server.go b/server.go index 144d462f..99893d3f 100644 --- a/server.go +++ b/server.go @@ -38,6 +38,7 @@ func NewServer(config *Config) *Server { Router: NewRouter(config), HttpServer: &fasthttp.Server{ MaxRequestBodySize: config.MaxServerRequestBodySize, + ReadBufferSize: config.MaxServerReadBufferSize, }, } } From 3955790c449aa965f4d3ffcd2534d0b0f5cf51e4 Mon Sep 17 00:00:00 2001 From: Dhanial Rizky Wira Putra Date: Wed, 16 Oct 2024 16:13:30 +0700 Subject: [PATCH 11/11] increase client read buffer size --- pkg/supabase/client/client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/supabase/client/client.go b/pkg/supabase/client/client.go index 00d2b6bc..69d5884c 100644 --- a/pkg/supabase/client/client.go +++ b/pkg/supabase/client/client.go @@ -57,6 +57,7 @@ func getClient() Client { Concurrency: 4096, DNSCacheDuration: time.Hour, }).Dial, + ReadBufferSize: 8192, } }