-
Notifications
You must be signed in to change notification settings - Fork 76
[request]: Build dynamic query builder similar to sequel (rb) #198
Comments
I hit the "Comment" button too soon. |
I'm afraid this does not fit the existing QL mechanism. The linked article says this:
The problem is, that in QL a dataset do not exists. Or more precisely, it never materializes in its entirety. QL translates the query to a function that on every call computes and returns just one row of the dataset. The nice property of a "frozen" dataset is that it can be reused and (sub)queried in different ways later, without recomputing it. That is possible to simulate in QL only by But maybe I've just misunderstood the concepts used by sequel. |
@mguentner I'm not sure what can be done with this issue. WDYT? |
The initial idea was to have a query builder that helps to construct queries where the arguments can differ. Sequel was just chosen because I like the API of constructing queries. My current use case is a function that queries a table. Some of the arguments can be Example: count := 1
basequery := "SELECT * FROM users"
query := basequery
if name != nil {
if count == 1 {
query += " where"
} else if count > 1 {
query += " and"
}
query = query + " name == $" + strconv.Itoa(count)
count++
}
if email != nil {
if count == 1 {
query += " where"
} else if count > 1 {
query += " and"
}
query = query + " email == $" + strconv.Itoa(count)
count++
}
// further down...
compiledQuery, err := ql.Compile(query + ";")
// even further down...
if name != nil && email != nil {
rs, _, err = db.Execute(ctx, compiledQuery, name, email)
}
if name == nil && email != nil {
rs, _, err = db.Execute(ctx, compiledQuery, email)
}
if name == nil && email == nil {
rs, _, err = db.Execute(ctx, compiledQuery)
} Instead of concatenating a query string like above, I'd like to be able to construct a builder. users := ql.NewSelectBuilder("users") // constructs a query for the table "users"
// -> SELECT * from users where email == [email protected] and name == "John"
query, _ = users.Where("email", email).And("name", name).Compile()
//or -> SELECT * from users where name == "John"
query, _ = users.Where("name", name).Compile()
//or -> SELECT * from users
query, _ = users.Compile()
// query is now ql.List
rs, _, err = db.Execute(ctx, query) I believe that the above is possible with ql. Thanks for your work by the way! |
modified: all_test.go new file: builder.go
@mguentner I've tried to code something in branch Line 3953 in 0469cd0
The new API is mostly ad hoc, so any suggestions are welcome, thanks. |
Awesome! This already looks really nice. Thank you. The expression API should allow for an identity Expression that is ignored and forms the start of a chain when the chain links are not known at compile time or should be constructed imperatively: expr := NewExpression("")
first := true
if email != nil {
expr = expr.Start("email").Equal(email)
first = false
}
if name != nil {
if first {
expr = expr.Start("name").Equal(name)
} else {
expr = expr.And("name").Equal(name)
}
first = false
}
// int16
if age != -1 {
if first {
expr = expr.Start("age").Equal(age)
} else {
expr = expr.And("age").Equal(age)
}
first = false
} func (e *Expression) Start(f interface{}) *Expression { return e.binop("", f) } Could be enough. Let me know if you see another way of constructing such a query using your current API since my example is just a naive continuation of the |
modified: all_test.go modified: builder.go
@mguentner PTAL, thank you. |
LGTM ;) |
modified: all_test.go modified: builder.go
modified: all_test.go modified: builder.go
Also 52dc064 updates this issue. @mguentner I'd like to ask you to now try to use this branch for some time, say a week or so. Let's collect your experiences and iterate over any troubles you may run into. After we'll eventually think it's ready to publish, it'll be committed to the master branch. Thanks. |
Will do. |
@mguentner Have you had a chance to work with the new API? If so, please provide feedback, thank you. |
@cznic Not yet. Needed to refactor a lot of stuff before I change the database layer again. Once I've used the new API, I will update this issue with feedback. I promise. |
No hurry, no problem. Thanks. |
-> invalid expression COUNT(*) however The |
This is working as documented. NewSelectStmt(NewExpression("count(*)")).From("users").Where(42) |
Indeed. Thanks! |
Uh oh!
There was an error while loading. Please reload this page.
Currently statements need to be written and compiled for each request.
A query builder could help doing that by aggregating the values / parameters first and then compiling the statement.
I like the interface the Sequel project (ruby) has.
Here is a simple select with chained statements:
http://sequel.jeremyevans.net/rdoc/files/doc/dataset_basics_rdoc.html
http://sequel.jeremyevans.net/documentation.html
The text was updated successfully, but these errors were encountered: