Skip to content

Commit bb1ee3b

Browse files
authored
Merge pull request #1124 from ydb-platform/add-pg-type
Add PG type as parameter support
2 parents e6d6c97 + 03bff34 commit bb1ee3b

File tree

9 files changed

+208
-0
lines changed

9 files changed

+208
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
* Added `ydb.ParamsBuilder().Pg().{Value,Int4,Int8,Unknown}` for postgres arguments
2+
13
## v3.57.4
24
* Added client pid to each gRPC requests to YDB over header `x-ydb-client-pid`
35
* Added `ydb.WithApplicationName` option

internal/params/builder_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/ydb-platform/ydb-go-genproto/protos/Ydb"
1010

1111
"github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator"
12+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/pg"
1213
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
1314
)
1415

@@ -450,6 +451,69 @@ func TestBuilder(t *testing.T) {
450451
},
451452
},
452453
},
454+
{
455+
name: xtest.CurrentFileLine(),
456+
builder: Builder{}.
457+
Param("$x").
458+
Pg().Unknown("123").
459+
Build(),
460+
params: map[string]*Ydb.TypedValue{
461+
"$x": {
462+
Type: &Ydb.Type{
463+
Type: &Ydb.Type_PgType{
464+
PgType: &Ydb.PgType{
465+
Oid: pg.OIDUnknown,
466+
},
467+
},
468+
},
469+
Value: &Ydb.Value{
470+
Value: &Ydb.Value_TextValue{TextValue: "123"},
471+
},
472+
},
473+
},
474+
},
475+
{
476+
name: xtest.CurrentFileLine(),
477+
builder: Builder{}.
478+
Param("$x").
479+
Pg().Int4(123).
480+
Build(),
481+
params: map[string]*Ydb.TypedValue{
482+
"$x": {
483+
Type: &Ydb.Type{
484+
Type: &Ydb.Type_PgType{
485+
PgType: &Ydb.PgType{
486+
Oid: pg.OIDInt4,
487+
},
488+
},
489+
},
490+
Value: &Ydb.Value{
491+
Value: &Ydb.Value_TextValue{TextValue: "123"},
492+
},
493+
},
494+
},
495+
},
496+
{
497+
name: xtest.CurrentFileLine(),
498+
builder: Builder{}.
499+
Param("$x").
500+
Pg().Int8(123).
501+
Build(),
502+
params: map[string]*Ydb.TypedValue{
503+
"$x": {
504+
Type: &Ydb.Type{
505+
Type: &Ydb.Type_PgType{
506+
PgType: &Ydb.PgType{
507+
Oid: pg.OIDInt8,
508+
},
509+
},
510+
},
511+
Value: &Ydb.Value{
512+
Value: &Ydb.Value_TextValue{TextValue: "123"},
513+
},
514+
},
515+
},
516+
},
453517
} {
454518
t.Run(tt.name, func(t *testing.T) {
455519
a := allocator.New()

internal/params/parameters.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ func (p *Parameter) List() *list {
109109
}
110110
}
111111

112+
func (p *Parameter) Pg() pgParam {
113+
return pgParam{p}
114+
}
115+
112116
func (p *Parameter) Set() *set {
113117
return &set{
114118
parent: p.parent,

internal/params/pg.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package params
2+
3+
import (
4+
"strconv"
5+
6+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/pg"
7+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/value"
8+
)
9+
10+
type pgParam struct {
11+
param *Parameter
12+
}
13+
14+
func (p pgParam) Unknown(val string) Builder {
15+
return p.Value(pg.OIDUnknown, val)
16+
}
17+
18+
func (p pgParam) Value(oid uint32, val string) Builder {
19+
p.param.value = value.PgValue(oid, val)
20+
p.param.parent.params = append(p.param.parent.params, p.param)
21+
22+
return p.param.parent
23+
}
24+
25+
func (p pgParam) Int4(val int32) Builder {
26+
return p.Value(pg.OIDInt4, strconv.FormatInt(int64(val), 10))
27+
}
28+
29+
func (p pgParam) Int8(val int64) Builder {
30+
return p.Value(pg.OIDInt8, strconv.FormatInt(val, 10))
31+
}

internal/pg/pgconst.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package pg
2+
3+
const (
4+
// https://github.com/postgres/postgres/blob/master/src/include/catalog/pg_type.dat
5+
6+
OIDInt4 = 23
7+
OIDInt8 = 20
8+
OIDUnknown = 705
9+
)

internal/types/types.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ func TypeFromYDB(x *Ydb.Type) Type {
7272
case *Ydb.Type_NullType:
7373
return NewNull()
7474

75+
case *Ydb.Type_PgType:
76+
return &PgType{
77+
OID: x.GetPgType().GetOid(),
78+
}
79+
7580
default:
7681
panic("ydb: unknown type")
7782
}
@@ -465,6 +470,37 @@ func NewOptional(t Type) Optional {
465470
}
466471
}
467472

473+
type PgType struct {
474+
OID uint32
475+
}
476+
477+
func (v PgType) String() string {
478+
return v.Yql()
479+
}
480+
481+
func (v PgType) Yql() string {
482+
return "pgunknown"
483+
}
484+
485+
func (v PgType) ToYDB(a *allocator.Allocator) *Ydb.Type {
486+
//nolint:godox
487+
// TODO: make allocator
488+
return &Ydb.Type{Type: &Ydb.Type_PgType{
489+
PgType: &Ydb.PgType{
490+
Oid: v.OID,
491+
},
492+
}}
493+
}
494+
495+
func (v PgType) equalsTo(rhs Type) bool {
496+
vv, ok := rhs.(PgType)
497+
if !ok {
498+
return false
499+
}
500+
501+
return v.OID == vv.OID
502+
}
503+
468504
type Primitive uint
469505

470506
func (v Primitive) String() string {

internal/types/types_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/require"
7+
8+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/pg"
79
)
810

911
func TestTypeToString(t *testing.T) {
@@ -267,6 +269,10 @@ func TestTypeToString(t *testing.T) {
267269
),
268270
s: "Variant<Bool,Float>",
269271
},
272+
{
273+
t: PgType{OID: pg.OIDUnknown},
274+
s: "pgunknown",
275+
},
270276
} {
271277
t.Run(tt.s, func(t *testing.T) {
272278
if got := tt.t.Yql(); got != tt.s {

internal/value/value.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,14 @@ func fromYDB(t *Ydb.Type, v *Ydb.Value) (Value, error) {
282282
ttt.Tuple,
283283
), nil
284284

285+
case *types.PgType:
286+
return &pgValue{
287+
t: types.PgType{
288+
OID: ttt.OID,
289+
},
290+
val: v.GetTextValue(),
291+
}, nil
292+
285293
default:
286294
return nil, xerrors.WithStackTrace(fmt.Errorf("uncovered type: %T", ttt))
287295
}
@@ -1229,6 +1237,39 @@ func ListValue(items ...Value) *listValue {
12291237
}
12301238
}
12311239

1240+
type pgValue struct {
1241+
t types.PgType
1242+
val string
1243+
}
1244+
1245+
func (v pgValue) castTo(dst interface{}) error {
1246+
return xerrors.WithStackTrace(fmt.Errorf(
1247+
"%w PgType to '%T' destination",
1248+
ErrCannotCast, dst,
1249+
))
1250+
}
1251+
1252+
func (v pgValue) Type() types.Type {
1253+
return v.t
1254+
}
1255+
1256+
func (v pgValue) toYDB(_ *allocator.Allocator) *Ydb.Value {
1257+
//nolint:godox
1258+
// TODO: make allocator
1259+
return &Ydb.Value{
1260+
Value: &Ydb.Value_TextValue{
1261+
TextValue: v.val,
1262+
},
1263+
}
1264+
}
1265+
1266+
func (v pgValue) Yql() string {
1267+
//nolint:godox
1268+
// TODO: call special function for unknown oids
1269+
// https://github.com/ydb-platform/ydb/issues/2706
1270+
return fmt.Sprintf("PgUnknown(%q)", v.val)
1271+
}
1272+
12321273
type setValue struct {
12331274
t types.Type
12341275
items []Value
@@ -1275,6 +1316,15 @@ func (v *setValue) toYDB(a *allocator.Allocator) *Ydb.Value {
12751316
return vvv
12761317
}
12771318

1319+
func PgValue(oid uint32, val string) pgValue {
1320+
return pgValue{
1321+
t: types.PgType{
1322+
OID: oid,
1323+
},
1324+
val: val,
1325+
}
1326+
}
1327+
12781328
func SetValue(items ...Value) *setValue {
12791329
sort.Slice(items, func(i, j int) bool {
12801330
return items[i].Yql() < items[j].Yql()

internal/value/value_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"google.golang.org/protobuf/proto"
1414

1515
"github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator"
16+
"github.com/ydb-platform/ydb-go-sdk/v3/internal/pg"
1617
"github.com/ydb-platform/ydb-go-sdk/v3/internal/types"
1718
"github.com/ydb-platform/ydb-go-sdk/v3/internal/xtest"
1819
)
@@ -176,6 +177,7 @@ func TestToYDBFromYDB(t *testing.T) {
176177
ZeroValue(types.Text),
177178
ZeroValue(types.NewStruct()),
178179
ZeroValue(types.NewTuple()),
180+
PgValue(pg.OIDInt4, "123"),
179181
} {
180182
t.Run(strconv.Itoa(i)+"."+v.Yql(), func(t *testing.T) {
181183
a := allocator.New()
@@ -498,6 +500,10 @@ func TestValueYql(t *testing.T) {
498500
value: YSONValue([]byte("<a=1>[3;%false]")),
499501
literal: `Yson("<a=1>[3;%false]")`,
500502
},
503+
{
504+
value: PgValue(pg.OIDUnknown, "123"),
505+
literal: `PgUnknown("123")`,
506+
},
501507
} {
502508
t.Run(strconv.Itoa(i)+"."+tt.literal, func(t *testing.T) {
503509
require.Equal(t, tt.literal, tt.value.Yql())

0 commit comments

Comments
 (0)