Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The db.MapperFunc is not called properly #937

Open
luxiangqing opened this issue Aug 15, 2024 · 0 comments
Open

The db.MapperFunc is not called properly #937

luxiangqing opened this issue Aug 15, 2024 · 0 comments

Comments

@luxiangqing
Copy link

Because different types of databases default return column name case inconsistency, oracle default uppercase, mysql default lowercase, I want to adapt to different databases struct field mapping, try using db.MapperFunc function in oracle can not work properly, StructScan return missing destination name error

var DB *sqlx.DB

func InitDB() {
	//db, err := sqlx.Connect("mysql", "xxxx")
	db, err := sqlx.Connect("godror", "xxxxx")
	if err != nil {
		panic(err)
	}
	DB = db
	DB.MapperFunc(DBMapper)
}

func DBMapper(s string) string {
	switch DB.DriverName() {
	case "mysql":
		return strings.ToLower(s)
	case "godror":
		return strings.ToUpper(s)
	case "sqlserver":
		return strings.ToLower(s)
	default:
		return strings.ToLower(s)
	}
}

type User struct {
	Id       int    `db:"id"`
	Username string `db:"username"`
	Nickname string `db:"nickname"`
	Password string `db:"password"`
	Phone    string `db:"phone"`
	Email    string `db:"email"`
}

func (u *User) ListByName(name string, db *sqlx.DB) (User, error) {
	query := "select * from tuser where username = ?"
	query = db.Rebind(query)
	var user User
	if err := db.QueryRowx(query, name).StructScan(&user); err != nil {
		return user, err
	}
	return user, nil
}

I checked the source code and found that when scanning the data into the structure filed, the parseName function call mapFunc not correctly, souce code as follows:

func parseName(field reflect.StructField, tagName string, mapFunc, tagMapFunc mapf) (tag, fieldName string) {
	// first, set the fieldName to the field's name
	fieldName = field.Name
	// if a mapFunc is set, use that to override the fieldName
	if mapFunc != nil {
		fieldName = mapFunc(fieldName)
	}

	// if there's no tag to look for, return the field name
	if tagName == "" {
		return "", fieldName
	}

	// if this tag is not set using the normal convention in the tag,
	// then return the fieldname..  this check is done because according
	// to the reflect documentation:
	//    If the tag does not have the conventional format,
	//    the value returned by Get is unspecified.
	// which doesn't sound great.
	if !strings.Contains(string(field.Tag), tagName+":") {
		return "", fieldName
	}

	// at this point we're fairly sure that we have a tag, so lets pull it out
	tag = field.Tag.Get(tagName)

	// if we have a mapper function, call it on the whole tag
	// XXX: this is a change from the old version, which pulled out the name
	// before the tagMapFunc could be run, but I think this is the right way
	if tagMapFunc != nil {
		tag = tagMapFunc(tag)
	}

	// finally, split the options from the name
	parts := strings.Split(tag, ",")
@	fieldName = parts[0]           //here mapFunc  is not called

	return tag, fieldName
}
@luxiangqing luxiangqing changed the title The NameMapper function is not called properly The db.MapperFunc function is not called properly Aug 15, 2024
@luxiangqing luxiangqing changed the title The db.MapperFunc function is not called properly The db.MapperFunc is not called properly Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant