MCPcopy Create free account
hub / github.com/cloudquery/cloudquery / WriteTableBatch

Method WriteTableBatch

plugins/destination/duckdb/client/write.go:137–186  ·  view source on GitHub ↗
(ctx context.Context, name string, msgs message.WriteInserts)

Source from the content-addressed store, hash-verified

135}
136
137func (c *Client) WriteTableBatch(ctx context.Context, name string, msgs message.WriteInserts) error {
138 if len(msgs) == 0 {
139 return nil
140 }
141
142 table := msgs[0].GetTable()
143
144 writeStart := time.Now()
145 tmpFile, err := writeTMPFile(table, msgs)
146 if err != nil {
147 return err
148 }
149 c.logger.Debug().Str("table", table.Name).Str("duration", time.Since(writeStart).String()).Msg("write tmp file")
150 defer os.Remove(tmpFile)
151
152 if len(table.PrimaryKeys()) == 0 {
153 copyStart := time.Now()
154 defer func() {
155 c.logger.Debug().Str("table", table.Name).Str("duration", time.Since(copyStart).String()).Msg("copy file to table")
156 }()
157 return c.copyFromFile(ctx, name, tmpFile, table)
158 }
159
160 tmpTableName := name + strings.ReplaceAll(uuid.New().String(), "-", "_")
161 // we skip constraints here, as copy doesn't allow us to handle conflicts, we handle those during upsert
162 if err := c.createTableIfNotExist(ctx, tmpTableName, table, true); err != nil {
163 return fmt.Errorf("failed to create table %s: %w", tmpTableName, err)
164 }
165 defer func() {
166 e := c.exec(ctx, "drop table "+tmpTableName)
167 if err == nil {
168 // we preserve original error, so update only on nil err
169 err = e
170 }
171 }()
172
173 if err := c.copyFromFile(ctx, tmpTableName, tmpFile, table); err != nil {
174 return fmt.Errorf("failed to copy from file %s: %w", tmpFile, err)
175 }
176
177 // At time of writing (March 2023), duckdb does not support updating list columns.
178 // As a workaround, we delete the row and insert it again. This makes it non-atomic, unfortunately,
179 // but this is unavoidable until support is added to duckdb itself.
180 // See https://github.com/duckdb/duckdb/blob/c5d9afb97bbf0be12216f3b89ae3131afbbc3156/src/storage/table/list_column_data.cpp#L243-L251
181 if containsList(table) {
182 return c.deleteInsert(ctx, tmpTableName, table)
183 }
184
185 return c.upsert(ctx, tmpTableName, table)
186}
187
188func writeTMPFile(table *schema.Table, msgs []*message.WriteInsert) (fileName string, err error) {
189 sc := transformSchemaForWriting(table)

Callers

nothing calls this directly

Calls 9

copyFromFileMethod · 0.95
createTableIfNotExistMethod · 0.95
execMethod · 0.95
deleteInsertMethod · 0.95
upsertMethod · 0.95
writeTMPFileFunction · 0.85
containsListFunction · 0.85
ErrorfMethod · 0.80
StringMethod · 0.45

Tested by

no test coverage detected