implement "sugar" wrapper method for findAll() followed by count()#533
implement "sugar" wrapper method for findAll() followed by count()#533janmeier merged 9 commits intosequelize:masterfrom iamjochem:feature/findAndCountSugar
Conversation
|
@iamjochem code looking good, had to reset the order option too since it was breaking the count |
|
@RobGonda - fixed and added a test |
|
Wonder if it should actually be findAllAndCount, for consistency with findAll, but that would be one ugly function name. |
|
I was struggling with a good name as well ... personally I don't agree with maybe this function should be called |
|
It's being discussed having find be findAll and findOne be find. But it would be a 2.0 thing in any case :) Yea, findAndCountAll looks nicer |
|
with regard to the 2.0 discussion regarding |
|
Weren't you just advocating that current findAll should be find and the current find should be findOne? |
|
if sequelize was a blank slate I'd opt for |
|
One more, have to reset 'include' too |
|
got anymore @RobGonda ? :) ... I'm still getting to grips with sequelize, I'm learning as I stumble along. |
|
Same here - not an expert, but I've been need tons of features so I'm adding them along ... |
…dAndCountAll() so that generating the "count" query does not break the generated "select" query (due to the query generator overwriting the options *where* property, e.g. from `["name LIKE ?", "foo%"]` to `["foo%"]`)
There was a problem hiding this comment.
It is hard to support consistently since mysql/sqlite and PG handles it two different ways - Mysql cannot do an offset without limit
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter.
So i guess the right way to make this work across dialects would be something like
{ offset: 1, limit: 9007199254740992 }
There was a problem hiding this comment.
hi @janmeier - I wasn't aware of the MySQL issue. I feel that the limit hack for MySQL (when a limit is not specified) should be stuffed into the MySQL dialect generator.
an alternative could be to require that limit and offset always be specified as a pair - this avoids having to implement the hack and means you'll never get that "Sequelize refuses to return trillionth+1 record when only specifying 'offset'" issue ;-).
other ORM/DBAL projects have the run into the same issues, e.g.:
note that there they chose for your 'big number' hackin their equivelent of the 'dialect' ... I am wondering whether the big number hack needs to take account of the size of 'MAX LONG' or should we opt to define the 'big number' as a string?
oh and do you need me to add a fix for this problem in this PR? :)
There was a problem hiding this comment.
From the MySQL docs
There is a limit of 2^32 (~4.295E+09) rows in a MyISAM table. If you build MySQL with the --with-big-tables option, the row limitation is increased to (2^32)^2 (1.844E+19) rows. See Section 2.16.2, “Typical configure Options”. Binary distributions for Unix and Linux are built with this option.
So 18446744073709552000 as a limit should be fine
Up to you, feel free to extend this PR or create a new one :)
There was a problem hiding this comment.
I thought about it - I'm of the opinion that this is not the place to fix it the problem is in the underlying code (findAndCountALL() is effectively a wrapper around findAll())
There was a problem hiding this comment.
I added another issues that the offset issue should be fixed :)
|
When we've resolved the comments above and the semi-colons are gone this should be good to merge |
… we now have lo-dash as a replacement for underscore)
|
I merged in latest sequelize/master, replaced the crufty deep-clone hack with lo-dash deepClone(), murdered some semi-colons, removed the debug-cruft. whatI did not do:
|
There was a problem hiding this comment.
we can use the proxy method of the event emitter for that: https://github.com/sequelize/sequelize/blob/master/lib/emitters/custom-event-emitter.js#L57
There was a problem hiding this comment.
I thought so too but the proxy() method only allows for straight pass through - if you wish to do any with the incoming result before emitting an event on the proxied emitter then you have to do the proxying 'manually' ... in this case I need to compose the object containing the count and rows object (in the success event handler).
it is not possible to tell the proxy() method that you only want to proxy certain events (i.e. in this case 'error' and 'sql')
There was a problem hiding this comment.
well you could just extend the method :D like emitter.proxy(anotherEmitter, ['error', 'sql])
There was a problem hiding this comment.
true but that would go against the idea of keeping PRs self-contained and as simple as possible, also I am not sure it would really make the code more understandable in this case.
just for laughs here is what I think an extended proxy() method should look like (maybe something for another PR):
CustomEventEmitter.prototype.proxy = function(emitter, events) {
var isa = events ? Utils._.isArray(events) : false
, iso = !isa && events ? Utils._.isObject(events) : false
proxyEventKeys.forEach(function (eventKey) {
var fn
if (isa && events.indexOf(eventKey) === -1) {
return
}
if (iso) {
if (!events.hasOwnProperty(eventKey))
return
if (Utils._.isFunction(events[eventKey]))
fn = events[eventKey]
}
this.on(eventKey, fn || function(result) { emitter.emit(eventKey, result) })
}.bind(this))
}|
ping - any chance this is good enough to go in? (see my previous comment about the last changes/improvements I made based on feedback/comments) |
implement "sugar" wrapper method for findAll() followed by count()
in response to: #531