Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
Thanks to Kyle and Melissa for the further explanation. So, I thought about it some more and agree with you that putting a few redundant bits on the disk is not sinful, and actually I am a fan of keyPathsForValuesAffectingValueForkey. Look at the little script I have in my Xcode scripts menu! [1] But the other issue -- the inability of a Core Data fetch to handle arbitrary predicates produced by NSPredicateEditor -- weighs heavily against Core Data fetches. I made my own simple predicate editor control a few years ago, but of course it is a pile of garbage compared to NSPredicateEditor, and I just can't go back to 2006 now. So I still plan to use NSPredicateEditor, fetch all and filter with - [NSArray filteredArrayWithPredicate:]. I have used sqlite3 directly myself and don't recall any limitation on the number of ALL, ANY or IN clauses. If there is not, then maybe Apple would be responsive to a enhancement/bug report on Core Data fetches not being able to handle predicates from NSPredicateEditor. And if I'm lucky Apple will fix it before any of my users has a data set large enough to require hard disk access during a search :) Jerry [1] Script for coding +keyPathsForValuesAffecting... #!/bin/sh echo + (NSSet*)keyPathsForValuesAffecting { echo return [NSSet setWithObjects: echo @\\, echo nil] ; echo } echo ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 23, at 13:53, Melissa J. Turner wrote: Unwinding to the original message, the most correct thing to do would be to add a derived property letterGrade which is automatically updated whenever grade is, which then allows you to search against that. I don't know if a derived property is a managed property that appears in the .xcdatamodel, or a regular instance variable. If Melissa is referring to a managed property, if it is non-transient, then yes this could be used in the predicate of a Core Data fetch. The disadvantage is that now every object in every store has this redundant (derived) attribute. More important than the wasted bits is that custom setters are now required to keep the derived attribute in sync with its source attribute, opening a way to introduce bugs into future versions. If Melissa is referring to a regular instance variable, then it cannot be used in the predicate of a Core Data fetch and thus filtering must be done in RAM by -[NSArray filteredArrayWithPredicate], resulting in limited scalability. For my application, I chose the latter. Am I misunderstanding anything? ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On Tue, Apr 28, 2009 at 5:15 PM, Jerry Krinock je...@ieee.org wrote: If Melissa is referring to a managed property, if it is non-transient, then yes this could be used in the predicate of a Core Data fetch. The disadvantage is that now every object in every store has this redundant (derived) attribute. More important than the wasted bits is that custom setters are now required to keep the derived attribute in sync with its source attribute, opening a way to introduce bugs into future versions. We all love normalization. That is, until it hinders our progress. One of the things to keep in mind with Core Data is that you are *not* using an RDMBS. Sure, one might provide the backing storage under the hood, but the traditional concern with data normalization in an n-tier enterprise situation is with the data: the data must remain pure and accessible to any number of interfaces. Core Data is different: it's an object graph management framework for desktop apps. You are required by its very nature to couple the business logic much tighter to the data storage, since you really are storing business-logic-bearing model objects. So step 1 is to stop clinging to normalization rules. (My database professor would kill me for that sentence, but it's true.) There really is no redundancy here, because the data stored on disk is never really separated from the model objects which use that data. In an n-tier app, you would be correct to avoid storing the derived property. As for the logic required to maintain this relationship, that's why we have KVC/KVO! Implement +keyPathsForValuesAffectingValueForKey: as appropriate. Implement your KVC setters/getters for the independent attributes such that they invoke -setPrimitiveValue:forKey: for the required dependent properties. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
(apologies for the delay; I've been on vacation for the last few days and just got back) On Apr 28, 2009, at 14:32, Kyle Sluder wrote: So step 1 is to stop clinging to normalization rules. (My database professor would kill me for that sentence, but it's true.) There really is no redundancy here, because the data stored on disk is never really separated from the model objects which use that data. In an n-tier app, you would be correct to avoid storing the derived property. Even in an n-tier application there are situations where it makes more sense to denormalize data than cling to theoretical purity. Once common case is to avoid joins, because they're *expensive*. Sometimes, the dba level pain of maintaining duplicate/derived data is much less than the user level pain of doing a join to display information in a frequently accessed view. There's no general rule for when this becomes true, because it's data set and use dependent, and it's not something you should do casually or without understanding what you're doing, why, and what tradeoffs are involved, but it is part of building a schema that's does what you need it to do efficiently. You can see an example of denormalized data in the Leopard version of iCal. The badges on the corner of events in the varying day/week/month views displays meta-information about the relationship that contains the note/contact/etc data. Having the badge provides useful information (there are other people invited, click here for meeting material), but it's expensive to do the join just to decide whether or not to display that badge for any given event, so iCal stores a separate bit of information saying this event has notes/contacts/ etc. According to pure relational design, this is a Very Bad Thing, because it duplicates information that exists in the join tables and introduces the possibility of error into the database. According to real-world performance, not doing the join sped displaying those views up by an order of magnitude (more in the case of large calendars). Taking normalization to it's fullest extent, you end up with things like databases where a Person is a set of joins to a Names table (don't get me started on natural vs assigned integer keys ;-), but no one outside academia does that because it's overkill and inefficient for anything except theoretical work. As for the logic required to maintain this relationship, that's why we have KVC/KVO! Implement +keyPathsForValuesAffectingValueForKey: as appropriate. Implement your KVC setters/getters for the independent attributes such that they invoke -setPrimitiveValue:forKey: for the required dependent properties. This is what I was getting at, yes. Create a separate modeled property 'letterGrade' and have the mutator for 'percentageGrade' automatically update it whenever percentageGrade is changed. Add observers as necessary. +Melissa ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 22, at 01:26, Ben Trumbull wrote: The Core Data SQL store supports only one to-many operation per query; therefore in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) from ALL, ANY, and IN. Do you have a specific scenario in which you need to perform nested to-many operations, yet you cannot use SUBQUERY or compound queries like OR ? Or is this troubling, in the sense that the universe is doomed to evaporate kind of way ? Well, I'd rather give my users NSPredicateEditor and let them make that decision. I'm sure that the code which Apple has written to generate predicates in NSPredicateEditor is better than any that I could write, not to mention that Lazy Programmer thing. However, it appears that NSPredicateEditor can produce compound predicates that violate the rule given above. For example, here's one that I just produced in my app: isAllowedDupe == 1 OR dontVerify == 1 OR shortcut CONTAINS stuff OR comments CONTAINS OR type == 3840 OR name CONTAINS M OR (url CONTAINS a AND tagsString CONTAINS apple) A much better way appears to be to fetch all objects from the store with no predicate and then use -[NSArray filteredArrayWithPredicate:]. This takes only one more line of code, solves all problems, and is supposedly cheaper too: This does not solve all problems, it most emphatically is NOT cheaper, and most assuredly does NOT scale Thank you, Ben. I understand about the scaling now. But for applications with typically small data sets, I believe that - filteredArrayWithPredicate can be a good, practical solution for developers who'd like to leverage the power of NSPredicateEditor in exchange for having a few users with not enough RAM to hold all their objects experience some hard disk access. Performance is always something that needs to be tested, anyhow. The managed objects in my app have 35 properties and I rarely see a user with more than 1500 objects. Searching is something that the average user might do once a week. I have an early 2006 Mac Mini with 2 GB RAM. Filtering an array on a test database of 5000 objects looks like it takes maybe 20 milliseconds or so. So, yes it would be nice to optimize the search, maybe doing a fetch with Core Data and then further filtering the array as someone suggested. I'll probably do some more testing, but at this point my cost/benefit analysis says to wait until, if ever, it becomes an issue for someone. Maybe Apple might provide an easier solution by then ;) (Yes, I know about the ER procedure.) ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 23, at 13:53, Melissa J. Turner wrote: Unwinding to the original message, the most correct thing to do would be to add a derived property letterGrade which is automatically updated whenever grade is, which then allows you to search against that. Melissa, please give a more precise definition of derived property. Is it... (a) an attribute defined in the data model or (b) a plain old instance variable Thanks, Jerry ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 22 Apr 2009, at 22:34, Melissa J. Turner wrote: On Apr 22, 2009, at 02:12, Mike Abdullah wrote: On 22 Apr 2009, at 08:48, Ben Trumbull wrote: Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know Probably because nobody ever cared enough to file an enhancement request, and it didn't occur to us that writing 1 line of code to call filteredArrayWithPredicate was so troublesome. Calling -filteredArrayWithPredicate is no hassle, but for a large predicate, it has the bad performance of comparing a bunch of the persistent properties all over again, despite already knowing they'll match the predicate. Since I assume Core Data must do some kind of internal splitting up of the predicate in order to perform its fetch, I'd have thought it is in a good position to know what the remaining transient portion of the predicate is. You assume incorrectly. CoreData simply translates the predicate to SQL and passes it down to SQLite as a WHERE clause. Hence the lack of support for transient properties: SQLite has no idea what to do when you ask it to qualify by a column that doesn't exist in its schema. OK, so I'm trying to wrap my head around this. Let's say I build a predicate along the lines of: fooPersistent == 123 fooTransient == 456 And then use it in a fetch request. Does Core Data: A) Pass that predicate straight to SQLite which fails because it can't find a fooTransient column. B) Pass that predicate straight to SQLite which ignores fooTransient (presumably treating it as always evaluating to true). C) Create a fooPersistent == 123 predicate and pass that to SQLite. Or of course D) something I've failed to conceive of which seems quite probable! Regards, Mike. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 23, at 05:18, Mike Abdullah wrote: OK, so I'm trying to wrap my head around this. Let's say I build a predicate along the lines of: fooPersistent == 123 fooTransient == 456 And then use it in a fetch request. Does Core Data: A) Pass that predicate straight to SQLite which fails because it can't find a fooTransient column. B) Pass that predicate straight to SQLite which ignores fooTransient (presumably treating it as always evaluating to true). C) Create a fooPersistent == 123 predicate and pass that to SQLite. Or of course D) something I've failed to conceive of which seems quite probable! In my experience, before I read the documentation and learned not to put transient properties in my predicates, I found that fetches containing such predicates returned an empty array. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 23 Apr 2009, at 15:03, Jerry Krinock wrote: On 2009 Apr 23, at 05:18, Mike Abdullah wrote: OK, so I'm trying to wrap my head around this. Let's say I build a predicate along the lines of: fooPersistent == 123 fooTransient == 456 And then use it in a fetch request. Does Core Data: A) Pass that predicate straight to SQLite which fails because it can't find a fooTransient column. B) Pass that predicate straight to SQLite which ignores fooTransient (presumably treating it as always evaluating to true). C) Create a fooPersistent == 123 predicate and pass that to SQLite. Or of course D) something I've failed to conceive of which seems quite probable! In my experience, before I read the documentation and learned not to put transient properties in my predicates, I found that fetches containing such predicates returned an empty array. Ah, so that would be option A then I guess, if by fail we take it to be more nothing matches the predicate. In which case, I guess it certainly would be quite a big change for Core Data to start handling transient attributes during fetches too. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know Probably because nobody ever cared enough to file an enhancement request, and it didn't occur to us that writing 1 line of code to call filteredArrayWithPredicate was so troublesome. - Ben ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
The fact that Core Data cannot fetch using a predicate based on transient properties [1] seems to greatly limit the utility of the NSPredicateEditor view, and makes me very sad. Dear list. transient (adj): (1) passing especially quickly into and out of existence May I suggest that the expectation that Core Data should fetch based on criteria that DOES NOT EXIST in the file seems somewhat unrealistic ? However, enhancement requests are always welcome if you can articulate a coherent solution to the existential limitation. But there's an even better way. Upon further study of the Predicate Programming Guide, I find that there are even more limitations to Core Data fetches with predicates. The most troubling is that: The Core Data SQL store supports only one to-many operation per query; therefore in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) from ALL, ANY, and IN. Do you have a specific scenario in which you need to perform nested to- many operations, yet you cannot use SUBQUERY or compound queries like OR ? Or is this troubling, in the sense that the universe is doomed to evaporate kind of way ? A much better way appears to be to fetch all objects from the store with no predicate and then use -[NSArray filteredArrayWithPredicate:]. This takes only one more line of code, solves all problems, and is supposedly cheaper too: This does not solve all problems, it most emphatically is NOT cheaper, and most assuredly does NOT scale. The atomic file approach is convenient and extremely simplistic. It also fails to scale gracefully past 10^2 objects. Optimizing memory management is very important for launch time and concurrency. The monster 8 core mac pro will be constrained by the memory bus (vastly slower compared to the sum computational power) if you're careless with memory usage. In addition to the memory bus bandwidth, concurrency is highly impacted by locality of reference. Keeping the voracious cpus fed with useful work is quite challenging for many pragmatic application tasks. Makes me wonder why NSFetchRequest even supports a predicate, since its predicate has all these limitations and is supposedly more expensive when compared to fetching all objects and then using - [NSArray filteredArrayWithPredicate:] ? ... If you redrew the entire window all the time, for each and every pixel change, and then marveled at the limitations, people might suggest clipping your drawing to the intersection of the dirty and visible regions. You might also use bounding rects as a convenient approximation of more complex region clipping calculations. These days even apps with modest requirements need bounding rects and region clipping for their data too. - Ben ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 22 Apr 2009, at 08:48, Ben Trumbull wrote: Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know Probably because nobody ever cared enough to file an enhancement request, and it didn't occur to us that writing 1 line of code to call filteredArrayWithPredicate was so troublesome. Calling -filteredArrayWithPredicate is no hassle, but for a large predicate, it has the bad performance of comparing a bunch of the persistent properties all over again, despite already knowing they'll match the predicate. Since I assume Core Data must do some kind of internal splitting up of the predicate in order to perform its fetch, I'd have thought it is in a good position to know what the remaining transient portion of the predicate is. I haven't filed a radar I admit as this hadn't become a issue for me yet, but may well do. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On Apr 22, 2009, at 02:12, Mike Abdullah wrote: On 22 Apr 2009, at 08:48, Ben Trumbull wrote: Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know Probably because nobody ever cared enough to file an enhancement request, and it didn't occur to us that writing 1 line of code to call filteredArrayWithPredicate was so troublesome. Calling -filteredArrayWithPredicate is no hassle, but for a large predicate, it has the bad performance of comparing a bunch of the persistent properties all over again, despite already knowing they'll match the predicate. Since I assume Core Data must do some kind of internal splitting up of the predicate in order to perform its fetch, I'd have thought it is in a good position to know what the remaining transient portion of the predicate is. You assume incorrectly. CoreData simply translates the predicate to SQL and passes it down to SQLite as a WHERE clause. Hence the lack of support for transient properties: SQLite has no idea what to do when you ask it to qualify by a column that doesn't exist in its schema. +Melissa ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
Problem solved. Although predicates cannot involve transient properties, you can follow relationships in a predicate using a key path. Obj-C Categories to the rescue… For example, you can write a category on NSNumber containing a method - letterGrade. Then use this to create the leftExpression in the row template. Now everything works nicely, except you need to dig into the template after creating it, get the views and change the title of the menu item from score.letterGrade to something like Letter Grade. But, in a real-life app, you need to do that for localization anyhow. On 2009 Apr 18, at 05:03, Mike Abdullah wrote: If it helps, the reason for Apple only supporting searching of persistent properties is for performance. If you're using the SQLite store for example, the predicate is not evaluated against the in- memory objects, but against the individual bits of data in the SQLite table. Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know… Yes, I figured something like that was going on but didn't want to get my hand slapped for trying to peek under Core Data's covers :) I also tried Keary's suggestion, and learned some stuff that may be useful to have in the list archives... On 2009 Apr 17, at 09:27, Keary Suska wrote: I am not really up to speed on NSPredicateEditor, but could you use - ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow: to convert the display case of grade = A-F to a predicate that is actually grade = = score range? I imagine you would need to construct a compound predicate with subpredicates (sub-rows). Either that or use the BETWEEN operator. Good question. Long answer: The method you refer to is one of five delegate methods of the NSPredicate superclass NSRuleEditor, three of which the delegate must implement. My guess is that implementing an NSPredicateEditor delegate is way to override the default row template generation. Might be what I need. However… • No documentation on how to implement a delegate. • Delegate seems to be ignored. I sent -setDelegate:self and echoed it back at several points. I implemented the three required methods, returning nil or 0. Expected result: Probably empty rule editors. Actual result: None of my delegate methods ever get invoked and everything still works as before. Echoing back -delegate returns self as expected. • Even if the delegate methods worked, I don't think I could implement them to return the required results. For example, ruleEditor:displayValueForCriterion:inRow: is supposed to return The criterion for which the value is required. I know what a criterion is in English but to write code one needs something precise. No explanation in either this document or the Predicate Programming Guide. Oh, and the type of it is id :( One clue I can find is that -criteriaForRow returns the same [items] as those returned from the delegate method ruleEditor:child:forCriterion:withRowType:. Aha -- so I send - criteriaForRow for each row up to -numberOfRows, log the results and get an array like this: 2009-04-19 17:22:45.521 TestApp[52864:10b] criteria for row 2: ( _NSPredicateEditorItem: 0x15b71ce0 [Name], _NSPredicateEditorItem: 0x15b6fbf0 [contains], _NSPredicateEditorItem: 0x15b70e80 [NSTextField: 0x15b50fe0] ) I can see what they're doing -- these are the three subviews in the template. But notice the underscore prefix on _NSPredicateEditorItem. Since I can't create those, I'd need a way to get this default answer and then tweak it, and I have no idea how to do either. Conclusion: Judging from these results and the lack of results in web searches, NSRuleEditor seems to be seldom used, NSPredicateEditor is rarely used, and probably delegate support in NSPredicateEditor is incomplete and unusable in Mac OS X 10.5. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 20, at 04:50, Jerry Krinock wrote: Problem solved But there's an even better way. Upon further study of the Predicate Programming Guide, I find that there are even more limitations to Core Data fetches with predicates. The most troubling is that: The Core Data SQL store supports only one to-many operation per query; therefore in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) from ALL, ANY, and IN. A much better way appears to be to fetch all objects from the store with no predicate and then use -[NSArray filteredArrayWithPredicate:]. This takes only one more line of code, solves all problems, and is supposedly cheaper too: If you use the Core Data framework, the array methods provide an efficient means of filtering an existing array of objects without —- as a fetch does —- requiring a round trip to a persistent data store. Furthermore, now since my left-side expressions don't need to be managed properties I don't need the categories -- I can just add simple derived-attribute getters to my target object class and predicate upon the derived attribute directly. So, I guess the reason why Apple has never noticed that Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness is because there's a better way to do it. Makes me wonder why NSFetchRequest even supports a predicate, since its predicate has all these limitations and is supposedly more expensive when compared to fetching all objects and then using - [NSArray filteredArrayWithPredicate:] ? It would have saved me a day on the learning curve had it not been there for me to hang myself with. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On Mon, April 20, 2009 11:02 am, Jerry Krinock wrote: Makes me wonder why NSFetchRequest even supports a predicate, since its predicate has all these limitations and is supposedly more expensive when compared to fetching all objects and then using - [NSArray filteredArrayWithPredicate:] ? It would have saved me a day on the learning curve had it not been there for me to hang myself with. filteredArrayWithPredicate: is only an option if you have a relatively small dataset. There's overhead to loading an object into memory, both in terms of memory and CPU cycles. Doing filtering in memory is a code smell. It generally signals that you're fetching against the wrong entity, or that your model needs to be tweaked to be more efficient. +Melissa ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On Apr 20, 2009, at 2:02 PM, Jerry Krinock wrote: A much better way appears to be to fetch all objects from the store with no predicate and then use -[NSArray filteredArrayWithPredicate:]. This takes only one more line of code, solves all problems, and is supposedly cheaper too: If you use the Core Data framework, the array methods provide an efficient means of filtering an existing array of objects without —- as a fetch does —- requiring a round trip to a persistent data store. [...] Makes me wonder why NSFetchRequest even supports a predicate, since its predicate has all these limitations and is supposedly more expensive when compared to fetching all objects and then using - [NSArray filteredArrayWithPredicate:] ? You are taking that quote out of context and misinterpreting it. If you already have an array of NSManagedObjects (fully realized, no faults), then it is going to be faster to filter that array than it is to execute a fetch request with a predicate, which always round trips to the store. They key is if you already have an array... (Or a set.) If you don't, then fetching a limited set with a predicate is (usually) going to be considerably faster than fetching all objects, and reducing the result after the fact with a predicate. Consider what happens when you fetch all objects of a particular type. Now consider what happens if you can give Core Data a predicate which says no, just these 3. Jim ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 4/20/09 11:02 AM, Jerry Krinock said: But there's an even better way. Upon further study of the Predicate Programming Guide, I find that there are even more limitations to Core Data fetches with predicates. The most troubling is that: The Core Data SQL store supports only one to-many operation per query; therefore in any predicate sent to the SQL store, there may be only one operator (and one instance of that operator) from ALL, ANY, and IN. Anyone know of a way to catch such 'SQL-unfriendly' predicates at compile time? Or with a static analyser? It strikes me that if one currently develops with with XML store, and then one day switches to the SQL store (say when it becomes compatible with GC apps, grrr) when one is in for lots of things suddenly breaking. -- Sean McBride, B. Eng s...@rogue-research.com Rogue Researchwww.rogue-research.com Mac Software Developer Montréal, Québec, Canada ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On 2009 Apr 20, at 11:24, Jim Correia wrote: On Apr 20, 2009, at 2:02 PM, Jerry Krinock wrote: Makes me wonder why NSFetchRequest even supports a predicate, since its predicate has all these limitations and is supposedly more expensive when compared to fetching all objects and then using - [NSArray filteredArrayWithPredicate:] ? You are taking that quote out of context and misinterpreting it. Yes, you're correct about that; I was being sloppy there. However, I did my own experiment on this with about 1200 objects a few months ago, each object having about 2 dozen attributes and a couple of relationships. A couple hundred bytes in each record. I compared the time for a Core Data fetch-with-predicate versus Core Data fetch- without-predicate followed by array filtering. Apples versus apples. The latter was slightly faster. For others this may not be true -- Always test performance in your own app -- and now I understand why NSFetchRequest supports a predicate. But in my case the search completes in milliseconds, and not having to program around the limitations of Core Data's fetch-with- predicate is a huge advantage. On 2009 Apr 20, at 13:09, Sean McBride wrote: It strikes me that if one currently develops with with XML store, and then one day switches to the SQL store ... when one is in for lots of things suddenly breaking. Yup. I gleefully chucked that off my list of things to retest after I ditched the Core Data fetch-with-predicate. On 2009 Apr 20, at 11:23, Melissa Turner wrote: Doing filtering in memory is a code smell. It generally signals that you're fetching against the wrong entity, or that your model needs to be tweaked to be more efficient. Well, when I first started with Core Data, my religion was: Oooo -- database -- relationships -- Oooo -- queries -- fast -- cool. But it doesn't always pan out. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
If it helps, the reason for Apple only supporting searching of persistent properties is for performance. If you're using the SQLite store for example, the predicate is not evaluated against the in- memory objects, but against the individual bits of data in the SQLite table. Of course, why Apple couldn't have then added automatic support for in-memory matching as the second step I don't know… On 17 Apr 2009, at 04:01, Jerry Krinock wrote: The fact that Core Data cannot fetch using a predicate based on transient properties [1] seems to greatly limit the utility of the NSPredicateEditor view, and makes me very sad. For example, say that my objects are student test results with a 'score' attribute and two dozen other properties. I could give the user an NSPredicateEditor and let them have oodles of fun constructing complex predicates. But what if I need the user to be able to set a predicate with a left-side-expression of letter grade and a right-side-expression popup menu showing 'A' - 'F'. If I could fetch based on a transient 'letterGrade' attribute, I could implement some custom accessors which would calculate 'letterGrade' from 'score' as needed, the predicate emitted from the NSPredicateEditor would just work, and life would be sweet. But since I can't use transient properties in my predicate, providing a popup like that in NSPredicateEditor seems to mean that I'm going to have to somehow deconstruct the compound predicate which Apple put so many man-years of engineering into, have Core Data do sub-fetches, then do my own filtering and put the results back together. I fear that writing bug-free code to handle the general compound predicate would be very time-consuming, and also it would be MVC hell with my NSPredicateEditor subclass (view) code wanting to have model logic such as if score 93, letterGrade = 'A'. Does anyone have any suggestions for a least worst workaround? Thanks, Jerry [1] http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html#/ /apple_ref/doc/uid/TP40002484 ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/cocoadev%40mikeabdullah.net This email sent to cocoa...@mikeabdullah.net ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
On Apr 16, 2009, at 9:01 PM, Jerry Krinock wrote: The fact that Core Data cannot fetch using a predicate based on transient properties [1] seems to greatly limit the utility of the NSPredicateEditor view, and makes me very sad. For example, say that my objects are student test results with a 'score' attribute and two dozen other properties. I could give the user an NSPredicateEditor and let them have oodles of fun constructing complex predicates. But what if I need the user to be able to set a predicate with a left-side-expression of letter grade and a right-side-expression popup menu showing 'A' - 'F'. If I could fetch based on a transient 'letterGrade' attribute, I could implement some custom accessors which would calculate 'letterGrade' from 'score' as needed, the predicate emitted from the NSPredicateEditor would just work, and life would be sweet. But since I can't use transient properties in my predicate, providing a popup like that in NSPredicateEditor seems to mean that I'm going to have to somehow deconstruct the compound predicate which Apple put so many man-years of engineering into, have Core Data do sub-fetches, then do my own filtering and put the results back together. I fear that writing bug-free code to handle the general compound predicate would be very time-consuming, and also it would be MVC hell with my NSPredicateEditor subclass (view) code wanting to have model logic such as if score 93, letterGrade = 'A'. I am not really up to speed on NSPredicateEditor, but could you use - ruleEditor:predicatePartsForCriterion:withDisplayValue:inRow: to convert the display case of grade = A-F to a predicate that is actually grade = = score range? I imagine you would need to construct a compound predicate with subpredicates (sub-rows). Either that or use the BETWEEN operator. HTH, Keary Suska Esoteritech, Inc. Demystifying technology for your home or business ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Core Data Fetches + Transient Properties + NSPredicateEditor = Sadness
The fact that Core Data cannot fetch using a predicate based on transient properties [1] seems to greatly limit the utility of the NSPredicateEditor view, and makes me very sad. For example, say that my objects are student test results with a 'score' attribute and two dozen other properties. I could give the user an NSPredicateEditor and let them have oodles of fun constructing complex predicates. But what if I need the user to be able to set a predicate with a left- side-expression of letter grade and a right-side-expression popup menu showing 'A' - 'F'. If I could fetch based on a transient 'letterGrade' attribute, I could implement some custom accessors which would calculate 'letterGrade' from 'score' as needed, the predicate emitted from the NSPredicateEditor would just work, and life would be sweet. But since I can't use transient properties in my predicate, providing a popup like that in NSPredicateEditor seems to mean that I'm going to have to somehow deconstruct the compound predicate which Apple put so many man-years of engineering into, have Core Data do sub-fetches, then do my own filtering and put the results back together. I fear that writing bug-free code to handle the general compound predicate would be very time-consuming, and also it would be MVC hell with my NSPredicateEditor subclass (view) code wanting to have model logic such as if score 93, letterGrade = 'A'. Does anyone have any suggestions for a least worst workaround? Thanks, Jerry [1] http://developer.apple.com/documentation/Cocoa/Conceptual/CoreData/Articles/cdFetching.html#/ /apple_ref/doc/uid/TP40002484 ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com