You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2010/03/10 20:12:06 UTC
svn commit: r921518 [2/2] - in /cayenne/sandbox/cayenne-gwt/src:
main/java/org/apache/cayenne/gwt/client/
main/java/org/apache/cayenne/gwt/server/
main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/
main/resources/org/apache/cayenne/query/...
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplate.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplate.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplate.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplate.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,485 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cayenne.map.SQLResult;
+import org.apache.commons.collections.Transformer;
+
+/**
+ * A query that executes unchanged (except for template preprocessing) "raw" SQL specified
+ * by the user. <h3>Template Script</h3>
+ * <p>
+ * SQLTemplate stores a dynamic template for the SQL query that supports parameters and
+ * customization using Velocity scripting language. The most straightforward use of
+ * scripting abilities is to build parameterized queries. For example:
+ * </p>
+ *
+ * <pre>
+ * SELECT ID, NAME FROM SOME_TABLE WHERE NAME LIKE $a
+ * </pre>
+ * <p>
+ * <i>For advanced scripting options see "Scripting SQLTemplate" chapter in the User
+ * Guide. </i>
+ * </p>
+ * <h3>Per-Database Template Customization</h3>
+ * <p>
+ * SQLTemplate has a {@link #getDefaultTemplate() default template script}, but also it
+ * allows to configure multiple templates and switch them dynamically. This way a single
+ * query can have multiple "dialects" specific to a given database.
+ * </p>
+ * <h3>Parameter Sets</h3>
+ * <p>
+ * SQLTemplate supports multiple sets of parameters, so a single query can be executed
+ * multiple times with different parameters. "Scrolling" through parameter list is done by
+ * calling {@link #parametersIterator()}. This iterator goes over parameter sets,
+ * returning a Map on each call to "next()"
+ * </p>
+ *
+ * @since 1.1
+ */
+public class SQLTemplate extends AbstractQuery implements ParameterizedQuery {
+
+ static final String COLUMN_NAME_CAPITALIZATION_PROPERTY = "cayenne.SQLTemplate.columnNameCapitalization";
+
+ private static final Transformer nullMapTransformer = new Transformer() {
+
+ public Object transform(Object input) {
+ return (input != null) ? input : Collections.EMPTY_MAP;
+ }
+ };
+
+ protected String defaultTemplate;
+ protected Map<String, String> templates;
+ protected Map<String, ?>[] parameters;
+ protected CapsStrategy columnNamesCapitalization;
+ protected SQLResult result;
+
+ SQLTemplateMetadata metaData = new SQLTemplateMetadata();
+
+ /**
+ * Creates an empty SQLTemplate. Note this constructor does not specify the "root" of
+ * the query, so a user must call "setRoot" later to make sure SQLTemplate can be
+ * executed.
+ *
+ * @since 1.2
+ */
+ public SQLTemplate() {
+ }
+
+ /**
+ * @since 1.2
+ */
+ public SQLTemplate(String objEntityName, String defaultTemplate) {
+ setRoot(objEntityName);
+ setDefaultTemplate(defaultTemplate);
+ }
+
+ /**
+ * Initializes query parameters using a set of properties.
+ *
+ * @since 1.1
+ */
+ public void initWithProperties(Map<String, ?> properties) {
+ // must init defaults even if properties are empty
+ metaData.initWithProperties(properties);
+
+ if (properties == null) {
+ properties = Collections.EMPTY_MAP;
+ }
+
+ Object columnNamesCapitalization = properties
+ .get(COLUMN_NAME_CAPITALIZATION_PROPERTY);
+ this.columnNamesCapitalization = (columnNamesCapitalization != null)
+ ? CapsStrategy.valueOf(columnNamesCapitalization
+ .toString()
+ .toUpperCase())
+ : null;
+ }
+
+ /**
+ * Returns the number of parameter sets.
+ */
+ public int parametersSize() {
+ return (parameters != null) ? parameters.length : 0;
+ }
+
+ /**
+ * Returns a new query built using this query as a prototype and a new set of
+ * parameters.
+ */
+ public SQLTemplate queryWithParameters(Map<String, ?>... parameters) {
+ // create a query replica
+ SQLTemplate query = new SQLTemplate();
+
+ query.setRoot(root);
+ query.setDefaultTemplate(getDefaultTemplate());
+
+ if (templates != null) {
+ query.templates = new HashMap<String, String>(templates);
+ }
+
+ query.metaData.copyFromInfo(this.metaData);
+ query.setParameters(parameters);
+ query.setColumnNamesCapitalization(this.getColumnNamesCapitalization());
+
+ return query;
+ }
+
+ /**
+ * Creates and returns a new SQLTemplate built using this query as a prototype and
+ * substituting template parameters with the values from the map.
+ *
+ * @since 1.1
+ */
+ public Query createQuery(Map<String, ?> parameters) {
+ return queryWithParameters(parameters);
+ }
+
+ /**
+ * @deprecated since 3.0 {@link #getCacheStrategy()} replaces this method.
+ */
+ @Deprecated
+ public String getCachePolicy() {
+ return metaData.getCachePolicy();
+ }
+
+ /**
+ * @deprecated since 3.0 {@link #setCacheStrategy(QueryCacheStrategy)} replaces this
+ * method.
+ */
+ @Deprecated
+ public void setCachePolicy(String policy) {
+ metaData.setCachePolicy(policy);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public QueryCacheStrategy getCacheStrategy() {
+ return metaData.getCacheStrategy();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setCacheStrategy(QueryCacheStrategy strategy) {
+ metaData.setCacheStrategy(strategy);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public String[] getCacheGroups() {
+ return metaData.getCacheGroups();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setCacheGroups(String... cacheGroups) {
+ this.metaData.setCacheGroups(cacheGroups);
+ }
+
+ public int getFetchLimit() {
+ return metaData.getFetchLimit();
+ }
+
+ public void setFetchLimit(int fetchLimit) {
+ this.metaData.setFetchLimit(fetchLimit);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public int getFetchOffset() {
+ return metaData.getFetchOffset();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setFetchOffset(int fetchOffset) {
+ metaData.setFetchOffset(fetchOffset);
+ }
+
+ public int getPageSize() {
+ return metaData.getPageSize();
+ }
+
+ public void setPageSize(int pageSize) {
+ metaData.setPageSize(pageSize);
+ }
+
+ public void setFetchingDataRows(boolean flag) {
+ metaData.setFetchingDataRows(flag);
+ }
+
+ public boolean isFetchingDataRows() {
+ return metaData.isFetchingDataRows();
+ }
+
+ /**
+ * @deprecated since 3.0. With introduction of the cache strategies this setting is
+ * redundant, although it is still being taken into account. It will be
+ * removed in the later versions of Cayenne.
+ */
+ @Deprecated
+ public boolean isRefreshingObjects() {
+ return metaData.isRefreshingObjects();
+ }
+
+ /**
+ * @deprecated since 3.0. With introduction of the cache strategies this setting is
+ * redundant, although it is still being taken into account. It will be
+ * removed in the later versions of Cayenne.
+ */
+ @Deprecated
+ public void setRefreshingObjects(boolean flag) {
+ // noop
+ }
+
+ /**
+ * @deprecated since 3.0. Inheritance resolving is not optional anymore.
+ */
+ @Deprecated
+ public boolean isResolvingInherited() {
+ return true;
+ }
+
+ /**
+ * @deprecated since 3.0. Inheritance resolving is not optional anymore.
+ */
+ @Deprecated
+ public void setResolvingInherited(boolean b) {
+ // noop
+ }
+
+ /**
+ * Returns default SQL template for this query.
+ */
+ public String getDefaultTemplate() {
+ return defaultTemplate;
+ }
+
+ /**
+ * Sets default SQL template for this query.
+ */
+ public void setDefaultTemplate(String string) {
+ defaultTemplate = string;
+ }
+
+ /**
+ * Returns a template for key, or a default template if a template for key is not
+ * found.
+ */
+ public synchronized String getTemplate(String key) {
+ if (templates == null) {
+ return defaultTemplate;
+ }
+
+ String template = templates.get(key);
+ return (template != null) ? template : defaultTemplate;
+ }
+
+ /**
+ * Returns template for key, or null if there is no template configured for this key.
+ * Unlike {@link #getTemplate(String)}this method does not return a default template
+ * as a failover strategy, rather it returns null.
+ */
+ public synchronized String getCustomTemplate(String key) {
+ return (templates != null) ? templates.get(key) : null;
+ }
+
+ /**
+ * Adds a SQL template string for a given key. Note the the keys understood by Cayenne
+ * must be fully qualified adapter class names. This way the framework can related
+ * current DataNode to the right template. E.g.
+ * "org.apache.cayenne.dba.oracle.OracleAdapter" is a key that should be used to setup
+ * an Oracle-specific template.
+ *
+ * @see #setDefaultTemplate(String)
+ */
+ public synchronized void setTemplate(String key, String template) {
+ if (templates == null) {
+ templates = new HashMap<String, String>();
+ }
+
+ templates.put(key, template);
+ }
+
+ public synchronized void removeTemplate(String key) {
+ if (templates != null) {
+ templates.remove(key);
+ }
+ }
+
+ /**
+ * Returns a collection of configured template keys.
+ */
+ public synchronized Collection<String> getTemplateKeys() {
+ return (templates != null) ? Collections.unmodifiableCollection(templates
+ .keySet()) : Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Utility method to get the first set of parameters, since most queries will only
+ * have one.
+ */
+ public Map<String, ?> getParameters() {
+ Map<String, ?> map = (parameters != null && parameters.length > 0)
+ ? parameters[0]
+ : null;
+ return (map != null) ? map : Collections.EMPTY_MAP;
+ }
+
+ /**
+ * Utility method to initialize query with one or more sets of parameters.
+ */
+ public void setParameters(Map<String, ?>... parameters) {
+
+ if (parameters == null) {
+ this.parameters = null;
+ }
+ else {
+ // clone parameters to ensure that we don't have immutable maps that are not
+ // serializable with Hessian...
+ this.parameters = new Map[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ this.parameters[i] = parameters[i] != null ? new HashMap<String, Object>(
+ parameters[i]) : new HashMap<String, Object>();
+ }
+ }
+ }
+
+ /**
+ * @since 1.2
+ */
+ public PrefetchTreeNode getPrefetchTree() {
+ return metaData.getPrefetchTree();
+ }
+
+ /**
+ * Adds a prefetch.
+ *
+ * @since 1.2
+ */
+ public PrefetchTreeNode addPrefetch(String prefetchPath) {
+ // by default use JOINT_PREFETCH_SEMANTICS
+ return metaData.addPrefetch(
+ prefetchPath,
+ PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
+ }
+
+ /**
+ * @since 1.2
+ */
+ public void removePrefetch(String prefetch) {
+ metaData.removePrefetch(prefetch);
+ }
+
+ /**
+ * Adds all prefetches from a provided collection.
+ *
+ * @since 1.2
+ */
+ public void addPrefetches(Collection<String> prefetches) {
+ metaData.addPrefetches(prefetches, PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
+ }
+
+ /**
+ * Clears all prefetches.
+ *
+ * @since 1.2
+ */
+ public void clearPrefetches() {
+ metaData.clearPrefetches();
+ }
+
+ /**
+ * Returns a column name capitalization policy applied to selecting queries. This is
+ * used to simplify mapping of the queries like "SELECT * FROM ...", ensuring that a
+ * chosen Cayenne column mapping strategy (e.g. all column names in uppercase) is
+ * portable across database engines that can have varying default capitalization.
+ * Default (null) value indicates that column names provided in result set are used
+ * unchanged.
+ *
+ * @since 3.0
+ */
+ public CapsStrategy getColumnNamesCapitalization() {
+ return columnNamesCapitalization != null
+ ? columnNamesCapitalization
+ : CapsStrategy.DEFAULT;
+ }
+
+ /**
+ * Sets a column name capitalization policy applied to selecting queries. This is used
+ * to simplify mapping of the queries like "SELECT * FROM ...", ensuring that a chosen
+ * Cayenne column mapping strategy (e.g. all column names in uppercase) is portable
+ * across database engines that can have varying default capitalization. Default
+ * (null) value indicates that column names provided in result set are used unchanged.
+ * <p/>
+ * Note that while a non-default setting is useful for queries that do not rely on a
+ * #result directive to describe columns, it works for all SQLTemplates the same way.
+ *
+ * @since 3.0
+ */
+ public void setColumnNamesCapitalization(CapsStrategy columnNameCapitalization) {
+ this.columnNamesCapitalization = columnNameCapitalization;
+ }
+
+ /**
+ * Sets an optional explicit mapping of the result set. If result set mapping is
+ * specified, the result of SQLTemplate may not be a normal list of Persistent objects
+ * or DataRows, instead it will follow the {@link SQLResult} rules.
+ *
+ * @since 3.0
+ */
+ public void setResult(SQLResult resultSet) {
+ this.result = resultSet;
+ }
+
+ /**
+ * @since 3.0
+ */
+ public SQLResult getResult() {
+ return result;
+ }
+
+ /**
+ * Sets statement's fetch size (0 for no default size)
+ * @since 3.0
+ */
+ public void setStatementFetchSize(int size) {
+ metaData.setStatementFetchSize(size);
+ }
+
+ /**
+ * @return statement's fetch size
+ * @since 3.0
+ */
+ public int getStatementFetchSize() {
+ return metaData.getStatementFetchSize();
+ }
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplateMetadata.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplateMetadata.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplateMetadata.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SQLTemplateMetadata.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,26 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.query;
+
+
+/**
+ * @since 3.0
+ */
+class SQLTemplateMetadata extends BaseQueryMetadata {
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQuery.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQuery.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQuery.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQuery.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,375 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+
+/**
+ * A query that selects persistent objects of a certain type or "raw data" (aka DataRows).
+ * Supports expression qualifier, multiple orderings and a number of other parameters that
+ * serve as runtime hints to Cayenne on how to optimize the fetch and result processing.
+ */
+public class SelectQuery extends QualifiedQuery implements ParameterizedQuery {
+
+ public static final String DISTINCT_PROPERTY = "cayenne.SelectQuery.distinct";
+ public static final boolean DISTINCT_DEFAULT = false;
+
+ protected List<Ordering> orderings;
+ protected boolean distinct;
+
+ SelectQueryMetadata metaData = new SelectQueryMetadata();
+
+ /** Creates an empty SelectQuery. */
+ public SelectQuery() {
+ }
+
+ /**
+ * Creates SelectQuery with <code>objEntityName</code> parameter.
+ */
+ public SelectQuery(String objEntityName) {
+ this(objEntityName, null);
+ }
+
+ /**
+ * Creates SelectQuery with <code>objEntityName</code> and <code>qualifier</code>
+ * parameters.
+ */
+ public SelectQuery(String objEntityName, Expression qualifier) {
+ init(objEntityName, qualifier);
+ }
+
+ private void init(Object root, Expression qualifier) {
+ this.setRoot(root);
+ this.setQualifier(qualifier);
+ }
+
+ /**
+ * Initializes query parameters using a set of properties.
+ *
+ * @since 1.1
+ */
+ public void initWithProperties(Map<String, ?> properties) {
+
+ // must init defaults even if properties are empty
+ if (properties == null) {
+ properties = Collections.EMPTY_MAP;
+ }
+
+ Object distinct = properties.get(DISTINCT_PROPERTY);
+
+ // init ivars from properties
+ this.distinct = (distinct != null)
+ ? "true".equalsIgnoreCase(distinct.toString())
+ : DISTINCT_DEFAULT;
+
+ metaData.initWithProperties(properties);
+ }
+
+ /**
+ * A shortcut for {@link #queryWithParameters(Map, boolean)}that prunes parts of
+ * qualifier that have no parameter value set.
+ */
+ public SelectQuery queryWithParameters(Map<String, ?> parameters) {
+ return queryWithParameters(parameters, true);
+ }
+
+ /**
+ * Returns a query built using this query as a prototype, using a set of parameters to
+ * build the qualifier.
+ *
+ * @see org.apache.cayenne.exp.Expression#expWithParameters(java.util.Map, boolean)
+ * parameter substitution.
+ */
+ public SelectQuery queryWithParameters(Map<String, ?> parameters, boolean pruneMissing) {
+ // create a query replica
+ SelectQuery query = new SelectQuery();
+ query.setDistinct(distinct);
+
+ query.metaData.copyFromInfo(this.metaData);
+ query.setRoot(root);
+
+ if (orderings != null) {
+ query.addOrderings(orderings);
+ }
+
+ // substitute qualifier parameters
+ if (qualifier != null) {
+ query.setQualifier(qualifier.expWithParameters(parameters, pruneMissing));
+ }
+
+ return query;
+ }
+
+ /**
+ * Creates and returns a new SelectQuery built using this query as a prototype and
+ * substituting qualifier parameters with the values from the map.
+ *
+ * @since 1.1
+ */
+ public Query createQuery(Map<String, ?> parameters) {
+ return queryWithParameters(parameters);
+ }
+
+ /**
+ * Adds ordering specification to this query orderings.
+ */
+ public void addOrdering(Ordering ordering) {
+ nonNullOrderings().add(ordering);
+ }
+
+ /**
+ * Adds a list of orderings.
+ */
+ public void addOrderings(List<Ordering> orderings) {
+ nonNullOrderings().addAll(orderings);
+ }
+
+ /**
+ * Adds ordering specification to this query orderings.
+ *
+ * @since 3.0
+ */
+ public void addOrdering(String sortPathSpec, SortOrder order) {
+ addOrdering(new Ordering(sortPathSpec, order));
+ }
+
+ /**
+ * Removes ordering.
+ *
+ * @since 1.1
+ */
+ public void removeOrdering(Ordering ordering) {
+ if (orderings != null) {
+ orderings.remove(ordering);
+ }
+ }
+
+ /**
+ * Returns a list of orderings used by this query.
+ */
+ public List<Ordering> getOrderings() {
+ return (orderings != null) ? orderings : Collections.EMPTY_LIST;
+ }
+
+ /**
+ * Clears all configured orderings.
+ */
+ public void clearOrderings() {
+ orderings = null;
+ }
+
+ /**
+ * Returns true if this query returns distinct rows.
+ */
+ public boolean isDistinct() {
+ return distinct;
+ }
+
+ /**
+ * Sets <code>distinct</code> property that determines whether this query returns
+ * distinct row.
+ */
+ public void setDistinct(boolean distinct) {
+ this.distinct = distinct;
+ }
+
+ /**
+ * Adds one or more aliases for the qualifier expression path. Aliases serve to
+ * instruct Cayenne to generate separate sets of joins for overlapping paths, that
+ * maybe needed for complex conditions. An example of an <i>implicit<i> splits is this
+ * method: {@link ExpressionFactory#matchAllExp(String, Object...)}.
+ *
+ * @since 3.0
+ */
+ public void aliasPathSplits(String path, String... aliases) {
+ metaData.addPathSplitAliases(path, aliases);
+ }
+
+ /**
+ * @since 1.2
+ */
+ public PrefetchTreeNode getPrefetchTree() {
+ return metaData.getPrefetchTree();
+ }
+
+ /**
+ * @since 1.2
+ */
+ public void setPrefetchTree(PrefetchTreeNode prefetchTree) {
+ metaData.setPrefetchTree(prefetchTree);
+ }
+
+ /**
+ * Adds a prefetch with specified relationship path to the query.
+ *
+ * @since 1.2 signature changed to return created PrefetchTreeNode.
+ */
+ public PrefetchTreeNode addPrefetch(String prefetchPath) {
+ return metaData.addPrefetch(prefetchPath, PrefetchTreeNode.UNDEFINED_SEMANTICS);
+ }
+
+ /**
+ * Clears all stored prefetch paths.
+ */
+ public void clearPrefetches() {
+ metaData.clearPrefetches();
+ }
+
+ /**
+ * Removes prefetch.
+ *
+ * @since 1.1
+ */
+ public void removePrefetch(String prefetchPath) {
+ metaData.removePrefetch(prefetchPath);
+ }
+
+ /**
+ * Returns <code>true</code> if this query should produce a list of data rows as
+ * opposed to DataObjects, <code>false</code> for DataObjects. This is a hint to
+ * QueryEngine executing this query.
+ */
+ public boolean isFetchingDataRows() {
+ return metaData.isFetchingDataRows();
+ }
+
+ /**
+ * Sets query result type. If <code>flag</code> parameter is <code>true</code>, then
+ * results will be in the form of data rows.
+ * <p>
+ * </p>
+ */
+ public void setFetchingDataRows(boolean flag) {
+ metaData.setFetchingDataRows(flag);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public QueryCacheStrategy getCacheStrategy() {
+ return metaData.getCacheStrategy();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setCacheStrategy(QueryCacheStrategy strategy) {
+ metaData.setCacheStrategy(strategy);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public String[] getCacheGroups() {
+ return metaData.getCacheGroups();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setCacheGroups(String... cacheGroups) {
+ this.metaData.setCacheGroups(cacheGroups);
+ }
+
+ /**
+ * Returns the fetchOffset.
+ *
+ * @since 3.0
+ */
+ public int getFetchOffset() {
+ return metaData.getFetchOffset();
+ }
+
+ /**
+ * Returns the fetchLimit.
+ */
+ public int getFetchLimit() {
+ return metaData.getFetchLimit();
+ }
+
+ /**
+ * Sets the fetchLimit.
+ */
+ public void setFetchLimit(int fetchLimit) {
+ this.metaData.setFetchLimit(fetchLimit);
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void setFetchOffset(int fetchOffset) {
+ this.metaData.setFetchOffset(fetchOffset);
+ }
+
+ /**
+ * Returns <code>pageSize</code> property. Page size is a hint telling Cayenne
+ * QueryEngine that query result should use paging instead of reading the whole result
+ * in the memory.
+ */
+ public int getPageSize() {
+ return metaData.getPageSize();
+ }
+
+ /**
+ * Sets <code>pageSize</code> property.
+ *
+ * @param pageSize The pageSize to set
+ */
+ public void setPageSize(int pageSize) {
+ throw new UnsupportedOperationException("Paging is not supported on GWT client");
+ //metaData.setPageSize(pageSize);
+ }
+
+ /**
+ * Returns a list that internally stores orderings, creating it on demand.
+ *
+ * @since 1.2
+ */
+ List<Ordering> nonNullOrderings() {
+ if (orderings == null) {
+ orderings = new ArrayList<Ordering>(3);
+ }
+
+ return orderings;
+ }
+
+ /**
+ * Sets statement's fetch size (0 for no default size)
+ *
+ * @since 3.0
+ */
+ public void setStatementFetchSize(int size) {
+ metaData.setStatementFetchSize(size);
+ }
+
+ /**
+ * @return statement's fetch size
+ * @since 3.0
+ */
+ public int getStatementFetchSize() {
+ return metaData.getStatementFetchSize();
+ }
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQueryMetadata.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQueryMetadata.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQueryMetadata.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SelectQueryMetadata.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,66 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+package org.apache.cayenne.query;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 3.0
+ */
+class SelectQueryMetadata extends BaseQueryMetadata {
+
+ Map<String, String> pathSplitAliases;
+
+ @Override
+ void copyFromInfo(QueryMetadata info) {
+ super.copyFromInfo(info);
+ this.pathSplitAliases = new HashMap<String, String>(info.getPathSplitAliases());
+ }
+
+ /**
+ * @since 3.0
+ */
+ public Map<String, String> getPathSplitAliases() {
+ return pathSplitAliases != null ? pathSplitAliases : Collections
+ .<String, String> emptyMap();
+ }
+
+ /**
+ * @since 3.0
+ */
+ public void addPathSplitAliases(String path, String... aliases) {
+ if (aliases == null) {
+ throw new NullPointerException("Null aliases");
+ }
+
+ if (aliases.length == 0) {
+ throw new IllegalArgumentException("No aliases specified");
+ }
+
+ if (pathSplitAliases == null) {
+ pathSplitAliases = new HashMap<String, String>();
+ }
+
+ for (String alias : aliases) {
+ pathSplitAliases.put(alias, path);
+ }
+ }
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SortOrder.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SortOrder.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SortOrder.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/query/SortOrder.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,34 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.query;
+
+/**
+ * Constants to order query results (the ORDER BY clause).
+ */
+public enum SortOrder {
+ /**
+ * ASCENDING = Ascending order, case sensitive.<br/>
+ * ASCENDING_INSENSITIVE = Ascending order, case insensitive<br/>
+ * DESCENDING = Descending order, case sensitive.<br>
+ * DESCENDING_INSENSITIVE = Descending order, case insensitive.<br>
+ */
+ ASCENDING, ASCENDING_INSENSITIVE,
+ DESCENDING, DESCENDING_INSENSITIVE
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/GenericResponse.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/GenericResponse.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/GenericResponse.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/GenericResponse.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,150 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.util;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.cayenne.QueryResponse;
+
+/**
+ * A simple serializable implementation of QueryResponse.
+ *
+ * @since 1.2
+ */
+public class GenericResponse implements QueryResponse, Serializable {
+
+ protected List results;
+
+ protected transient int currentIndex;
+
+ /**
+ * Creates an empty BaseResponse.
+ */
+ public GenericResponse() {
+ results = new ArrayList();
+ }
+
+ /**
+ * Creates a BaseResponse with a single result list.
+ */
+ public GenericResponse(List list) {
+ results = new ArrayList(1);
+ addResultList(list);
+ }
+
+ /**
+ * Creates a response that it a shallow copy of another response.
+ */
+ public GenericResponse(QueryResponse response) {
+
+ results = new ArrayList(response.size());
+
+ response.reset();
+ while (response.next()) {
+ if (response.isList()) {
+ addResultList(response.currentList());
+ }
+ else {
+ addBatchUpdateCount(response.currentUpdateCount());
+ }
+ }
+ }
+
+ public List firstList() {
+ for (reset(); next();) {
+ if (isList()) {
+ return currentList();
+ }
+ }
+
+ return null;
+ }
+
+ public int[] firstUpdateCount() {
+ for (reset(); next();) {
+ if (!isList()) {
+ return currentUpdateCount();
+ }
+ }
+
+ return null;
+ }
+
+ public List currentList() {
+ return (List) results.get(currentIndex - 1);
+ }
+
+ public int[] currentUpdateCount() {
+ return (int[]) results.get(currentIndex - 1);
+ }
+
+ public boolean isList() {
+ return results.get(currentIndex - 1) instanceof List;
+ }
+
+ public boolean next() {
+ return ++currentIndex <= results.size();
+ }
+
+ public void reset() {
+ // use a zero-based index, not -1, as this will simplify serialization handling
+ currentIndex = 0;
+ }
+
+ public int size() {
+ return results.size();
+ }
+
+ /**
+ * Clears any previously collected information.
+ */
+ public void clear() {
+ results.clear();
+ }
+
+ public void addBatchUpdateCount(int[] resultCount) {
+
+ if (resultCount != null) {
+ results.add(resultCount);
+ }
+ }
+
+ public void addUpdateCount(int resultCount) {
+ results.add(new int[] {
+ resultCount
+ });
+ }
+
+ public void addResultList(List list) {
+ this.results.add(list);
+ }
+
+ /**
+ * Replaces previously stored result with a new result.
+ */
+ public void replaceResult(Object oldResult, Object newResult) {
+ int index = results.indexOf(oldResult);
+ if (index >= 0) {
+ results.set(index, newResult);
+ }
+ }
+}
Added: cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/ListResponse.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/ListResponse.java?rev=921518&view=auto
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/ListResponse.java (added)
+++ cayenne/sandbox/cayenne-gwt/src/main/resources/org/apache/cayenne/query/emul/org/apache/cayenne/util/ListResponse.java Wed Mar 10 19:12:05 2010
@@ -0,0 +1,95 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.util;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cayenne.QueryResponse;
+
+/**
+ * A QueryResponse optimized to hold a single object or data row list.
+ *
+ * @since 1.2
+ */
+public class ListResponse implements QueryResponse, Serializable {
+
+ protected List objectList;
+
+ protected transient int currentIndex;
+
+ /**
+ * Creates an empty response.
+ */
+ public ListResponse() {
+ this.objectList = new ArrayList(1);
+ }
+
+ public ListResponse(Object object) {
+ this.objectList = Collections.singletonList(object);
+ }
+
+ public ListResponse(List objectList) {
+ this.objectList = objectList;
+ }
+
+ public int size() {
+ return 1;
+ }
+
+ public boolean isList() {
+ if (currentIndex != 1) {
+ throw new IndexOutOfBoundsException("Past iteration end: " + currentIndex);
+ }
+
+ return true;
+ }
+
+ public List currentList() {
+ if (currentIndex != 1) {
+ throw new IndexOutOfBoundsException("Past iteration end: " + currentIndex);
+ }
+
+ return objectList;
+ }
+
+ public int[] currentUpdateCount() {
+ throw new IllegalStateException("Current object is not an update count");
+ }
+
+ public boolean next() {
+ return ++currentIndex <= 1;
+ }
+
+ public void reset() {
+ // use a zero-based index, not -1, as this will simplify serialization handling
+ currentIndex = 0;
+ }
+
+ public List firstList() {
+ return objectList;
+ }
+
+ public int[] firstUpdateCount() {
+ return new int[0];
+ }
+}
Modified: cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/GwtTestQuery.java
URL: http://svn.apache.org/viewvc/cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/GwtTestQuery.java?rev=921518&r1=921517&r2=921518&view=diff
==============================================================================
--- cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/GwtTestQuery.java (original)
+++ cayenne/sandbox/cayenne-gwt/src/test/java/org/apache/cayenne/gwt/test/client/GwtTestQuery.java Wed Mar 10 19:12:05 2010
@@ -18,13 +18,16 @@
****************************************************************/
package org.apache.cayenne.gwt.test.client;
+import java.util.Collections;
import java.util.List;
import org.apache.cayenne.DataRow;
+import org.apache.cayenne.QueryResponse;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.gwt.client.GWTDataContext;
import org.apache.cayenne.gwt.test.client.model.Tree;
import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import org.apache.cayenne.query.SortOrder;
@@ -40,8 +43,6 @@ public class GwtTestQuery extends Cayenn
Tree pine = result.get(0);
assertEquals(pine.getName(), "Pine");
assertEquals(result.get(1).getName(), "Fir");
-
- finishTest();
}
});
}
@@ -55,8 +56,6 @@ public class GwtTestQuery extends Cayenn
assertEquals(result.size(), 1);
Tree pine = result.get(0);
assertEquals(pine.getName(), "Pine");
-
- finishTest();
}
});
}
@@ -73,8 +72,6 @@ public class GwtTestQuery extends Cayenn
assertEquals(result.size(), 1);
DataRow pine = result.get(0);
assertEquals(pine.get("name"), "Pine");
-
- finishTest();
}
});
}
@@ -90,4 +87,22 @@ public class GwtTestQuery extends Cayenn
delayTestFinish(500);
}
+
+ public void testSQLTemplate() {
+ SQLTemplate template = new SQLTemplate("Tree", "DELETE FROM TREE WHERE TREE_ID=#bind($id)");
+ template.setParameters(Collections.singletonMap("id", 0));
+ GWTDataContext.getInstance().performGenericQuery(template, new TestCallback<QueryResponse>() {
+ @Override
+ public void onSuccess(QueryResponse result) {
+ //mock assert, but at least we check that GenericResponse was tranferred correctly
+ int[] res = result.firstUpdateCount();
+ assertEquals(res.length, 1);
+ assertEquals(res[0], 0);
+
+ finishTest();
+ }
+ });
+
+ delayTestFinish(500);
+ }
}