简体   繁体   中英

golang calling mysql function

I have an existing mysql table, which uses mysql's UUID_SHORT() function to generate unique IDs. A simplified version of the table:

CREATE TABLE `users` (
  `user_uuid` bigint(20) unsigned NOT NULL,
  `user_name` varchar(64) NOT NULL
);

And a new user would be created via:

INSERT INTO users (user_uuid, user_name) values (UUID_SHORT(), "new user name");

I started to implement the DBs model using gorm and I'm drawing a blank on how to tell gorm and database/sql to call UUID_SHORT() when a new instance of User is created.

From model/users.go:

package model

type User struct {
    UserUUID          uint64     `gorm:"column:user_uuid;primary_key:yes";sql:"notnull;default:uuid_short"`
    UserName          string     `sql:"notnull"`
}

func (user User) TableName() string {
    return "users"
}

From model/users_test.go:

package model_test

import (
    "testing"

    ".../model"
    ".../model/testutil"
)

func TestUserCreate(t *testing.T) {
    user := model.User{
        // UserUUID: **HOW DO I CALL UUID_SHORT() HERE?**,
        UserName: "Go Test",
    }
    // testutil.DB is the successful result of gorm.Open("mysql", ...)
    testutil.DB.Create(&user)
}

How can I call UUID_SHORT() for the user_uuid column when the instance is saved?

In order to make a call to MySQL's UUID_SHORT() in your model.User call, it would seem that you'd need to make an additional SQL call to the database before reaching the testutil.DB.Create(&user) line at some point.

It might be nice to find a way to use gorm for the MySQL UUID_SHORT() call itself, but that might end up requiring more work just to map a single row value ( user_uuid in this case) for use in your model.User (possibly requiring an additional struct just for UUID_SHORT() ) .

Therefore, using a simpler approach might help. The following code is a basic (though perhaps poor*) example of how UUID_SHORT() could be found using the sql package (specifically with the get_uuid_short() user-defined function, in this case):

package model_test

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "github.com/jinzhu/gorm"
    "github.com/stretchr/testify/assert"
    "log"
    "testing"
)

type User struct {
    UserUUID uint64 `gorm:"column:user_uuid;primary_key:yes";sql:"notnull;default:uuid_short"`
    UserName string `sql:"notnull"`
}

func (user User) TableName() string {
    return "users"
}

func get_uuid_short() uint64 {
    var uuid_short uint64

    /* connect to db using `sql` package */
    db, err := sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/uuid_test")
    if err != nil {
        log.Fatal(err)
    }

    /* select UUID_SHORT() */
    rows, err := db.Query("select UUID_SHORT()")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    /* get value of uuid_short */
    for rows.Next() {
        err := rows.Scan(&uuid_short)
        if err != nil {
            log.Fatal(err)
        }
    }

    return uuid_short
}

func TestUserCreate(t *testing.T) {
    user := User{
        UserUUID: get_uuid_short(),    /* get next UUID_SHORT() value */
        UserName: "Go Test",
    }
    db, err := gorm.Open("mysql", "username:password@/uuid_test?charset=utf8&parseTime=True&loc=Local")
    db.Create(&user)
    assert.Nil(t, err)
}

With results like this in the MySQL table:

mysql> select * from users;
+-------------------+-----------+
| user_uuid         | user_name |
+-------------------+-----------+
| 24070794506141712 | Go Test   |
| 24070794506141713 | Go Test   |
| 24070794506141714 | Go Test   |
+-------------------+-----------+
3 rows in set (0.00 sec)

*Note: This code might not address times where multiple users are concurrently calling get_uuid_short() (though MySQL may already provide a way to deal with this).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM