-
Notifications
You must be signed in to change notification settings - Fork 64
Question: Merger 抽象相关逻辑语义问题及批量查询实现问题 #165
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
Comments
关于抽象定义问题:明哥说暂时先定义这些用到的方法 |
Err()根据sql.Rows的设计思路,在用 暂时先别改 等一下 @flycash 的回复吧 |
我还有没有遗漏任何问题? |
Close的主要作用是防止进一步枚举即用户再次调用Next/Scan获取数据,咱们的mergerRows也要达到这个效果,所以我认为一定要遍历全部的[]sql.Rows并调用其Close()方法,做的全面点就将此遍历过程中的err全部记录再返回,简单点就记录第一个再返回。但不能碰到一个sql.Rows的Close方法返回error就中断循环不再遍历了。没有调用Close的sql.Rows仍能被使用,这不符合上面的Close语义。 |
|
sqlrows的方法除了已经定义的还有
|
|
关于NextResultSet的调研结果如下:
详情见下方学习资料1 可能出现的问题
用户使用
用户可能使用
综上,也许我们应该强制要求一个SELECT只对应一个sql.Rows且不支持存储过程,这样就不用处理NextResultSet了。 学习资料
func ExampleDB_Query_multipleResultSets() {
age := 27
q := `
create temp table uid (id bigint); -- Create temp table for queries.
insert into uid
select id from users where age < ?; -- Populate temp table.
-- First result set.
select
users.id, name
from
users
join uid on users.id = uid.id
;
-- Second result set.
select
ur.user, ur.role
from
user_roles as ur
join uid on uid.id = ur.user
;
`
rows, err := db.Query(q, age)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var (
id int64
name string
)
if err := rows.Scan(&id, &name); err != nil {
log.Fatal(err)
}
log.Printf("id %d name is %s\n", id, name)
}
if !rows.NextResultSet() {
log.Fatalf("expected more result sets: %v", rows.Err())
}
var roleMap = map[int64]string{
1: "user",
2: "admin",
3: "gopher",
}
for rows.Next() {
var (
id int64
role int64
)
if err := rows.Scan(&id, &role); err != nil {
log.Fatal(err)
}
log.Printf("id %d has role %s\n", id, roleMap[role])
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
}
When your database operation might return multiple result sets, you can retrieve those by using Rows.NextResultSet. This can be useful, for example, when you’re sending SQL that separately queries multiple tables, returning a result set for each. Rows.NextResultSet prepares the next result set so that a call to Rows.Next retrieves the first row from that next set. It returns a boolean indicating whether there is a next result set at all. Code in the following example uses DB.Query to execute two SQL statements. The first result set is from the first query in the procedure, retrieving all of the rows in the album table. The next result set is from the second query, retrieving rows from the song table. rows, err := db.Query("SELECT * from album; SELECT * from song;")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Loop through the first result set.
for rows.Next() {
// Handle result set.
}
// Advance to next result set.
rows.NextResultSet()
// Loop through the second result set.
for rows.Next() {
// Handle second set.
}
// Check for any error in either result set.
if err := rows.Err(); err != nil {
log.Fatal(err)
} |
感谢@longyue0521 的调研。 我觉得我们的目标是保持和 sql.Rows 语义一样,但是并不意味着我们现在就要支持全部的 sql.Rows 的所有的方法。我准备采取一种延迟支持的策略,即只有我们需要的时候再支持。而如果我们支持了,就要保持和 sql.Rows 的语义一致。 所以@juniaoshaonian 你可以先按照所需方法的最小集来支持,然后每一个方法都保持和 sql.Rows 的语义一致,所以请在具体的 rows 实现里面支持 NextResultSet。 从理论上来说,我们的分库分表功能永远不会走进去 NextResultSet,但是如果考虑将 merger 将来作为一个单独的项目拆出去的话,那么还是要考虑万一就有人不按照套路出牌呢。 |
不客气 ^_^ ,@juniaoshaonian 在Rows的定义上方把这个策略及语义要求描述一下以便后续维护者理解、维护。 |
抽象定义问题
当前Merger和Rows抽象定义如下
Merge(ctx context.Context, group []Rows) (Rows, error)
使其更具通用性、组合性、扩展性。批量查询实现问题
m.rows[m.cnt].Scan(dest...)
处,g2执行到Next()的第一个if m.rows[m.cnt].Next() {...}
把本该由g1读取走的缓存行用新行给覆盖掉了。如果MergerRows与sql.Rows语义一致即不能用于并发场景,那么读写锁m.mu
的作用是什么?m.rows[m.cnt].Next()
返回false时,需要调用其上的NextResultSet()
检查/获取下一个结果集for rows.Next() { rows.Scan(...) }
之后用rows.Err()
来检查迭代期间遇到的错误。你的问题
你使用的是 eorm 哪个版本?
你设置的的 Go 环境?
The text was updated successfully, but these errors were encountered: