@@ -2,6 +2,7 @@ package column
22
33import (
44 "database/sql"
5+ "errors"
56 "fmt"
67 "reflect"
78 "strings"
@@ -101,6 +102,11 @@ func (col *Array) Row(i int, ptr bool) any {
101102}
102103
103104func (col * Array ) Append (v any ) (nulls []uint8 , err error ) {
105+ if col .depth == 1 {
106+ if handled , err := col .appendBulkPlain (v ); handled || err != nil {
107+ return nil , err
108+ }
109+ }
104110 value := reflect .Indirect (reflect .ValueOf (v ))
105111 if value .Kind () != reflect .Slice {
106112 return nil , & ColumnConverterError {
@@ -151,6 +157,19 @@ func (col *Array) appendRowDefault(v any) error {
151157
152158func appendRowPlain [T any ](col * Array , arr []T ) error {
153159 col .appendOffset (0 , uint64 (len (arr )))
160+ _ , err := col .values .Append (arr )
161+ if err == nil {
162+ return nil
163+ }
164+
165+ // Append rejects unknown slice types up-front via ColumnConverterError
166+ // without mutating column state. AppendRow has a reflection-based
167+ // conversion fallback that accepts e.g. []int into Array(Int64); preserve
168+ // that by retrying per-item.
169+ var convErr * ColumnConverterError
170+ if ! errors .As (err , & convErr ) {
171+ return err
172+ }
154173 for _ , item := range arr {
155174 if err := col .values .AppendRow (item ); err != nil {
156175 return err
@@ -161,14 +180,108 @@ func appendRowPlain[T any](col *Array, arr []T) error {
161180
162181func appendNullableRowPlain [T any ](col * Array , arr []* T ) error {
163182 col .appendOffset (0 , uint64 (len (arr )))
183+ _ , err := col .values .Append (arr )
184+ if err == nil {
185+ return nil
186+ }
187+
188+ var convErr * ColumnConverterError
189+ if ! errors .As (err , & convErr ) {
190+ return err
191+ }
192+
164193 for _ , item := range arr {
165- var err error
166194 if item == nil {
167- err = col .values .AppendRow (nil )
168- } else {
169- err = col .values .AppendRow (item )
195+ if err := col .values .AppendRow (nil ); err != nil {
196+ return err
197+ }
198+ continue
170199 }
171- if err != nil {
200+ if err := col .values .AppendRow (item ); err != nil {
201+ return err
202+ }
203+ }
204+ return nil
205+
206+ }
207+
208+ // appendBulkPlain is the bulk equivalent of appendRowPlain for depth-1 Array
209+ // columns. Flattens arr into a single inner Append call so the inner column's
210+ // growth/loop preamble runs once instead of N times.
211+ //
212+ // Mirrors appendRowPlain's retry semantics: inner Append rejects unknown slice
213+ // types up-front via ColumnConverterError without mutating its state, so on
214+ // that error we retry per-item with AppendRow from the flat slice.
215+ func appendBulkPlain [T any ](col * Array , arr [][]T ) error {
216+ if len (arr ) == 0 {
217+ return nil
218+ }
219+
220+ total := 0
221+ for _ , row := range arr {
222+ total += len (row )
223+ }
224+
225+ flat := make ([]T , 0 , total )
226+ for _ , row := range arr {
227+ col .appendOffset (0 , uint64 (len (row )))
228+ flat = append (flat , row ... )
229+ }
230+
231+ _ , err := col .values .Append (flat )
232+ if err == nil {
233+ return nil
234+ }
235+
236+ var convErr * ColumnConverterError
237+ if ! errors .As (err , & convErr ) {
238+ return err
239+ }
240+
241+ for _ , item := range flat {
242+ if err := col .values .AppendRow (item ); err != nil {
243+ return err
244+ }
245+ }
246+
247+ return nil
248+ }
249+
250+ func appendNullableBulkPlain [T any ](col * Array , arr [][]* T ) error {
251+ if len (arr ) == 0 {
252+ return nil
253+ }
254+ total := 0
255+ for _ , row := range arr {
256+ total += len (row )
257+ }
258+
259+ flat := make ([]* T , 0 , total )
260+ for _ , row := range arr {
261+ col .appendOffset (0 , uint64 (len (row )))
262+ flat = append (flat , row ... )
263+ }
264+
265+ _ , err := col .values .Append (flat )
266+ if err == nil {
267+ return nil
268+ }
269+
270+ var convErr * ColumnConverterError
271+
272+ if ! errors .As (err , & convErr ) {
273+ return err
274+ }
275+
276+ for _ , item := range flat {
277+ if item == nil {
278+ if err := col .values .AppendRow (nil ); err != nil {
279+ return err
280+ }
281+ continue
282+ }
283+
284+ if err := col .values .AppendRow (item ); err != nil {
172285 return err
173286 }
174287 }
0 commit comments