@@ -105,23 +105,23 @@ func (d *BaseDatabase) WalkMessageDescriptorAndInsertWithDialect(dm *dynamic.Mes
105105 }
106106
107107 d .logger .Debug ("Walking message descriptor" , zap .String ("message_descriptor_name" , md .GetName ()), zap .Any ("table_info" , tableInfo ))
108- // Keep the actual PK value handy so we don't rely on slice indexes later
109- var primaryKeyValue any
110- if tableInfo != nil {
111- if table := dialect .GetTable (tableInfo .Name ); table != nil {
112- if table .PrimaryKey != nil {
113- // Robust PK retrieval: always use the original protobuf field name
114- // from the descriptor (not the possibly renamed SQL column name).
115- pkFieldName := table .PrimaryKey .FieldDescriptor .GetName ()
116- pkValue := dm .GetFieldByName (pkFieldName )
117- if pkValue == nil {
118- return 0 , fmt .Errorf ("missing primary key field %q for table %q" , pkFieldName , tableInfo .Name )
119- }
120- fieldValues = append (fieldValues , pkValue )
121- primaryKeyValue = pkValue
122- }
123- }
124- }
108+ // Keep the actual PK value handy so we don't rely on slice indexes later
109+ var primaryKeyValue any
110+ if tableInfo != nil {
111+ if table := dialect .GetTable (tableInfo .Name ); table != nil {
112+ if table .PrimaryKey != nil {
113+ // Robust PK retrieval: always use the original protobuf field name
114+ // from the descriptor (not the possibly renamed SQL column name).
115+ pkFieldName := table .PrimaryKey .FieldDescriptor .GetName ()
116+ pkValue := dm .GetFieldByName (pkFieldName )
117+ if pkValue == nil {
118+ return 0 , fmt .Errorf ("missing primary key field %q for table %q" , pkFieldName , tableInfo .Name )
119+ }
120+ fieldValues = append (fieldValues , pkValue )
121+ primaryKeyValue = pkValue
122+ }
123+ }
124+ }
125125
126126 totalSqlDuration := time .Duration (0 )
127127
@@ -131,17 +131,17 @@ func (d *BaseDatabase) WalkMessageDescriptorAndInsertWithDialect(dm *dynamic.Mes
131131
132132 var childs []* dynamic.Message
133133
134- for _ , fd := range dm .GetKnownFields () {
135- // Skip the PK using descriptor equality, resilient to column renames
136- if tableInfo != nil {
137- if table := dialect .GetTable (tableInfo .Name ); table != nil && table .PrimaryKey != nil {
138- if fd == table .PrimaryKey .FieldDescriptor {
139- continue
140- }
141- }
142- }
143- fv := dm .GetField (fd )
144- if v , ok := fv .([]interface {}); ok {
134+ for _ , fd := range dm .GetKnownFields () {
135+ // Skip the PK using descriptor equality, resilient to column renames
136+ if tableInfo != nil {
137+ if table := dialect .GetTable (tableInfo .Name ); table != nil && table .PrimaryKey != nil {
138+ if fd == table .PrimaryKey .FieldDescriptor {
139+ continue
140+ }
141+ }
142+ }
143+ fv := dm .GetField (fd )
144+ if v , ok := fv .([]interface {}); ok {
145145 // Check if this is an array of messages or native values
146146 if len (v ) > 0 {
147147 if _ , ok := v [0 ].(* dynamic.Message ); ok {
@@ -154,8 +154,16 @@ func (d *BaseDatabase) WalkMessageDescriptorAndInsertWithDialect(dm *dynamic.Mes
154154 childs = append (childs , fm )
155155 }
156156 } else {
157- // Array of native values - add as a single field value (the array itself)
158- fieldValues = append (fieldValues , fv )
157+ // Array of native values - normalize each element before storing
158+ normalized := make ([]interface {}, len (v ))
159+ for idx , elem := range v {
160+ converted , err := NormalizeValue (fd , elem )
161+ if err != nil {
162+ return 0 , fmt .Errorf ("normalizing repeated field %q: %w" , fd .GetName (), err )
163+ }
164+ normalized [idx ] = converted
165+ }
166+ fieldValues = append (fieldValues , normalized )
159167 }
160168 }
161169 } else if fm , ok := fv .(* dynamic.Message ); ok {
@@ -164,7 +172,11 @@ func (d *BaseDatabase) WalkMessageDescriptorAndInsertWithDialect(dm *dynamic.Mes
164172 }
165173 childs = append (childs , fm ) //need to be handled after current message inserted
166174 } else {
167- fieldValues = append (fieldValues , fv )
175+ converted , err := NormalizeValue (fd , fv )
176+ if err != nil {
177+ return 0 , fmt .Errorf ("normalizing field %q: %w" , fd .GetName (), err )
178+ }
179+ fieldValues = append (fieldValues , converted )
168180 }
169181 }
170182
@@ -179,22 +191,22 @@ func (d *BaseDatabase) WalkMessageDescriptorAndInsertWithDialect(dm *dynamic.Mes
179191 fmt .Println ("field values:" , fieldValues )
180192 return 0 , fmt .Errorf ("inserting into table %q: %w" , table .Name , err )
181193 }
182- if len (childs ) > 0 && d .useProtoOptions {
183- if table .PrimaryKey == nil {
184- return 0 , fmt .Errorf ("table %q has no primary key and has %d associated children table" , table .Name , len (childs ))
185- }
186- // Use the actual primary key value we fetched above. Using the
187- // descriptor index to compute its position within fieldValues is
188- // incorrect because fieldValues does not mirror the proto field
189- // ordering (we prepend block metadata, optionally add parent id,
190- // and we skipped the PK when iterating fields). This previously
191- // caused index out-of-range panics like: index 8 with length 6.
192- id := primaryKeyValue
193- p = & Parent {
194- field : strings .ToLower (md .GetName ()),
195- id : id ,
196- }
197- }
194+ if len (childs ) > 0 && d .useProtoOptions {
195+ if table .PrimaryKey == nil {
196+ return 0 , fmt .Errorf ("table %q has no primary key and has %d associated children table" , table .Name , len (childs ))
197+ }
198+ // Use the actual primary key value we fetched above. Using the
199+ // descriptor index to compute its position within fieldValues is
200+ // incorrect because fieldValues does not mirror the proto field
201+ // ordering (we prepend block metadata, optionally add parent id,
202+ // and we skipped the PK when iterating fields). This previously
203+ // caused index out-of-range panics like: index 8 with length 6.
204+ id := primaryKeyValue
205+ p = & Parent {
206+ field : strings .ToLower (md .GetName ()),
207+ id : id ,
208+ }
209+ }
198210 totalSqlDuration += time .Since (insertStartAt )
199211 }
200212 }
0 commit comments