/
githubmirror
/
ydb-go-sdk
Обзор
Документация
Войти
/
githubmirror
/
ydb-go-sdk
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
internal/query/scanner/struct.go
95 строк
2 KB
Konstantin Prokopenko
Modernize Go codebase: adopt modern idioms and upgrade CI tooling (#2082)
08 апр 2026, 20:42
Не верифицирован
08 апр 2026, 20:42
f3aeeb1
Код
Авторство
О чём код?
package scanner import ( "fmt" "reflect" "strings" "github.com/ydb-platform/ydb-go-sdk/v3/internal/value" "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" ) type scanStructSettings struct { TagName string AllowMissingColumnsFromSelect bool AllowMissingFieldsInStruct bool } type StructScanner struct { data *Data } func Struct(data *Data) StructScanner { return StructScanner{ data: data, } } func fieldName(f reflect.StructField, tagName string) string { //nolint:gocritic if name, has := f.Tag.Lookup(tagName); has { return name } return f.Name } func (s StructScanner) ScanStruct(dst any, opts ...ScanStructOption) (err error) { settings := scanStructSettings{ TagName: "sql", AllowMissingColumnsFromSelect: false, AllowMissingFieldsInStruct: false, } for _, opt := range opts { if opt != nil { opt.applyScanStructOption(&settings) } } ptr := reflect.ValueOf(dst) if ptr.Kind() != reflect.Pointer { return xerrors.WithStackTrace(fmt.Errorf("%w: '%s'", errDstTypeIsNotAPointer, ptr.Kind().String())) } if ptr.Elem().Kind() != reflect.Struct { return xerrors.WithStackTrace(fmt.Errorf("%w: '%s'", errDstTypeIsNotAPointerToStruct, ptr.Elem().Kind().String())) } tt := ptr.Elem().Type() missingColumns := make([]string, 0, len(s.data.columns)) existingFields := make(map[string]struct{}, tt.NumField()) for i := 0; i < tt.NumField(); i++ { name := fieldName(tt.Field(i), settings.TagName) if name == "-" { continue } v, err := s.data.seekByName(name) if err != nil { missingColumns = append(missingColumns, name) } else { if err = value.CastTo(v, ptr.Elem().Field(i).Addr().Interface()); err != nil { return xerrors.WithStackTrace(fmt.Errorf("scan error on struct field name '%s': %w", name, err)) } existingFields[name] = struct{}{} } } if !settings.AllowMissingColumnsFromSelect && len(missingColumns) > 0 { return xerrors.WithStackTrace( fmt.Errorf("%w: '%v'", ErrColumnsNotFoundInRow, strings.Join(missingColumns, "','")), ) } if !settings.AllowMissingFieldsInStruct { missingFields := make([]string, 0, tt.NumField()) for _, c := range s.data.columns { if _, has := existingFields[c.GetName()]; !has { missingFields = append(missingFields, c.GetName()) } } if len(missingFields) > 0 { return xerrors.WithStackTrace( fmt.Errorf("%w: '%v'", ErrFieldsNotFoundInStruct, strings.Join(missingFields, "','")), ) } } return nil }