@@ -4,8 +4,10 @@ import (
44 "context"
55 "time"
66
7+ "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Formats"
78 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Table"
89
10+ "github.com/ydb-platform/ydb-go-sdk/v3/internal/allocator"
911 "github.com/ydb-platform/ydb-go-sdk/v3/internal/closer"
1012 "github.com/ydb-platform/ydb-go-sdk/v3/internal/params"
1113 "github.com/ydb-platform/ydb-go-sdk/v3/internal/tx"
@@ -68,6 +70,12 @@ type Client interface {
6870 // If op TxOperation return non nil - transaction will be rollback
6971 // Warning: if context without deadline or cancellation func than DoTx can run indefinitely
7072 DoTx (ctx context.Context , op TxOperation , opts ... Option ) error
73+
74+ // BulkUpsert upserts a batch of rows non-transactionally.
75+ //
76+ // Returns success only when all rows were successfully upserted. In case of an error some rows might
77+ // be upserted and some might not.
78+ BulkUpsert (ctx context.Context , table string , data BulkUpsertData , opts ... Option ) error
7179}
7280
7381type SessionStatus = string
@@ -179,6 +187,7 @@ type Session interface {
179187 opts ... options.ExecuteScanQueryOption ,
180188 ) (_ result.StreamResult , err error )
181189
190+ // Deprecated: use Client instance instead.
182191 BulkUpsert (
183192 ctx context.Context ,
184193 table string ,
@@ -578,3 +587,170 @@ func (opt traceOption) ApplyTableOption(opts *Options) {
578587func WithTrace (t trace.Table ) traceOption { //nolint:gocritic
579588 return traceOption {t : & t }
580589}
590+
591+ type BulkUpsertData interface {
592+ ToYDB (a * allocator.Allocator , tableName string ) (* Ydb_Table.BulkUpsertRequest , error )
593+ }
594+
595+ type bulkUpsertRows struct {
596+ rows value.Value
597+ }
598+
599+ func (data bulkUpsertRows ) ToYDB (a * allocator.Allocator , tableName string ) (* Ydb_Table.BulkUpsertRequest , error ) {
600+ return & Ydb_Table.BulkUpsertRequest {
601+ Table : tableName ,
602+ Rows : value .ToYDB (data .rows , a ),
603+ }, nil
604+ }
605+
606+ func BulkUpsertDataRows (rows value.Value ) bulkUpsertRows {
607+ return bulkUpsertRows {
608+ rows : rows ,
609+ }
610+ }
611+
612+ type bulkUpsertCsv struct {
613+ data []byte
614+ opts []csvFormatOption
615+ }
616+
617+ type csvFormatOption interface {
618+ applyCsvFormatOption (dataFormat * Ydb_Table.BulkUpsertRequest_CsvSettings ) (err error )
619+ }
620+
621+ func (data bulkUpsertCsv ) ToYDB (a * allocator.Allocator , tableName string ) (* Ydb_Table.BulkUpsertRequest , error ) {
622+ var (
623+ request = & Ydb_Table.BulkUpsertRequest {
624+ Table : tableName ,
625+ Data : data .data ,
626+ }
627+ dataFormat = & Ydb_Table.BulkUpsertRequest_CsvSettings {
628+ CsvSettings : & Ydb_Formats.CsvSettings {},
629+ }
630+ )
631+
632+ for _ , opt := range data .opts {
633+ if opt != nil {
634+ if err := opt .applyCsvFormatOption (dataFormat ); err != nil {
635+ return nil , err
636+ }
637+ }
638+ }
639+
640+ request .DataFormat = dataFormat
641+
642+ return request , nil
643+ }
644+
645+ func BulkUpsertDataCsv (data []byte , opts ... csvFormatOption ) bulkUpsertCsv {
646+ return bulkUpsertCsv {
647+ data : data ,
648+ opts : opts ,
649+ }
650+ }
651+
652+ type csvHeaderOption struct {}
653+
654+ func (opt * csvHeaderOption ) applyCsvFormatOption (dataFormat * Ydb_Table.BulkUpsertRequest_CsvSettings ) error {
655+ dataFormat .CsvSettings .Header = true
656+
657+ return nil
658+ }
659+
660+ // First not skipped line is a CSV header (list of column names).
661+ func WithCsvHeader () csvFormatOption {
662+ return & csvHeaderOption {}
663+ }
664+
665+ type csvNullValueOption []byte
666+
667+ func (nullValue csvNullValueOption ) applyCsvFormatOption (dataFormat * Ydb_Table.BulkUpsertRequest_CsvSettings ) error {
668+ dataFormat .CsvSettings .NullValue = nullValue
669+
670+ return nil
671+ }
672+
673+ // String value that would be interpreted as NULL.
674+ func WithCsvNullValue (value []byte ) csvFormatOption {
675+ return csvNullValueOption (value )
676+ }
677+
678+ type csvDelimiterOption []byte
679+
680+ func (delimeter csvDelimiterOption ) applyCsvFormatOption (dataFormat * Ydb_Table.BulkUpsertRequest_CsvSettings ) error {
681+ dataFormat .CsvSettings .Delimiter = delimeter
682+
683+ return nil
684+ }
685+
686+ // Fields delimiter in CSV file. It's "," if not set.
687+ func WithCsvDelimiter (value []byte ) csvFormatOption {
688+ return csvDelimiterOption (value )
689+ }
690+
691+ type csvSkipRowsOption uint32
692+
693+ func (skipRows csvSkipRowsOption ) applyCsvFormatOption (dataFormat * Ydb_Table.BulkUpsertRequest_CsvSettings ) error {
694+ dataFormat .CsvSettings .SkipRows = uint32 (skipRows )
695+
696+ return nil
697+ }
698+
699+ // Number of rows to skip before CSV data. It should be present only in the first upsert of CSV file.
700+ func WithCsvSkipRows (skipRows uint32 ) csvFormatOption {
701+ return csvSkipRowsOption (skipRows )
702+ }
703+
704+ type bulkUpsertArrow struct {
705+ data []byte
706+ opts []arrowFormatOption
707+ }
708+
709+ type arrowFormatOption interface {
710+ applyArrowFormatOption (req * Ydb_Table.BulkUpsertRequest_ArrowBatchSettings ) (err error )
711+ }
712+
713+ func (data bulkUpsertArrow ) ToYDB (a * allocator.Allocator , tableName string ) (* Ydb_Table.BulkUpsertRequest , error ) {
714+ var (
715+ request = & Ydb_Table.BulkUpsertRequest {
716+ Table : tableName ,
717+ Data : data .data ,
718+ }
719+ dataFormat = & Ydb_Table.BulkUpsertRequest_ArrowBatchSettings {
720+ ArrowBatchSettings : & Ydb_Formats.ArrowBatchSettings {},
721+ }
722+ )
723+
724+ for _ , opt := range data .opts {
725+ if opt != nil {
726+ if err := opt .applyArrowFormatOption (dataFormat ); err != nil {
727+ return nil , err
728+ }
729+ }
730+ }
731+
732+ request .DataFormat = dataFormat
733+
734+ return request , nil
735+ }
736+
737+ func BulkUpsertDataArrow (data []byte , opts ... arrowFormatOption ) bulkUpsertArrow {
738+ return bulkUpsertArrow {
739+ data : data ,
740+ opts : opts ,
741+ }
742+ }
743+
744+ type arrowSchemaOption []byte
745+
746+ func (schema arrowSchemaOption ) applyArrowFormatOption (
747+ dataFormat * Ydb_Table.BulkUpsertRequest_ArrowBatchSettings ,
748+ ) error {
749+ dataFormat .ArrowBatchSettings .Schema = schema
750+
751+ return nil
752+ }
753+
754+ func WithArrowSchema (schema []byte ) arrowFormatOption {
755+ return arrowSchemaOption (schema )
756+ }
0 commit comments