That sounds like what is going on. I'll give that a shot tomorrow. Thanks Chuck.
Sent from my iPhone > On Mar 19, 2017, at 2:59 AM, Chuck Hill <ch...@gevityinc.com> wrote: > > Hi Ricardo, > > You need to create a branch (push from your local) in your GitHub fork of > Wonder for each set of changes in GitHub (aka a Feature Branch), then make a > pull request from that branch to Wonder. Otherwise all of your changes get > inter-mixed. > > Chuck > > > From: Ricardo Parada <rpar...@mac.com> > Date: Saturday, March 18, 2017 at 11:22 PM > To: "webobjects-dev@lists.apple.com" <webobjects-dev@lists.apple.com> > Cc: Markus Ruggiero <mailingli...@kataputt.com>, Paul Hoadley > <pa...@logicsquad.net>, "koa...@icloud.com" <koa...@icloud.com>, > "g...@knuckleheads.net" <g...@knuckleheads.net>, Chuck Hill > <ch...@gevityinc.com>, "aa...@chatnbike.com" <aa...@chatnbike.com> > Subject: Re: ERXQuery Preview > > Hi all, > > As promised, I have committed ERXQuery to my Wonder clone on GitHub, i.e. > rparada/wonder. I just need help creating the pull request. :-) > > It turns out that I created first a pull request for ERXExtensions.java > unrelated to ERXQuery. Now when I tried to create the pull request for > ERXQuery it just seems to show the previous pull request. So I’m not sure > what is going on. I don’t have much experience with GitHub. > > Anyways, the ERXQuery is an additive change to Wonder and consists of only > three files: ERXQuery.java, ERXQueryAttributes and ERXQueryEOAttribute. It’s > the last two commits in rparada/wonder. > > I took the time to polish the API a bit more. I think the API came out nicer > than what I had the first time around. Specially the single variadic > select() method that allows you to specify EOAttributes, Strings, ERXKeys, or > any Iterable containing these. Same for groupBy(). And the a similar > technique with the orderBy() which can take EOSortOrderings or any Iterable > (ERXSortOrderings, NSArray, List, Collection). > > The documentation is more extensive now. I have included here a copy of the > ERXQuery class from the javadoc tab in my Eclipse. > > I have tested with ORACLE which is the easiest for me to test. It would be > great to hear others using this with other databases (h2, derby, mssql, > mysql, frontbase, etc.) > > > ERXQuery.java > Overview > This class has a fluent API that mimics a select statement: > > NSArray<NSDictionary<String,Object>> records = > ERXQuery.create() > .select (keys) > .from (entity) > .where (qualifier) > .groupBy (groupings) > .having (havingQualifier) > .orderBy (sortings) > .fetch(); > > It allows you to use EOF/Wonder higher-level constructs (qualifiers, > attributes, orderings, key paths, ERXKeys, etc.) to create a query that looks > like this: > > SELECT ... > FROM ... > WHERE ... > GROUP BY ... > HAVING ... > ORDER BY ... > > > Specifying the Attributes to Fetch > The select() method is very flexible and powerful. It accepts a variable > number of objects of different types that specify the attributes to fetch. > These objects can be EOAttributes, ERXKeys, Strings. You may also specify > NSArray or List objects containing any combination of these (EOAttributes, > ERXKeys, Strings). > > The ERXKeys and String objects correspond to keys and key paths to the > attributes to fetch, i.e. "customer.name". The keys and key paths can also be > relationships to objects, i.e. "customer" which translate into a fetch of > foreign keys used to build object faults and return them in the results. > > You may call the select() method multiple times to keep adding to the list of > attributes to fetch. > > Using Ad Hoc Attributes > It is very common to aggregate attributes in these queries. For this purpose, > you may want to create what ERXQuery refers to as ad hoc attributes. These > attributes have a definition but are not physically attached to the entity. > You can use the ERXQueryAttributes class to easily create multiple ad hoc > attributes. The definition of the attribute can reference relationships and > attributes as shown below. If you just want to create a single ad hoc > attribute you may use the ERXQueryEOAttribute class. > > // Using a single query against the order entity to count the number of > // orders and line items that match an order qualifier. > > ERXQueryAttributes attributes = ERXQueryAttributes.create(orderEntity) > .add("itemCount", "COUNT(DISTINCT lineItems.lineItemID)", "intNumber") > .add("orderCount", "COUNT(DISTINCT orderID)", "intNumber"); > > ERXQuery query = > ERXQuery.create() > .select (attributes) > .from (orderEntity) > .where (qualifier); > > // Fetch into a dictionary > NSDictionary<String,Object> row = query.fetch().lastObject(); > > int orderCount = ((Number) row.objectForKey("orderCount")).intValue(); > int itemCount = ((Number) row.objectForKey("itemCount")).intValue(); > > Fetching Results into a Custom Class > It is useful to fetch results into objects of a custom class. This allows you > to have type checking on the getter methods and add methods for computed > values on the data fetched. For the example above you could have fetched the > results into a custom class as follows: > > // Fetch into object instances of the a custom Result class > Result result = query.fetch(editingContext, Result.class).lastObject(); > int orderCount = result.orderCount(); > int itemCount = result.itemCount(); > > The Result custom class would have to be defined as shown below. The > constructor may keep the mutable dictionary passed in to the constructor or > make an immutable copy from it as shown below. > > public static class Result { > NSDictionary<String,Object> data; > > public Result(EOEditingContext ec, NSMutableDictionary<String,Object> > row) { > data = row.immutableClone(); > } > > public int itemCount() { > return ((Number) data.objectForKey("itemCount")).intValue(); > } > public int orderCount() { > return ((Number) data.objectForKey("orderCount")).intValue(); > } > } > } > > In general, fetching into a custom class can be done in several ways: > // If your custom class has a constructor that takes an editing context and > // a mutable dictionary then it is very simple: > NSArray<Foo> objs = query.fetch(editingContext, Foo.class); > > // Using java 8 or later you may use a lambda expression: > NSArray<Foo> objs = query.fetch(editingContext, (ec, row) -> new Foo(ec, > row)); > > > // You may also create an implementation of the RecordConstructor > // functional interface and pass it into the fetch method: > ERXQuery.RecordConstructor<Foo> recordConstructor = > new ERXQuery.RecordConstructor<Foo> { > @Override > public Foo constructRecord(EOEditingContext ec, NSMutableDictionary > row) { > return new Foo(ec, row); > } > }; > NSArray objs = query.fetch(editingContext, recordConstructor) > } > > Augmenting Row Values > You can have entries from a dictionary added in to the rows fetched from the > database. The mutable dictionary passed in to the record constructor will > contain the data fetched along with the keys/values from this > recordInitializationValues dictionary. > > NSDictionary<String,Object> recordInitializationValues = new > NSDictionary<>((Object)2017, "preferredYear"); > NSArray<Foo> objs = query.fetch(editingContext, recordInitializationValues, > Foo.class); > Foo aFoo = objs.lastObject(); > int preferredYear = aFoo.preferredYear(); // i.e. 2017 > > Defining Ad Hoc Attributes in the Entity > An alternate way to define your ad hoc attributes is to define them in your > entity and flagging them as non-class properties. Unlike ERXQueryEOAttribute > objects, these attributes will be instances of EOAttribute and reside in your > entity. They may be a bit distracting when looking at the entity if you have > a lot but this method allows you to reuse all the existing attributes and > relationships already defined in the entity and does not require code for > creating the attributes. > > One incovenience is that eogeneration templates do not generate ERXKeys for > non-class properties. However, this problem could be overcome by enhancing > the eogeneration templates to generate ERXKeys for derived non-class property > attributes. > > // Fetch last year's customer order totals exceeding $1000 in descending > order > NSArray<OrderSummary> lastYearTopSales = > ERXQuery.create() > .select (Order.CUSTOMER) // customer to-one > .select (Order.SUM_TOTAL_AMOUNT) // non-class property defined > as SUM(totalAmount) > .from (Order.ENTITY_NAME) > .where (lastYearQualifier) > .groupBy (Order.CUSTOMER) > .having (Order.SUM_TOTAL_AMOUNT.greaterThan(1000.00)) > .orderBy (Order.SUM_TOTAL_AMOUNT.desc()) > .fetch(editingContext, OrderSummary.class); > > // Peek at top sale record > OrderSummary topSale = ERXArrayUtilities.firstObject(lastYearTopSales); > if (topSale != null) { > System.out.println("Customer " + topSale.customer().fullName() > + " ordered " + moneyFormatter.format(topSale.sumTotalAmount())); > } > } > > It would be nice to enhance the eogeneration templates to also create a > custom class for fetching the results, i.e. WonderEntitySummary.java and > _WonderEntitySummary.java with the getters for attributes/relationships in > the entity including derived non-class properties. These templates would be > used when the entity has a user info key with ERXQuery.enabled=yes. > > Limitations > Ad hoc attributes created with ERXQueryAttributes or ERXQueryEOAttribute are > not physically attached to an entity. When EOF generates SQL for a qualifier > it calls sqlStringForSQLExpression(q,e) where q is an EOQualifier and e is an > EOSQLExpression. Qualifiers then try to reach the attribute by following the > qualifier's referenced keys starting with the entity of the EOSQLExpression, > i.e. e.entity(). > > The current workaround used by ERXQuery is to temporarily add to the entity > any ad hoc attributes referenced by the qualifiers. This typically happens > with the havingQualifier which normally references the ad hoc attributes > corresponding to aggregated attributes. For example, "sumTotalAmount" defined > as "SUM(totalAmount)" could be used in a having qualifier: > > // When grouping orders by customer and fetching sumTotalAmount we may want > to have > // this having qualifier so that we only fetch the groups totaling more > than 1000. > EOQualifier havingQualifier = ERXQ.greaterThan("sumTotalAmount", new > BigDecimal(1000.0)); > > However, if you were to define your "sumTotalAmount" attribute in your entity > as a derived non-class property with definition "SUM(totalAmount)" then > ERXQuery doesn't have to add the attribute to the entity. > > Defaults for Behavior Properties > 1. er.extensions.eof.ERXQuery.useBindVariables=false > 2. er.extensions.eof.ERXQuery.useEntityRestrictingQualifiers=true > 3. er.extensions.eof.ERXQuery.removesForeignKeysFromRowValues=true > Author: > Ricardo J. Parada > > > > On Mar 14, 2017, at 8:31 AM, Ricardo Parada <rpar...@mac.com> wrote: > > > > Thanks all for the feedback. I'll be adding it by the weekend I hope. > > > On Mar 14, 2017, at 4:29 AM, Markus Ruggiero <mailingli...@kataputt.com> > wrote: > > Great thing, looks very useful. > > On 11.03.2017, at 23:41, Ricardo Parada <rpar...@mac.com> wrote: > > Hi all, > > Over the years, I’ve worked on an class for doing ad hoc queries. This class > has gotten better and better. At first, the API of this class and some > implementation details were not ready for public consumption in my opinion. > > However, recently I took the time to polish the code as much as possible and > if I can get my employer's approval I would like to contribute this code to > project Wonder which has given us so much in return during the years. > > Here is a preview of its functionality. Please let me know if you guys think > this would be a useful contribution. > ERXQuery.java > This class has a fluent API that mimics a select statement: > NSArray<NSDictionary<String,Object>> records = > ERXQuery.create() > .select (keys) > .from (entity) > .where (qualifier) > .groupBy (groupings) > .having (havingQualifier) > .orderBy (sortings) > .fetch(); > Overview > ERXQuery allows you to use EOF constructs (EOQualifiers, EOAttributes, > EOSortOrdering, EOAttribute names, relationships, etc.) to create queries of > the form: > SELECT ... > FROM ... > WHERE ... > GROUP BY ... > HAVING ... > ORDER BY ... > Using Ad Hoc Attributes > You may use the ERXAdHocAttributes class to easily create ad hoc attributes > to use with your query. For example, the code below creates two ad hoc > EOAttributes. An ad hoc attribute is an EOAttribute that is not physically > attached to an entity and that has a definition. They are useful for > aggregating other attributes. The definition of the attribute can reference > relationships and attributes as shown below. > // Using a single query against the order entity, count the number of > // orders and line items that match the qualifier. > ERXAdHocAttributes attributes = ERXAdHocAttributes.create(orderEntity) > .add("itemCount", "COUNT(DISTINCT lineItems.lineItemID)", "intNumber") > .add("orderCount", "COUNT(DISTINCT orderID)", "intNumber"); > NSDictionary<String,Object> row = > ERXQuery.create() > .select (attributes) > .from (orderEntity) > .where (qualifier) > .fetch() > .lastObject(); > int orderCount = ((Number) row.objectForKey("orderCount")).intValue(); > int itemCount = ((Number) row.objectForKey("itemCount")).intValue(); > Fetching into a Custom Record Class > You can also fetch using a custom class of your choice, i.e. Foo, as shown > below: > // Using java >= 8 is easy with a lambda expression > NSArray<Foo> objs = query.fetch(editingContext, (ec, row) -> new Foo(ec, > row)); > > // Using java < 8 you must provide a RecordConstructor > ERXQuery.RecordConstructor<Foo> recordConstructor = > new ERXQuery.RecordConstructor<Foo> { > @Override > public Foo constructRecord(EOEditingContext ec, NSMutableDictionary > row) { > return new Foo(ec, row); > } > }; > NSArray objs = query.fetch(editingContext, recordConstructor); > Author: Ricardo J. Parada > _______________________________________________ > Do not post admin requests to the list. They will be ignored. > Webobjects-dev mailing list (Webobjects-dev@lists.apple.com) > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/webobjects-dev/mailinglists%40kataputt.com > > This email sent to mailingli...@kataputt.com > > > > Markus Ruggiero > mailingli...@kataputt.com > Check out the new book about Project Wonder and WebObjects on > http://learningthewonders.com/ > > > > > > > >
_______________________________________________ Do not post admin requests to the list. They will be ignored. Webobjects-dev mailing list (Webobjects-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com