@@ -74,15 +74,15 @@ func ScanOneRowToDest(scanContext *ScanContext, rows *sql.Rows, destPtr interfac
7474 err := rows .Scan (scanContext .row ... )
7575
7676 if err != nil {
77- return fmt .Errorf ("rows scan error, %w" , err )
77+ return fmt .Errorf ("jet: rows scan error, %w" , err )
7878 }
7979
80- destValue := reflect .ValueOf (destPtr )
80+ destValuePtr := reflect .ValueOf (destPtr )
8181
82- _ , err = mapRowToStruct (scanContext , "" , newTypeStack (), destValue , nil )
82+ _ , err = mapRowToStruct (scanContext , "" , destValuePtr , nil )
8383
8484 if err != nil {
85- return fmt .Errorf ("failed to map a row, %w" , err )
85+ return fmt .Errorf ("jet: failed to scan a row into destination , %w" , err )
8686 }
8787
8888 return nil
@@ -121,7 +121,7 @@ func queryToSlice(ctx context.Context, db DB, query string, args []interface{},
121121
122122 scanContext .rowNum ++
123123
124- _ , err = mapRowToSlice (scanContext , "" , newTypeStack (), slicePtrValue , nil )
124+ _ , err = mapRowToSlice (scanContext , "" , slicePtrValue , nil )
125125
126126 if err != nil {
127127 return scanContext .rowNum , err
@@ -139,7 +139,6 @@ func queryToSlice(ctx context.Context, db DB, query string, args []interface{},
139139func mapRowToSlice (
140140 scanContext * ScanContext ,
141141 groupKey string ,
142- typesVisited * typeStack ,
143142 slicePtrValue reflect.Value ,
144143 field * reflect.StructField ) (updated bool , err error ) {
145144
@@ -154,19 +153,19 @@ func mapRowToSlice(
154153
155154 structGroupKey := scanContext .getGroupKey (sliceElemType , field )
156155
157- groupKey = groupKey + "," + structGroupKey
156+ groupKey = concat ( groupKey , "," , structGroupKey )
158157
159158 index , ok := scanContext .uniqueDestObjectsMap [groupKey ]
160159
161160 if ok {
162161 structPtrValue := getSliceElemPtrAt (slicePtrValue , index )
163162
164- return mapRowToStruct (scanContext , groupKey , typesVisited , structPtrValue , field , true )
163+ return mapRowToStruct (scanContext , groupKey , structPtrValue , field , true )
165164 }
166165
167166 destinationStructPtr := newElemPtrValueForSlice (slicePtrValue )
168167
169- updated , err = mapRowToStruct (scanContext , groupKey , typesVisited , destinationStructPtr , field )
168+ updated , err = mapRowToStruct (scanContext , groupKey , destinationStructPtr , field )
170169
171170 if err != nil {
172171 return
@@ -192,7 +191,7 @@ func mapRowToBaseTypeSlice(scanContext *ScanContext, slicePtrValue reflect.Value
192191 return
193192 }
194193 }
195- rowElemPtr := scanContext .rowElemValuePtr (index )
194+ rowElemPtr := scanContext .rowElemValueClonePtr (index )
196195
197196 if rowElemPtr .IsValid () && ! rowElemPtr .IsNil () {
198197 updated = true
@@ -208,7 +207,6 @@ func mapRowToBaseTypeSlice(scanContext *ScanContext, slicePtrValue reflect.Value
208207func mapRowToStruct (
209208 scanContext * ScanContext ,
210209 groupKey string ,
211- typesVisited * typeStack , // to prevent circular dependency scan
212210 structPtrValue reflect.Value ,
213211 parentField * reflect.StructField ,
214212 onlySlices ... bool , // small optimization, not to assign to already assigned struct fields
@@ -217,12 +215,12 @@ func mapRowToStruct(
217215 mapOnlySlices := len (onlySlices ) > 0
218216 structType := structPtrValue .Type ().Elem ()
219217
220- if typesVisited .contains (& structType ) {
218+ if scanContext . typesVisited .contains (& structType ) {
221219 return false , nil
222220 }
223221
224- typesVisited .push (& structType )
225- defer typesVisited .pop ()
222+ scanContext . typesVisited .push (& structType )
223+ defer scanContext . typesVisited .pop ()
226224
227225 typeInf := scanContext .getTypeInfo (structType , parentField )
228226
@@ -240,7 +238,7 @@ func mapRowToStruct(
240238
241239 if fieldMap .complexType {
242240 var changed bool
243- changed , err = mapRowToDestinationValue (scanContext , groupKey , typesVisited , fieldValue , & field )
241+ changed , err = mapRowToDestinationValue (scanContext , groupKey , fieldValue , & field )
244242
245243 if err != nil {
246244 return
@@ -251,34 +249,36 @@ func mapRowToStruct(
251249 }
252250
253251 } else {
254- if mapOnlySlices || fieldMap .columnIndex == - 1 {
252+ if mapOnlySlices || fieldMap .rowIndex == - 1 {
255253 continue
256254 }
257255
258- cellValue := scanContext .rowElem (fieldMap .columnIndex )
256+ scannedValue := scanContext .rowElemValue (fieldMap .rowIndex )
259257
260- if cellValue == nil {
258+ if ! scannedValue .IsValid () {
259+ setZeroValue (fieldValue ) // scannedValue is nil, destination should be set to zero value
261260 continue
262261 }
263262
264- initializeValueIfNilPtr (fieldValue )
265263 updated = true
266264
267265 if fieldMap .implementsScanner {
268- scanner := getScanner (fieldValue )
266+ initializeValueIfNilPtr (fieldValue )
267+ fieldScanner := getScanner (fieldValue )
269268
270- err = scanner .Scan (cellValue )
269+ value := scannedValue .Interface ()
270+
271+ err := fieldScanner .Scan (value )
271272
272273 if err != nil {
273- err = fmt .Errorf (`can't scan %T(%q) to '%s %s': %w` , cellValue , cellValue , field .Name , field .Type .String (), err )
274- return
274+ return updated , fmt .Errorf (`can't scan %T(%q) to '%s %s': %w` , value , value , field .Name , field .Type .String (), err )
275275 }
276276 } else {
277- err = setReflectValue ( reflect . ValueOf ( cellValue ) , fieldValue )
277+ err := assign ( scannedValue , fieldValue )
278278
279279 if err != nil {
280- err = fmt .Errorf (`can't assign %T(%q) to '%s %s': %w` , cellValue , cellValue , field . Name , field . Type . String (), err )
281- return
280+ return updated , fmt .Errorf (`can't assign %T(%q) to '%s %s': %w` , scannedValue . Interface (), scannedValue . Interface (),
281+ field . Name , field . Type . String (), err )
282282 }
283283 }
284284 }
@@ -290,7 +290,6 @@ func mapRowToStruct(
290290func mapRowToDestinationValue (
291291 scanContext * ScanContext ,
292292 groupKey string ,
293- typesVisited * typeStack ,
294293 dest reflect.Value ,
295294 structField * reflect.StructField ) (updated bool , err error ) {
296295
@@ -306,7 +305,7 @@ func mapRowToDestinationValue(
306305 }
307306 }
308307
309- updated , err = mapRowToDestinationPtr (scanContext , groupKey , typesVisited , destPtrValue , structField )
308+ updated , err = mapRowToDestinationPtr (scanContext , groupKey , destPtrValue , structField )
310309
311310 if err != nil {
312311 return
@@ -322,7 +321,6 @@ func mapRowToDestinationValue(
322321func mapRowToDestinationPtr (
323322 scanContext * ScanContext ,
324323 groupKey string ,
325- typesVisited * typeStack ,
326324 destPtrValue reflect.Value ,
327325 structField * reflect.StructField ) (updated bool , err error ) {
328326
@@ -331,9 +329,9 @@ func mapRowToDestinationPtr(
331329 destValueKind := destPtrValue .Elem ().Kind ()
332330
333331 if destValueKind == reflect .Struct {
334- return mapRowToStruct (scanContext , groupKey , typesVisited , destPtrValue , structField )
332+ return mapRowToStruct (scanContext , groupKey , destPtrValue , structField )
335333 } else if destValueKind == reflect .Slice {
336- return mapRowToSlice (scanContext , groupKey , typesVisited , destPtrValue , structField )
334+ return mapRowToSlice (scanContext , groupKey , destPtrValue , structField )
337335 } else {
338336 panic ("jet: unsupported dest type: " + structField .Name + " " + structField .Type .String ())
339337 }
0 commit comments