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

Bugfix for chained Where() #24

Merged
merged 2 commits into from
Sep 2, 2016
Merged

Bugfix for chained Where() #24

merged 2 commits into from
Sep 2, 2016

Conversation

Emreu
Copy link
Contributor

@Emreu Emreu commented Jun 10, 2016

Hello!
I'm using goqu with MySQL dialect.
Problem description: If you make detailed Dataset (using Where) from base Dataset, already having some where clauses, sometimes added expressions could be presented in the base dataset or its derivatives.

For example:

baseDS := From(...).Select(...).Where(<some heavy expressions with subqueries etc.>)
// some conditional filtering
if doFilter {
    baseDS = baseDS.Where(goqu.I("selected").Eq(1))
}
subDS1 := baseDS.Where(goqu.I("type").Eq("Type1"))
subDS2 := baseDS.Where(goqu.I("type").Eq("Type2")) //This may overwrite where clause for subDS1!

sql, _, err := subDS1.ToSql() // sql = SELECT ... ... WHERE ... ... AND "Type" = "Type2" ; should be "Type1"
...

This happens because of go append() behaviour - in expressionList.Append() it may return reallocated slice (and everything goes well) or slice at the same address (then shit could happens if another Dataset already using same physical memory to store its own expression). To prevent this you should always reallocate slice.
I have implemented this fix and added test case.
Alternatively you could build base Dataset for every subset, but this will produce excessive and hardly maintainable code. Also you can generate sql for one dataset at a time, but this won't work if you want to make Union or another combination.

Best regards,
Anton Kriukov.

@denisvm
Copy link
Contributor

denisvm commented Aug 2, 2016

Hello, I've just ran into the same issue and got the following approach:

var filters []goqu.Expression

// add filters
filters = append(filters, goqu.I("contact").Eq(contact))
// [...] add some other filters

// check if there's any filter set
if filters != nil {
    queryBase = queryBase.Where(goqu.And(filters...))
}

I find this way clearer because you can specify which operator you want to use and can use it even inside subfilters if you like.

@doug-martin doug-martin merged commit 510bcea into doug-martin:master Sep 2, 2016
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

Successfully merging this pull request may close these issues.

None yet

3 participants