mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7770a9617 | ||
|
|
41abf34ef6 | ||
|
|
89beaee0f6 | ||
|
|
5052afbd07 | ||
|
|
d89a58482c | ||
|
|
eb1bca805e | ||
|
|
9cb66b112f | ||
|
|
210901ee2d | ||
|
|
396fb49acd | ||
|
|
a83896f1ff | ||
|
|
3483372ae3 | ||
|
|
4e1f817ade | ||
|
|
d4139aa8ef | ||
|
|
a6cfed7c44 | ||
|
|
cc17ea8911 | ||
|
|
141f0a8b16 | ||
|
|
9dbd903a73 | ||
|
|
b8105190d1 | ||
|
|
ef3d911e19 | ||
|
|
31fd0b7ed5 | ||
|
|
26d1288757 | ||
|
|
1d49e5b341 | ||
|
|
4a0806e453 | ||
|
|
ab48f796c6 | ||
|
|
0cb8bb0415 | ||
|
|
471691c747 | ||
|
|
c86e6b3cf9 | ||
|
|
b399713a85 | ||
|
|
f8d4ad7f33 | ||
|
|
7984a9ccd1 | ||
|
|
27cda09523 | ||
|
|
20fc23c19c | ||
|
|
bac53a5d75 | ||
|
|
2e0690efa9 | ||
|
|
fdd9b1905c | ||
|
|
fc966618a6 | ||
|
|
669ba7837a |
@@ -1,8 +1,11 @@
|
||||
[](https://travis-ci.org/ebean-orm/ebean)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
|
||||
|
||||
# Need help?
|
||||
Post questions or issues to the Ebean google group - https://groups.google.com/forum/#!forum/ebean
|
||||
|
||||
# Documentation
|
||||
Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
|
||||
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
|
||||
|
||||
|
||||
## Maven cental links:
|
||||
@@ -10,8 +13,7 @@ Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Web
|
||||
|
||||
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cebean "maven central all related projects")
|
||||
|
||||
## Current versions
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean) - ebean
|
||||
## Other versions
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent) - ebean-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin) - ebean-maven-plugin
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.32.1</version>
|
||||
<version>11.33.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.32.1</tag>
|
||||
<tag>ebean-11.33.2</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -117,7 +117,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>4.4</version>
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -141,7 +141,7 @@
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
<version>4.7.1</version>
|
||||
<version>4.7.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson core used internally by Ebean -->
|
||||
|
||||
@@ -570,7 +570,7 @@ public interface EbeanServer {
|
||||
* txn.setBatchGetGeneratedKeys(false);
|
||||
*
|
||||
* // explicitly flush the JDBC batch buffer
|
||||
* txn.flushBatch();
|
||||
* txn.flush();
|
||||
*
|
||||
* ...
|
||||
*
|
||||
@@ -688,8 +688,6 @@ public interface EbeanServer {
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* </p>
|
||||
*/
|
||||
void endTransaction();
|
||||
|
||||
@@ -963,7 +961,7 @@ public interface EbeanServer {
|
||||
* updateSql.getRowCount().
|
||||
* <p>
|
||||
* If you wish to execute a Sql Select natively then you should use the
|
||||
* FindByNativeSql object.
|
||||
* SqlQuery object or DtoQuery.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the table modification information is automatically deduced and
|
||||
@@ -1330,9 +1328,8 @@ public interface EbeanServer {
|
||||
* u1.setName("u1 mod");
|
||||
* u2.setName("u2 mod");
|
||||
*
|
||||
* ebeanServer.save(u1);
|
||||
* ebeanServer.save(u2);
|
||||
*
|
||||
* u1.save();
|
||||
* u2.save();
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
|
||||
@@ -64,6 +64,17 @@ public class Expr {
|
||||
return Ebean.getExpressionFactory().ieq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
*/
|
||||
public static Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
|
||||
return Ebean.getExpressionFactory().inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
|
||||
@@ -149,6 +149,14 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression ineObject(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
*/
|
||||
Expression inRange(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
|
||||
@@ -316,7 +316,7 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
*
|
||||
* <h3>Example 1:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -327,7 +327,7 @@ public interface ExpressionList<T> {
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Example 2:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -349,7 +349,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Execute a query returning a single value of a single property/column.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* String name =
|
||||
@@ -434,7 +433,6 @@ public interface ExpressionList<T> {
|
||||
* If maxRows is not set on the query prior to calling findPagedList() then a
|
||||
* PersistenceException is thrown.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = Ebean.find(Order.class)
|
||||
@@ -573,7 +571,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Extended version for setDistinct in conjunction with "findSingleAttributeList";
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<CountedValue<Order.Status>> orderStatusCount =
|
||||
@@ -683,7 +680,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Equal to expression for the value at the given path in the JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonEqualTo("content", "path.other", 34)
|
||||
@@ -698,7 +694,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Not Equal to - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonNotEqualTo("content", "path.other", 34)
|
||||
@@ -713,7 +708,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Greater than - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonGreaterThan("content", "path.other", 34)
|
||||
@@ -724,7 +718,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonGreaterOrEqual("content", "path.other", 34)
|
||||
@@ -735,7 +728,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Less than - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonLessThan("content", "path.other", 34)
|
||||
@@ -746,7 +738,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Less than or equal to - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonLessOrEqualTo("content", "path.other", 34)
|
||||
@@ -757,7 +748,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Between - for the given path in a JSON document.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
|
||||
@@ -771,7 +761,6 @@ public interface ExpressionList<T> {
|
||||
* <p>
|
||||
* This returns the list so that add() can be chained.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query = Ebean.find(Customer.class);
|
||||
@@ -814,8 +803,16 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> ine(String propertyName, String value);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
*/
|
||||
ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
ExpressionList<T> between(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
@@ -868,7 +865,6 @@ public interface ExpressionList<T> {
|
||||
* To get control over the options you can create an ExampleExpression and set
|
||||
* those options such as case insensitive etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // create an example bean and set the properties
|
||||
@@ -877,7 +873,7 @@ public interface ExpressionList<T> {
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where()
|
||||
* List<Customer> list = Ebean.find(Customer.class).where()
|
||||
* // pass the bean into the where() clause
|
||||
* .exampleLike(example)
|
||||
* // you can add other expressions to the same query
|
||||
@@ -886,7 +882,7 @@ public interface ExpressionList<T> {
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Similarly you can create an ExampleExpression
|
||||
* <p>
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Customer example = new Customer();
|
||||
@@ -1108,7 +1104,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Add expression for ALL of the given bit flags to be set.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
|
||||
@@ -1122,7 +1117,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Add expression for the given bit flags to be NOT set.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().bitwiseNot("flags", BwFlags.HAS_COLOUR)
|
||||
@@ -1173,6 +1167,13 @@ public interface ExpressionList<T> {
|
||||
* raw("add_days(orderDate, 10) < ?", someDate)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Subquery example:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw, Object value);
|
||||
|
||||
@@ -1197,12 +1198,18 @@ public interface ExpressionList<T> {
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* raw("orderQty < shipQty")
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Subquery example:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw);
|
||||
|
||||
@@ -1276,12 +1283,10 @@ public interface ExpressionList<T> {
|
||||
* typically you only explicitly need to use the and() junction
|
||||
* when it is nested inside an or() or not() junction.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Example: Nested and()
|
||||
*
|
||||
* Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* .or()
|
||||
* .and() // nested and
|
||||
@@ -1302,16 +1307,27 @@ public interface ExpressionList<T> {
|
||||
* Return a list of expressions that will be joined by OR's.
|
||||
* This is exactly the same as disjunction();
|
||||
* <p>
|
||||
* <p>
|
||||
* Use endOr() or endJunction() to end the OR junction.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Example: (status active OR anniversary is null)
|
||||
*
|
||||
* .where()
|
||||
* .or()
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .isNull("anniversary")
|
||||
* .orderBy().asc("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Example: Use or() to join
|
||||
* // two nested and() expressions
|
||||
*
|
||||
* Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* .or()
|
||||
* .and()
|
||||
@@ -1335,8 +1351,8 @@ public interface ExpressionList<T> {
|
||||
* Use endNot() or endJunction() to end expressions being added to the
|
||||
* NOT expression list.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>@{code
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* .where()
|
||||
* .not()
|
||||
@@ -1345,12 +1361,11 @@ public interface ExpressionList<T> {
|
||||
* .endNot()
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <pre>@{code
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Example: nested not()
|
||||
*
|
||||
* Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .not()
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.ebean.util.StringHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -412,15 +411,15 @@ public final class OrderBy<T> implements Serializable {
|
||||
|
||||
String[] chunks = orderByClause.split(",");
|
||||
for (String chunk : chunks) {
|
||||
String[] pairs = chunk.split(" ");
|
||||
Property p = parseProperty(pairs);
|
||||
Property p = parseProperty(chunk);
|
||||
if (p != null) {
|
||||
list.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Property parseProperty(String[] pairs) {
|
||||
private Property parseProperty(String chunk) {
|
||||
String[] pairs = chunk.split(" ");
|
||||
if (pairs.length == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -446,8 +445,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
boolean asc = isAscending(wordList.get(1));
|
||||
return new Property(wordList.get(0), asc, wordList.get(2), wordList.get(3));
|
||||
}
|
||||
String m = "Expecting a 1, 2 or 4 words in [" + Arrays.toString(pairs) + "] but got " + wordList;
|
||||
throw new RuntimeException(m);
|
||||
return new Property(chunk.trim(), true);
|
||||
}
|
||||
|
||||
private boolean isAscending(String s) {
|
||||
|
||||
@@ -897,17 +897,22 @@ public interface Query<T> {
|
||||
* 'does a row exist in the db' check.
|
||||
* </p>
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Example using a query bean:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
|
||||
* boolean userExists =
|
||||
* new QContact()
|
||||
* .email.equalTo("rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = query()
|
||||
* .where().eq("email", "rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
@@ -1623,6 +1628,14 @@ public interface Query<T> {
|
||||
* Typically this is used when a table has partitioning and we wish to specify a specific
|
||||
* partition/table to query against.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* QOrder()
|
||||
* .setBaseTable("order_2019_05")
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Query<T> setBaseTable(String baseTable);
|
||||
|
||||
@@ -1632,7 +1645,19 @@ public interface Query<T> {
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* Sets the inherit type. Must be a subtype of getBeanType
|
||||
* Restrict the query to only return subtypes of the given inherit type.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Animal> animals =
|
||||
* new QAnimal()
|
||||
* .name.startsWith("Fluffy")
|
||||
* .setInheritType(Cat.class)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param type An inheritance subtype of the
|
||||
*/
|
||||
Query<T> setInheritType(Class<? extends T> type);
|
||||
|
||||
|
||||
@@ -244,8 +244,7 @@ public interface Transaction extends AutoCloseable {
|
||||
*
|
||||
* // assume Customer has L2 bean caching enabled ...
|
||||
*
|
||||
* Transaction transaction = Ebean.beginTransaction();
|
||||
* try {
|
||||
* try (Transaction transaction = ebeanServer.beginTransaction()) {
|
||||
*
|
||||
* // this uses L2 bean cache as the transaction
|
||||
* // ... is considered "query only" at this point
|
||||
@@ -253,7 +252,7 @@ public interface Transaction extends AutoCloseable {
|
||||
*
|
||||
* // transaction no longer "query only" once
|
||||
* // ... a bean has been saved etc
|
||||
* Ebean.save(someBean);
|
||||
* someBean.save();
|
||||
*
|
||||
* // will NOT use L2 bean cache as the transaction
|
||||
* // ... is no longer considered "query only"
|
||||
@@ -273,8 +272,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* Customer.find.byId(99); // skips l2 bean cache
|
||||
*
|
||||
*
|
||||
* } finally {
|
||||
* transaction.end();
|
||||
* transaction.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
@@ -290,36 +288,66 @@ public interface Transaction extends AutoCloseable {
|
||||
boolean isSkipCache();
|
||||
|
||||
/**
|
||||
* Turn on or off statement batching. Statement batching can be transparent
|
||||
* for drivers and databases that support getGeneratedKeys. Otherwise you may
|
||||
* wish to specifically control when batching is used via this method.
|
||||
* <p>
|
||||
* Refer to <code>java.sql.PreparedStatement.addBatch();</code>
|
||||
* <p>
|
||||
* Note that you may also wish to use the setPersistCascade method to stop
|
||||
* save and delete cascade behaviour. You may do this to have full control
|
||||
* over the order of execution rather than the normal cascading fashion.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the <em>execution order</em> in batch mode may be different from
|
||||
* non batch mode execution order. Also note that <em>insert behaviour</em>
|
||||
* may be different depending on the JDBC driver and its support for
|
||||
* getGeneratedKeys. That is, for JDBC drivers that do not support
|
||||
* getGeneratedKeys you may not get back the generated IDs (used for inserting
|
||||
* associated detail beans etc).
|
||||
* </p>
|
||||
* Turn on or off use of JDBC statement batching.
|
||||
* <p>
|
||||
* Calls to save(), delete(), insert() and execute() all support batch
|
||||
* processing. This includes normal beans, MapBean, CallableSql and UpdateSql.
|
||||
* processing. This includes normal beans, CallableSql and UpdateSql.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction transaction = server.beginTransaction()) {
|
||||
*
|
||||
* // turn on JDBC batch
|
||||
* transaction.setBatchMode(true);
|
||||
*
|
||||
* // tune the batch size
|
||||
* transaction.setBatchSize(50);
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* transaction.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>getGeneratedKeys</h3>
|
||||
* <p>
|
||||
* The flushing of the batched statements is automatic but you can call
|
||||
* batchFlush when you like. Note that flushing occurs when a query is
|
||||
* executed or when you mix UpdateSql and CallableSql with save and delete of
|
||||
* Often with large batch inserts we want to turn off getGeneratedKeys. We do
|
||||
* this via {@link #setBatchGetGeneratedKeys(boolean)}.
|
||||
* Also note that some JDBC drivers do not support getGeneratedKeys in JDBC batch mode.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction transaction = server.beginTransaction()) {
|
||||
*
|
||||
* transaction.setBatchMode(true);
|
||||
* transaction.setBatchSize(100);
|
||||
* // insert but don't bother getting back the generated keys
|
||||
* transaction.setBatchGetGeneratedKeys(false);
|
||||
*
|
||||
*
|
||||
* // perform lots of inserts ...
|
||||
* ...
|
||||
*
|
||||
* transaction.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Flush</h3>
|
||||
* <p>
|
||||
* The batch is automatically flushed when it hits the batch size and also when we
|
||||
* execute queries or when we mix UpdateSql and CallableSql with save and delete of
|
||||
* beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example: batch processing executing every 3 rows
|
||||
* We use {@link #flush()} to explicitly flush the batch and we can use
|
||||
* {@link #setBatchFlushOnQuery(boolean)} and {@link #setBatchFlushOnMixed(boolean)}
|
||||
* to control the automatic flushing behaviour.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example: batch processing of CallableSql executing every 10 rows
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
@@ -334,24 +362,21 @@ public interface Transaction extends AutoCloseable {
|
||||
* CallableSql cs = new CallableSql(sql);
|
||||
* cs.registerOut(2, Types.INTEGER);
|
||||
*
|
||||
* // (optional) inform eBean this stored procedure
|
||||
* // (optional) inform Ebean this stored procedure
|
||||
* // inserts into a table called sp_test
|
||||
* cs.addModification("sp_test", true, false, false);
|
||||
*
|
||||
* Transaction txn = ebeanServer.beginTransaction();
|
||||
* txn.setBatchMode(true);
|
||||
* txn.setBatchSize(3);
|
||||
* try {
|
||||
* try (Transaction txn = ebeanServer.beginTransaction()) {
|
||||
* txn.setBatchMode(true);
|
||||
* txn.setBatchSize(10);
|
||||
*
|
||||
* for (int i = 0; i < da.length;) {
|
||||
* cs.setParameter(1, da[i]);
|
||||
* ebeanServer.execute(cs);
|
||||
* }
|
||||
*
|
||||
* // NB: commit implicitly flushes
|
||||
* // Note: commit implicitly flushes
|
||||
* txn.commit();
|
||||
*
|
||||
* } finally {
|
||||
* txn.end();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
|
||||
@@ -50,6 +50,11 @@ public interface DbMigration {
|
||||
throw new IllegalStateException("No service implementation found for DbMigration?");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false to suppress logging to System out.
|
||||
*/
|
||||
void setLogToSystemOut(boolean logToSystemOut);
|
||||
|
||||
/**
|
||||
* Set the path from the current working directory to the application resources.
|
||||
* <p>
|
||||
|
||||
@@ -11,4 +11,8 @@ public interface CQueryPlanKey {
|
||||
*/
|
||||
String getPartialKey();
|
||||
|
||||
/**
|
||||
* Return a query plan key taking into account persist cascading.
|
||||
*/
|
||||
CQueryPlanKey withDeleteByIds();
|
||||
}
|
||||
|
||||
@@ -439,6 +439,11 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
*/
|
||||
void setDelete();
|
||||
|
||||
/**
|
||||
* Set the query to be delete by ids due to cascading delete.
|
||||
*/
|
||||
CQueryPlanKey setDeleteByIdsPlan();
|
||||
|
||||
/**
|
||||
* Set the query to select the id property only.
|
||||
*/
|
||||
|
||||
@@ -72,6 +72,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
private static final String GENERATED_COMMENT = "THIS IS A GENERATED FILE - DO NOT MODIFY";
|
||||
|
||||
private boolean logToSystemOut = true;
|
||||
|
||||
/**
|
||||
* Set to true if DefaultDbMigration run with online EbeanServer instance.
|
||||
*/
|
||||
@@ -316,6 +318,11 @@ public class DefaultDbMigration implements DbMigration {
|
||||
return generateDiff(request);
|
||||
}
|
||||
|
||||
} catch (UnknownResourcePathException e) {
|
||||
logError("ERROR - " + e.getMessage());
|
||||
logError("Check the working directory or change dbMigration.setPathToResources() value?");
|
||||
return null;
|
||||
|
||||
} finally {
|
||||
if (!online) {
|
||||
DbOffline.reset();
|
||||
@@ -387,8 +394,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
private void writeExtraDdl(File migrationDir, DdlScript script) throws IOException {
|
||||
|
||||
String fullName = repeatableMigrationName(script.isInit(), script.getName());
|
||||
|
||||
logger.info("writing repeatable script {}", fullName);
|
||||
logger.debug("writing repeatable script {}", fullName);
|
||||
|
||||
File file = new File(migrationDir, fullName);
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
@@ -397,6 +403,30 @@ public class DefaultDbMigration implements DbMigration {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogToSystemOut(boolean logToSystemOut) {
|
||||
this.logToSystemOut = logToSystemOut;
|
||||
}
|
||||
|
||||
private void logError(String message) {
|
||||
if (logToSystemOut) {
|
||||
System.out.println("DbMigration> " + message);
|
||||
} else {
|
||||
logger.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void logInfo(String message, Object value) {
|
||||
if (value != null) {
|
||||
message = String.format(message, value);
|
||||
}
|
||||
if (logToSystemOut) {
|
||||
System.out.println("DbMigration> " + message);
|
||||
} else {
|
||||
logger.info(message);
|
||||
}
|
||||
}
|
||||
|
||||
private String repeatableMigrationName(boolean init, String scriptName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (init) {
|
||||
@@ -416,12 +446,12 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
List<String> pendingDrops = request.getPendingDrops();
|
||||
if (!pendingDrops.isEmpty()) {
|
||||
logger.info("Pending un-applied drops in versions {}", pendingDrops);
|
||||
logInfo("Pending un-applied drops in versions %s", pendingDrops);
|
||||
}
|
||||
|
||||
Migration migration = request.createDiffMigration();
|
||||
if (migration == null) {
|
||||
logger.info("no changes detected - no migration written");
|
||||
logInfo("no changes detected - no migration written", null);
|
||||
return null;
|
||||
} else {
|
||||
// there were actually changes to write
|
||||
@@ -440,7 +470,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
List<String> pendingDrops = request.getPendingDrops();
|
||||
if (!pendingDrops.isEmpty()) {
|
||||
logger.info("... remaining pending un-applied drops in versions {}", pendingDrops);
|
||||
logInfo("... remaining pending un-applied drops in versions %s", pendingDrops);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
@@ -520,9 +550,9 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
String fullVersion = getFullVersion(request.nextVersion(), dropsFor);
|
||||
|
||||
logger.info("generating migration:{}", fullVersion);
|
||||
logInfo("generating migration:%s", fullVersion);
|
||||
if (!request.dbinitMigration && !writeMigrationXml(dbMigration, request.modelDir, fullVersion)) {
|
||||
logger.warn("migration already exists, not generating DDL");
|
||||
logError("migration already exists, not generating DDL");
|
||||
return null;
|
||||
} else {
|
||||
if (!platforms.isEmpty()) {
|
||||
@@ -627,7 +657,6 @@ public class DefaultDbMigration implements DbMigration {
|
||||
if (vanillaPlatform || databasePlatform == null) {
|
||||
// not explicitly set so use the platform of the server
|
||||
databasePlatform = server.getDatabasePlatform();
|
||||
logger.trace("set platform to {}", databasePlatform.getName());
|
||||
}
|
||||
if (migrationConfig != null) {
|
||||
if (strictMode != null) {
|
||||
@@ -713,13 +742,17 @@ public class DefaultDbMigration implements DbMigration {
|
||||
|
||||
// path to src/main/resources in typical maven project
|
||||
File resourceRootDir = new File(pathToResources);
|
||||
if (!resourceRootDir.exists()) {
|
||||
String msg = String.format("Error - path to resources %s does not exist. Absolute path is %s", pathToResources, resourceRootDir.getAbsolutePath());
|
||||
throw new UnknownResourcePathException(msg);
|
||||
}
|
||||
String resourcePath = migrationConfig.getMigrationPath(dbinitMigration);
|
||||
|
||||
// expect to be a path to something like - src/main/resources/dbmigration/model
|
||||
File path = new File(resourceRootDir, resourcePath);
|
||||
if (!path.exists()) {
|
||||
if (!path.mkdirs()) {
|
||||
logger.debug("Unable to ensure migration directory exists at {}", path.getAbsolutePath());
|
||||
logInfo("Warning - Unable to ensure migration directory exists at %s", path.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
return path;
|
||||
@@ -735,7 +768,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
}
|
||||
File modelDir = new File(migrationDirectory, migrationConfig.getModelPath());
|
||||
if (!modelDir.exists() && !modelDir.mkdirs()) {
|
||||
logger.debug("Unable to ensure migration model directory exists at {}", modelDir.getAbsolutePath());
|
||||
logInfo("Warning - Unable to ensure migration model directory exists at %s", modelDir.getAbsolutePath());
|
||||
}
|
||||
return modelDir;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
/**
|
||||
* Exception when db migration resource path does not exist.
|
||||
* <p>
|
||||
* Typically the working directory or pathToResources is incorrect.
|
||||
* </p>
|
||||
*/
|
||||
public class UnknownResourcePathException extends RuntimeException {
|
||||
|
||||
public UnknownResourcePathException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,14 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
|
||||
@Override
|
||||
public boolean isDeleteByStatement() {
|
||||
return beanDescriptor.isDeleteByStatement();
|
||||
if (!transaction.isPersistCascade() || beanDescriptor.isDeleteByStatement()) {
|
||||
// plain delete by query
|
||||
return true;
|
||||
} else {
|
||||
// delete by ids due to cascading delete needs
|
||||
queryPlanKey = query.setDeleteByIdsPlan();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,8 @@ package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.query.CQueryCollectionAdd;
|
||||
|
||||
|
||||
/**
|
||||
@@ -10,10 +12,10 @@ import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
public class BeanCollectionHelpFactory {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static final BeanListHelp LIST_HELP = new BeanListHelp();
|
||||
private static final BeanListHelp LIST_HELP = new BeanListHelp();
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
static final BeanSetHelp SET_HELP = new BeanSetHelp();
|
||||
private static final BeanSetHelp SET_HELP = new BeanSetHelp();
|
||||
|
||||
/**
|
||||
* Create the helper based on the many property.
|
||||
@@ -36,7 +38,7 @@ public class BeanCollectionHelpFactory {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> BeanCollectionHelp<T> create(SpiQuery.Type manyType, OrmQueryRequest<T> request) {
|
||||
public static <T> CQueryCollectionAdd<T> create(SpiQuery.Type manyType, OrmQueryRequest<T> request) {
|
||||
|
||||
if (manyType == SpiQuery.Type.LIST) {
|
||||
return LIST_HELP;
|
||||
@@ -44,10 +46,13 @@ public class BeanCollectionHelpFactory {
|
||||
} else if (manyType == SpiQuery.Type.SET) {
|
||||
return SET_HELP;
|
||||
|
||||
} else {
|
||||
} else if (manyType == SpiQuery.Type.MAP) {
|
||||
BeanDescriptor<T> target = request.getBeanDescriptor();
|
||||
String mapKey = request.getQuery().getMapKey();
|
||||
return new BeanMapHelp<>(target, mapKey);
|
||||
ElPropertyValue elProperty = target.getElGetValue(request.getQuery().getMapKey());
|
||||
return new BeanMapQueryHelp<>(elProperty);
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2586,9 +2586,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Return a 'dynamic property' used to read a formula.
|
||||
*/
|
||||
private STreeProperty findSqlTreeFormula(String formulaExpression) {
|
||||
|
||||
return dynamicProperty.computeIfAbsent(formulaExpression, (formula) -> new FormulaPropertyPath(this, formula).build());
|
||||
private STreeProperty findSqlTreeFormula(String formula, String path) {
|
||||
String key = formula + "-" + path;
|
||||
return dynamicProperty.computeIfAbsent(key, (fullKey) -> new FormulaPropertyPath(this, formula, path).build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2597,9 +2597,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* The property can be a dynamic formula or a well known bean property.
|
||||
*/
|
||||
@Override
|
||||
public STreeProperty findPropertyWithDynamic(String propName) {
|
||||
public STreeProperty findPropertyWithDynamic(String propName, String path) {
|
||||
if (propName.indexOf('(') > -1) {
|
||||
return findSqlTreeFormula(propName);
|
||||
return findSqlTreeFormula(propName, path);
|
||||
}
|
||||
return _findBeanProperty(propName);
|
||||
}
|
||||
|
||||
@@ -24,16 +24,6 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
private final String propertyName;
|
||||
private final BeanProperty beanProperty;
|
||||
|
||||
/**
|
||||
* When created for a given query that will return a map.
|
||||
*/
|
||||
BeanMapHelp(BeanDescriptor<T> targetDescriptor, String mapKey) {
|
||||
this.targetDescriptor = targetDescriptor;
|
||||
this.beanProperty = targetDescriptor.getBeanProperty(mapKey);
|
||||
this.many = null;
|
||||
this.propertyName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* When help is attached to a specific many property.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.common.BeanMap;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.query.CQueryCollectionAdd;
|
||||
|
||||
class BeanMapQueryHelp<T> implements CQueryCollectionAdd<T> {
|
||||
|
||||
private final ElPropertyValue elGetValue;
|
||||
|
||||
/**
|
||||
* Create for a findMap query.
|
||||
*/
|
||||
BeanMapQueryHelp(ElPropertyValue elGetValue) {
|
||||
this.elGetValue = elGetValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmptyNoParent() {
|
||||
return new BeanMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(BeanCollection collection, EntityBean bean, boolean withCheck) {
|
||||
if (bean == null) {
|
||||
((BeanMap<?, ?>) collection).internalPutNull();
|
||||
} else {
|
||||
Object keyValue = elGetValue.pathGet(bean);
|
||||
BeanMap<?, ?> map = ((BeanMap<?, ?>) collection);
|
||||
map.internalPutWithCheck(keyValue, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,15 +20,17 @@ class FormulaPropertyPath {
|
||||
|
||||
private final String internalExpression;
|
||||
|
||||
private final String path;
|
||||
|
||||
private boolean countDistinct;
|
||||
|
||||
private String cast;
|
||||
private String alias;
|
||||
|
||||
FormulaPropertyPath(BeanDescriptor<?> descriptor, String formula) {
|
||||
|
||||
FormulaPropertyPath(BeanDescriptor<?> descriptor, String formula, String path) {
|
||||
this.descriptor = descriptor;
|
||||
this.formula = formula;
|
||||
this.path = path;
|
||||
|
||||
int openBracket = formula.indexOf('(');
|
||||
int closeBracket = formula.lastIndexOf(')');
|
||||
@@ -94,6 +96,11 @@ class FormulaPropertyPath {
|
||||
DeployPropertyParser parser = descriptor.parser().setCatchFirst(true);
|
||||
|
||||
String parsed = parser.parse(internalExpression);
|
||||
if (path != null) {
|
||||
// fetch("machineStats", "sum(hours), sum(totalKms)")
|
||||
parsed = parsed.replace("${}", "${" + path + "}");
|
||||
}
|
||||
|
||||
ElPropertyDeploy firstProp = parser.getFirstProp();
|
||||
|
||||
ScalarType<?> scalarType;
|
||||
|
||||
@@ -25,6 +25,7 @@ import io.ebean.annotation.Index;
|
||||
import io.ebean.annotation.JsonIgnore;
|
||||
import io.ebean.annotation.Length;
|
||||
import io.ebean.annotation.SoftDelete;
|
||||
import io.ebean.annotation.Sum;
|
||||
import io.ebean.annotation.TenantId;
|
||||
import io.ebean.annotation.UnmappedJson;
|
||||
import io.ebean.annotation.UpdatedTimestamp;
|
||||
@@ -285,6 +286,10 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (aggregation != null) {
|
||||
prop.setAggregation(aggregation.value());
|
||||
}
|
||||
Sum sum = get(prop, Sum.class);
|
||||
if (sum != null) {
|
||||
prop.setAggregation("sum(" + prop.getName() + ")");
|
||||
}
|
||||
|
||||
Version version = get(prop, Version.class);
|
||||
if (version != null) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.IOException;
|
||||
|
||||
class BetweenExpression extends AbstractExpression {
|
||||
|
||||
private static final String BETWEEN = " between ";
|
||||
private static final String _BETWEEN = " between ? and ?";
|
||||
|
||||
private final Object valueHigh;
|
||||
|
||||
@@ -40,7 +40,7 @@ class BetweenExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(propName).append(BETWEEN).append(" ? and ? ");
|
||||
request.append(propName).append(_BETWEEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
import io.ebean.util.SplitName;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -80,7 +80,7 @@ class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(" ?").append(BETWEEN).append(name(lowProperty)).append(" and ").append(name(highProperty)).append(" ");
|
||||
request.append(" ?").append(BETWEEN).append(name(lowProperty)).append(" and ").append(name(highProperty));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -53,9 +53,9 @@ class CaseInsensitiveEqualExpression extends AbstractValueExpression {
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propName);
|
||||
}
|
||||
if (not) {
|
||||
request.append("lower(").append(pname).append(") !=? ");
|
||||
request.append("lower(").append(pname).append(") != ?");
|
||||
} else {
|
||||
request.append("lower(").append(pname).append(") =? ");
|
||||
request.append("lower(").append(pname).append(") = ?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
}
|
||||
item.addSql(request);
|
||||
}
|
||||
request.append(") ");
|
||||
request.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -217,8 +217,15 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
@Override
|
||||
public Expression between(String propertyName, Object value1, Object value2) {
|
||||
public Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
return new InRangeExpression(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
@Override
|
||||
public Expression between(String propertyName, Object value1, Object value2) {
|
||||
return new BetweenExpression(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
@@ -227,7 +234,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression betweenProperties(String lowProperty, String highProperty, Object value) {
|
||||
|
||||
return new BetweenPropertyExpression(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
@@ -236,7 +242,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression gt(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(propertyName, Op.GT, value);
|
||||
}
|
||||
|
||||
@@ -246,7 +251,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression ge(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(propertyName, Op.GT_EQ, value);
|
||||
}
|
||||
|
||||
@@ -255,7 +259,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression lt(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(propertyName, Op.LT, value);
|
||||
}
|
||||
|
||||
@@ -264,7 +267,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression le(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(propertyName, Op.LT_EQ, value);
|
||||
}
|
||||
|
||||
@@ -273,7 +275,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression isNull(String propertyName) {
|
||||
|
||||
return new NullExpression(propertyName, false);
|
||||
}
|
||||
|
||||
@@ -282,7 +283,6 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression isNotNull(String propertyName) {
|
||||
|
||||
return new NullExpression(propertyName, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -794,6 +794,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
|
||||
add(expr.inRange(propertyName, value1, value2));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> between(String propertyName, Object value1, Object value2) {
|
||||
add(expr.between(propertyName, value1, value2));
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
@@ -9,7 +10,6 @@ import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.query.CQuery;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -98,7 +98,7 @@ class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreExpress
|
||||
}
|
||||
request.append(" exists (");
|
||||
request.append(sql);
|
||||
request.append(") ");
|
||||
request.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -60,7 +60,7 @@ class IdExpression extends NonPrepareExpression implements SpiExpression {
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
String idSql = r.getBeanDescriptor().getIdBinderIdSql(null);
|
||||
|
||||
request.append(idSql).append(" ");
|
||||
request.append(idSql);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,7 +85,7 @@ class InQueryExpression extends AbstractExpression implements UnsupportedDocStor
|
||||
}
|
||||
request.append(" in (");
|
||||
request.append(sql);
|
||||
request.append(") ");
|
||||
request.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class InRangeExpression extends AbstractExpression {
|
||||
|
||||
private final Object valueHigh;
|
||||
|
||||
private final Object valueLow;
|
||||
|
||||
InRangeExpression(String propertyName, Object valueLow, Object valueHigh) {
|
||||
super(propertyName);
|
||||
this.valueLow = valueLow;
|
||||
this.valueHigh = valueHigh;
|
||||
}
|
||||
|
||||
private Object low() {
|
||||
return NamedParamHelp.value(valueLow);
|
||||
}
|
||||
|
||||
private Object high() {
|
||||
return NamedParamHelp.value(valueHigh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.writeRange(propName, Op.GT_EQ, low(), Op.LT, high());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
request.addBindValue(low());
|
||||
request.addBindValue(high());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append("(").append(propName).append(" >= ? and ").append(propName).append(" < ?)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(StringBuilder builder) {
|
||||
builder.append("InRange[").append(propName).append("]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
int hc = low().hashCode();
|
||||
hc = hc * 92821 + high().hashCode();
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
InRangeExpression that = (InRangeExpression) other;
|
||||
return low().equals(that.low()) && high().equals(that.high());
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
item.addSql(request);
|
||||
}
|
||||
request.append(") ");
|
||||
request.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +280,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.and(expOne, expTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
|
||||
return exprList.inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> between(String propertyName, Object value1, Object value2) {
|
||||
return exprList.between(propertyName, value1, value2);
|
||||
|
||||
@@ -51,7 +51,7 @@ class LikeExpression extends AbstractValueExpression {
|
||||
request.append(pname);
|
||||
}
|
||||
if (type == LikeType.EQUAL_TO) {
|
||||
request.append(" = ? ");
|
||||
request.append(" = ?");
|
||||
} else {
|
||||
// append db platform like clause
|
||||
request.appendLike(type == LikeType.RAW);
|
||||
|
||||
@@ -4,11 +4,11 @@ import io.ebean.Expression;
|
||||
import io.ebean.Junction;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -140,7 +140,7 @@ abstract class LogicExpression implements SpiExpression {
|
||||
expOne.addSql(request);
|
||||
request.append(conjunction ? AND : OR);
|
||||
expTwo.addSql(request);
|
||||
request.append(") ");
|
||||
request.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,7 +42,7 @@ class NativeILikeExpression extends AbstractExpression {
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propName);
|
||||
}
|
||||
|
||||
request.append(pname).append(" ilike ? ");
|
||||
request.append(pname).append(" ilike ?");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,11 +2,11 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -76,7 +76,7 @@ class NoopExpression implements SpiExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append("1=1 ");
|
||||
request.append("1=1");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,18 +3,18 @@ package io.ebeaninternal.server.expression;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
final class NotExpression implements SpiExpression {
|
||||
|
||||
private static final String NOT_START = "not (";
|
||||
private static final String NOT_END = ") ";
|
||||
private static final String NOT_END = ")";
|
||||
|
||||
private final SpiExpression exp;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class NullExpression extends AbstractExpression {
|
||||
return;
|
||||
}
|
||||
|
||||
String nullExpr = notNull ? " is not null " : " is null ";
|
||||
String nullExpr = notNull ? " is not null" : " is null";
|
||||
if (elProperty != null && elProperty.isAssocId()) {
|
||||
request.append(elProperty.getAssocIdExpression(propName, nullExpr));
|
||||
} else {
|
||||
|
||||
@@ -8,48 +8,48 @@ public enum Op {
|
||||
/**
|
||||
* Exists (JSON).
|
||||
*/
|
||||
EXISTS(" is not null ", ""),
|
||||
EXISTS(" is not null", ""),
|
||||
|
||||
/**
|
||||
* Not Exists (JSON).
|
||||
*/
|
||||
NOT_EXISTS(" is null ", ""),
|
||||
NOT_EXISTS(" is null", ""),
|
||||
|
||||
/**
|
||||
* Between (JSON).
|
||||
*/
|
||||
BETWEEN(" between ? and ? ", ""),
|
||||
BETWEEN(" between ? and ?", ""),
|
||||
|
||||
/**
|
||||
* Equal to
|
||||
*/
|
||||
EQ(" = ? ", ""),
|
||||
EQ(" = ?", ""),
|
||||
|
||||
/**
|
||||
* Not equal to.
|
||||
*/
|
||||
NOT_EQ(" <> ? ", ""),
|
||||
NOT_EQ(" <> ?", ""),
|
||||
|
||||
/**
|
||||
* Less than.
|
||||
*/
|
||||
|
||||
LT(" < ? ", "lt"),
|
||||
LT(" < ?", "lt"),
|
||||
|
||||
/**
|
||||
* Less than or equal to.
|
||||
*/
|
||||
LT_EQ(" <= ? ", "lte"),
|
||||
LT_EQ(" <= ?", "lte"),
|
||||
|
||||
/**
|
||||
* Greater than.
|
||||
*/
|
||||
GT(" > ? ", "gt"),
|
||||
GT(" > ?", "gt"),
|
||||
|
||||
/**
|
||||
* Greater than or equal to.
|
||||
*/
|
||||
GT_EQ(" >= ? ", "gte");
|
||||
GT_EQ(" >= ?", "gte");
|
||||
|
||||
final String exp;
|
||||
|
||||
|
||||
@@ -99,13 +99,13 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
@Override
|
||||
public void enterSelect_clause(EQLParser.Select_clauseContext ctx) {
|
||||
|
||||
checkChildren(ctx, 4);
|
||||
// with or without surrounding ( and )
|
||||
int childCount = ctx.getChildCount();
|
||||
String clause = trimParenthesis(child(ctx, childCount - 1));
|
||||
if (DISTINCT.equals(child(ctx, 1))) {
|
||||
query.setDistinct(true);
|
||||
query.select(child(ctx, 3));
|
||||
} else {
|
||||
query.select(child(ctx, 2));
|
||||
}
|
||||
query.select(clause);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,24 +113,46 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
|
||||
int childCount = ctx.getChildCount();
|
||||
checkChildren(ctx, 2);
|
||||
String path = child(ctx, 1);
|
||||
|
||||
int noPropertiesLength = 2;
|
||||
String maybePath = child(ctx, 1);
|
||||
FetchConfig fetchConfig = ParseFetchConfig.parse(maybePath);
|
||||
|
||||
FetchConfig fetchConfig = ParseFetchConfig.parse(path);
|
||||
if (fetchConfig != null) {
|
||||
noPropertiesLength = 3;
|
||||
path = child(ctx, 2);
|
||||
int propsIndex = 2;
|
||||
|
||||
String path;
|
||||
if (fetchConfig == null) {
|
||||
path = trimQuotes(maybePath);
|
||||
} else {
|
||||
propsIndex = 3;
|
||||
path = trimQuotes(child(ctx, 2));
|
||||
}
|
||||
if (childCount == noPropertiesLength) {
|
||||
|
||||
if (childCount == propsIndex) {
|
||||
query.fetch(path, fetchConfig);
|
||||
|
||||
} else {
|
||||
String fetchProperties = trimParenthesis(ctx.getChild(noPropertiesLength).getText());
|
||||
query.fetch(path, fetchProperties, fetchConfig);
|
||||
String properties = trimParenthesis(ctx.getChild(propsIndex).getText());
|
||||
query.fetch(path, properties, fetchConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim leading '(' and trailing ')'
|
||||
*/
|
||||
private String trimParenthesis(String text) {
|
||||
if (text.charAt(0) == '(') {
|
||||
return text.substring(1, text.length() - 1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
private String trimQuotes(String path) {
|
||||
if (path.charAt(0) == '\'' || path.charAt(0) == '`') {
|
||||
return path.substring(1, path.length() - 1);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterOrderby_property(EQLParser.Orderby_propertyContext ctx) {
|
||||
|
||||
@@ -177,20 +199,22 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim leading '(' and trailing ')'
|
||||
*/
|
||||
private String trimParenthesis(String text) {
|
||||
text = text.substring(1);
|
||||
text = text.substring(0, text.length() - 1);
|
||||
return text;
|
||||
}
|
||||
|
||||
private String getLeftHandSidePath(ParserRuleContext ctx) {
|
||||
TerminalNode pathToken = ctx.getToken(EQLLexer.PATH_VARIABLE, 0);
|
||||
return pathToken.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterInrange_expression(EQLParser.Inrange_expressionContext ctx) {
|
||||
checkChildren(ctx, 5);
|
||||
String path = getLeftHandSidePath(ctx);
|
||||
EqlOperator op = getOperator(ctx);
|
||||
if (op != EqlOperator.INRANGE) {
|
||||
throw new IllegalStateException("Expecting INRANGE operator but got " + op);
|
||||
}
|
||||
helper.addInRange(path, child(ctx, 2), child(ctx, 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterBetween_expression(EQLParser.Between_expressionContext ctx) {
|
||||
|
||||
@@ -388,7 +412,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
*/
|
||||
private void checkChildren(ParserRuleContext ctx, int min) {
|
||||
if (ctx.getChildCount() < min) {
|
||||
throw new IllegalStateException("expecting " + min + " children for comparison? " + ctx);
|
||||
throw new IllegalStateException("expecting " + min + " children for comparison but got " + ctx.getChildCount());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ class EqlAdapterHelper {
|
||||
peekExprList().between(path, bind(value1), bind(value2));
|
||||
}
|
||||
|
||||
protected void addInRange(String path, String value1, String value2) {
|
||||
peekExprList().inRange(path, bind(value1), bind(value2));
|
||||
}
|
||||
|
||||
protected void addIn(String path, List<Object> inValues) {
|
||||
peekExprList().in(path, inValues);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ enum EqlOperator {
|
||||
ISTARTS_WITH,
|
||||
IENDS_WITH,
|
||||
ILIKE,
|
||||
INRANGE,
|
||||
BETWEEN
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ class OperatorMapping {
|
||||
map.put("iendsWith", EqlOperator.IENDS_WITH);
|
||||
map.put("ilike", EqlOperator.ILIKE);
|
||||
|
||||
map.put("inrange", EqlOperator.INRANGE);
|
||||
map.put("between", EqlOperator.BETWEEN);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -56,18 +56,22 @@ T__54=55
|
||||
T__55=56
|
||||
T__56=57
|
||||
T__57=58
|
||||
INPUT_VARIABLE=59
|
||||
PATH_VARIABLE=60
|
||||
BOOLEAN_LITERAL=61
|
||||
NUMBER_LITERAL=62
|
||||
DOUBLE=63
|
||||
INT=64
|
||||
ZERO=65
|
||||
STRING_LITERAL=66
|
||||
WS=67
|
||||
'select'=1
|
||||
'('=2
|
||||
')'=3
|
||||
T__58=59
|
||||
T__59=60
|
||||
INPUT_VARIABLE=61
|
||||
PATH_VARIABLE=62
|
||||
QUOTED_PATH_VARIABLE=63
|
||||
PROP_FORMULA=64
|
||||
BOOLEAN_LITERAL=65
|
||||
NUMBER_LITERAL=66
|
||||
DOUBLE=67
|
||||
INT=68
|
||||
ZERO=69
|
||||
STRING_LITERAL=70
|
||||
WS=71
|
||||
'('=1
|
||||
')'=2
|
||||
'select'=3
|
||||
'distinct'=4
|
||||
'where'=5
|
||||
'order'=6
|
||||
@@ -89,38 +93,40 @@ WS=67
|
||||
'not'=22
|
||||
'in'=23
|
||||
'between'=24
|
||||
'is'=25
|
||||
'null'=26
|
||||
'isNull'=27
|
||||
'isNotNull'=28
|
||||
'notNull'=29
|
||||
'empty'=30
|
||||
'isEmpty'=31
|
||||
'isNotEmpty'=32
|
||||
'notEmpty'=33
|
||||
'like'=34
|
||||
'ilike'=35
|
||||
'contains'=36
|
||||
'icontains'=37
|
||||
'startsWith'=38
|
||||
'istartsWith'=39
|
||||
'endsWith'=40
|
||||
'iendsWith'=41
|
||||
'='=42
|
||||
'eq'=43
|
||||
'>'=44
|
||||
'gt'=45
|
||||
'>='=46
|
||||
'ge'=47
|
||||
'gte'=48
|
||||
'<'=49
|
||||
'lt'=50
|
||||
'<='=51
|
||||
'le'=52
|
||||
'lte'=53
|
||||
'<>'=54
|
||||
'!='=55
|
||||
'ne'=56
|
||||
'ieq'=57
|
||||
'ine'=58
|
||||
'0'=65
|
||||
'inrange'=25
|
||||
'to'=26
|
||||
'is'=27
|
||||
'null'=28
|
||||
'isNull'=29
|
||||
'isNotNull'=30
|
||||
'notNull'=31
|
||||
'empty'=32
|
||||
'isEmpty'=33
|
||||
'isNotEmpty'=34
|
||||
'notEmpty'=35
|
||||
'like'=36
|
||||
'ilike'=37
|
||||
'contains'=38
|
||||
'icontains'=39
|
||||
'startsWith'=40
|
||||
'istartsWith'=41
|
||||
'endsWith'=42
|
||||
'iendsWith'=43
|
||||
'='=44
|
||||
'eq'=45
|
||||
'>'=46
|
||||
'gt'=47
|
||||
'>='=48
|
||||
'ge'=49
|
||||
'gte'=50
|
||||
'<'=51
|
||||
'lt'=52
|
||||
'<='=53
|
||||
'le'=54
|
||||
'lte'=55
|
||||
'<>'=56
|
||||
'!='=57
|
||||
'ne'=58
|
||||
'ieq'=59
|
||||
'ine'=60
|
||||
'0'=69
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
// Generated from C:/dev/ebean/ebean/src/test/resources/EQL.g4 by ANTLR 4.7.1
|
||||
// Generated from /home/rob/github/ebean-dir/ebean/src/test/resources/EQL.g4 by ANTLR 4.7.2
|
||||
package io.ebeaninternal.server.grammer.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
@@ -12,286 +12,330 @@ import org.antlr.v4.runtime.atn.LexerATNSimulator;
|
||||
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
|
||||
@SuppressWarnings({ "all", "warnings", "unchecked", "unused", "cast" })
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class EQLLexer extends Lexer {
|
||||
static {
|
||||
RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION);
|
||||
}
|
||||
static { RuntimeMetaData.checkVersion("4.7.2", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache = new PredictionContextCache();
|
||||
public static final int T__0 = 1, T__1 = 2, T__2 = 3, T__3 = 4, T__4 = 5, T__5 = 6, T__6 = 7, T__7 = 8, T__8 = 9,
|
||||
T__9 = 10, T__10 = 11, T__11 = 12, T__12 = 13, T__13 = 14, T__14 = 15, T__15 = 16, T__16 = 17, T__17 = 18,
|
||||
T__18 = 19, T__19 = 20, T__20 = 21, T__21 = 22, T__22 = 23, T__23 = 24, T__24 = 25, T__25 = 26, T__26 = 27,
|
||||
T__27 = 28, T__28 = 29, T__29 = 30, T__30 = 31, T__31 = 32, T__32 = 33, T__33 = 34, T__34 = 35, T__35 = 36,
|
||||
T__36 = 37, T__37 = 38, T__38 = 39, T__39 = 40, T__40 = 41, T__41 = 42, T__42 = 43, T__43 = 44, T__44 = 45,
|
||||
T__45 = 46, T__46 = 47, T__47 = 48, T__48 = 49, T__49 = 50, T__50 = 51, T__51 = 52, T__52 = 53, T__53 = 54,
|
||||
T__54 = 55, T__55 = 56, T__56 = 57, T__57 = 58, INPUT_VARIABLE = 59, PATH_VARIABLE = 60, BOOLEAN_LITERAL = 61,
|
||||
NUMBER_LITERAL = 62, DOUBLE = 63, INT = 64, ZERO = 65, STRING_LITERAL = 66, WS = 67;
|
||||
public static String[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" };
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9,
|
||||
T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17,
|
||||
T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24,
|
||||
T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31,
|
||||
T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38,
|
||||
T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, T__44=45,
|
||||
T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52,
|
||||
T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59,
|
||||
T__59=60, INPUT_VARIABLE=61, PATH_VARIABLE=62, QUOTED_PATH_VARIABLE=63,
|
||||
PROP_FORMULA=64, BOOLEAN_LITERAL=65, NUMBER_LITERAL=66, DOUBLE=67, INT=68,
|
||||
ZERO=69, STRING_LITERAL=70, WS=71;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = { "DEFAULT_MODE" };
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE"
|
||||
};
|
||||
|
||||
public static final String[] ruleNames = { "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8",
|
||||
"T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "T__20",
|
||||
"T__21", "T__22", "T__23", "T__24", "T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32",
|
||||
"T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", "T__41", "T__42", "T__43", "T__44",
|
||||
"T__45", "T__46", "T__47", "T__48", "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56",
|
||||
"T__57", "INPUT_VARIABLE", "PATH_VARIABLE", "BOOLEAN_LITERAL", "NUMBER_LITERAL", "DOUBLE", "INT", "ZERO",
|
||||
"STRING_LITERAL", "WS" };
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8",
|
||||
"T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16",
|
||||
"T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24",
|
||||
"T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32",
|
||||
"T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40",
|
||||
"T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48",
|
||||
"T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56",
|
||||
"T__57", "T__58", "T__59", "INPUT_VARIABLE", "PATH_VARIABLE", "QUOTED_PATH_VARIABLE",
|
||||
"PROP_FORMULA", "BOOLEAN_LITERAL", "NUMBER_LITERAL", "DOUBLE", "INT",
|
||||
"ZERO", "STRING_LITERAL", "WS"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static final String[] _LITERAL_NAMES = { null, "'select'", "'('", "')'", "'distinct'", "'where'", "'order'",
|
||||
"'by'", "','", "'nulls'", "'first'", "'last'", "'asc'", "'desc'", "'limit'", "'offset'", "'fetch'", "'+'",
|
||||
"'query'", "'lazy'", "'or'", "'and'", "'not'", "'in'", "'between'", "'is'", "'null'", "'isNull'", "'isNotNull'",
|
||||
"'notNull'", "'empty'", "'isEmpty'", "'isNotEmpty'", "'notEmpty'", "'like'", "'ilike'", "'contains'",
|
||||
"'icontains'", "'startsWith'", "'istartsWith'", "'endsWith'", "'iendsWith'", "'='", "'eq'", "'>'", "'gt'", "'>='",
|
||||
"'ge'", "'gte'", "'<'", "'lt'", "'<='", "'le'", "'lte'", "'<>'", "'!='", "'ne'", "'ieq'", "'ine'", null, null,
|
||||
null, null, null, null, "'0'" };
|
||||
private static final String[] _SYMBOLIC_NAMES = { null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, "INPUT_VARIABLE", "PATH_VARIABLE", "BOOLEAN_LITERAL",
|
||||
"NUMBER_LITERAL", "DOUBLE", "INT", "ZERO", "STRING_LITERAL", "WS" };
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "'('", "')'", "'select'", "'distinct'", "'where'", "'order'", "'by'",
|
||||
"','", "'nulls'", "'first'", "'last'", "'asc'", "'desc'", "'limit'",
|
||||
"'offset'", "'fetch'", "'+'", "'query'", "'lazy'", "'or'", "'and'", "'not'",
|
||||
"'in'", "'between'", "'inrange'", "'to'", "'is'", "'null'", "'isNull'",
|
||||
"'isNotNull'", "'notNull'", "'empty'", "'isEmpty'", "'isNotEmpty'", "'notEmpty'",
|
||||
"'like'", "'ilike'", "'contains'", "'icontains'", "'startsWith'", "'istartsWith'",
|
||||
"'endsWith'", "'iendsWith'", "'='", "'eq'", "'>'", "'gt'", "'>='", "'ge'",
|
||||
"'gte'", "'<'", "'lt'", "'<='", "'le'", "'lte'", "'<>'", "'!='", "'ne'",
|
||||
"'ieq'", "'ine'", null, null, null, null, null, null, null, null, "'0'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, null, null, null, null, null, null, null,
|
||||
null, "INPUT_VARIABLE", "PATH_VARIABLE", "QUOTED_PATH_VARIABLE", "PROP_FORMULA",
|
||||
"BOOLEAN_LITERAL", "NUMBER_LITERAL", "DOUBLE", "INT", "ZERO", "STRING_LITERAL",
|
||||
"WS"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
public EQLLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this, _ATN, _decisionToDFA, _sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() {
|
||||
return "EQL.g4";
|
||||
}
|
||||
public EQLLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() {
|
||||
return ruleNames;
|
||||
}
|
||||
@Override
|
||||
public String getGrammarFileName() { return "EQL.g4"; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() {
|
||||
return _serializedATN;
|
||||
}
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() {
|
||||
return channelNames;
|
||||
}
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() {
|
||||
return modeNames;
|
||||
}
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() {
|
||||
return _ATN;
|
||||
}
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
public static final String _serializedATN = "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2E\u0206\b\1\4\2\t"
|
||||
+ "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"
|
||||
+ "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"
|
||||
+ "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"
|
||||
+ "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"
|
||||
+ "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"
|
||||
+ ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"
|
||||
+ "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="
|
||||
+ "\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\3\2\3\2\3\2\3\2\3\2\3\2\3\2"
|
||||
+ "\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3"
|
||||
+ "\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n"
|
||||
+ "\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r"
|
||||
+ "\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20"
|
||||
+ "\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\23\3\23"
|
||||
+ "\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26"
|
||||
+ "\3\26\3\26\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\31\3\31\3\31\3\31\3\31"
|
||||
+ "\3\31\3\31\3\31\3\32\3\32\3\32\3\33\3\33\3\33\3\33\3\33\3\34\3\34\3\34"
|
||||
+ "\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35\3\35"
|
||||
+ "\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37"
|
||||
+ "\3 \3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3!\3\"\3\"\3\""
|
||||
+ "\3\"\3\"\3\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3%\3%\3%\3%"
|
||||
+ "\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'"
|
||||
+ "\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3"
|
||||
+ ")\3)\3)\3)\3)\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3+\3+\3,\3,\3,\3-\3-\3.\3"
|
||||
+ ".\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\61\3\61\3\62\3\62\3\63\3\63\3"
|
||||
+ "\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\66\3\67\3\67\3\67\3"
|
||||
+ "8\38\38\39\39\39\3:\3:\3:\3:\3;\3;\3;\3;\3<\3<\3<\7<\u01c1\n<\f<\16<\u01c4"
|
||||
+ "\13<\3=\3=\7=\u01c8\n=\f=\16=\u01cb\13=\3>\3>\3>\3>\3>\3>\3>\3>\3>\5>"
|
||||
+ "\u01d6\n>\3?\5?\u01d9\n?\3?\3?\5?\u01dd\n?\3?\3?\5?\u01e1\n?\3@\6@\u01e4"
|
||||
+ "\n@\r@\16@\u01e5\3@\3@\7@\u01ea\n@\f@\16@\u01ed\13@\3A\3A\7A\u01f1\nA"
|
||||
+ "\fA\16A\u01f4\13A\3B\3B\3C\3C\3C\3C\7C\u01fc\nC\fC\16C\u01ff\13C\3C\3"
|
||||
+ "C\3D\3D\3D\3D\2\2E\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r"
|
||||
+ "\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33"
|
||||
+ "\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63"
|
||||
+ "e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\3"
|
||||
+ "\2\t\5\2C\\aac|\6\2\62;C\\aac|\7\2\60\60\62;C\\aac|\3\2\62;\3\2\63;\3"
|
||||
+ "\2))\5\2\13\f\17\17\"\"\2\u0211\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2"
|
||||
+ "\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2"
|
||||
+ "\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2"
|
||||
+ "\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2"
|
||||
+ "\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2"
|
||||
+ "\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2"
|
||||
+ "\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O"
|
||||
+ "\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2"
|
||||
+ "\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2"
|
||||
+ "\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u"
|
||||
+ "\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081"
|
||||
+ "\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\3\u0089\3\2\2"
|
||||
+ "\2\5\u0090\3\2\2\2\7\u0092\3\2\2\2\t\u0094\3\2\2\2\13\u009d\3\2\2\2\r"
|
||||
+ "\u00a3\3\2\2\2\17\u00a9\3\2\2\2\21\u00ac\3\2\2\2\23\u00ae\3\2\2\2\25\u00b4"
|
||||
+ "\3\2\2\2\27\u00ba\3\2\2\2\31\u00bf\3\2\2\2\33\u00c3\3\2\2\2\35\u00c8\3"
|
||||
+ "\2\2\2\37\u00ce\3\2\2\2!\u00d5\3\2\2\2#\u00db\3\2\2\2%\u00dd\3\2\2\2\'"
|
||||
+ "\u00e3\3\2\2\2)\u00e8\3\2\2\2+\u00eb\3\2\2\2-\u00ef\3\2\2\2/\u00f3\3\2"
|
||||
+ "\2\2\61\u00f6\3\2\2\2\63\u00fe\3\2\2\2\65\u0101\3\2\2\2\67\u0106\3\2\2"
|
||||
+ "\29\u010d\3\2\2\2;\u0117\3\2\2\2=\u011f\3\2\2\2?\u0125\3\2\2\2A\u012d"
|
||||
+ "\3\2\2\2C\u0138\3\2\2\2E\u0141\3\2\2\2G\u0146\3\2\2\2I\u014c\3\2\2\2K"
|
||||
+ "\u0155\3\2\2\2M\u015f\3\2\2\2O\u016a\3\2\2\2Q\u0176\3\2\2\2S\u017f\3\2"
|
||||
+ "\2\2U\u0189\3\2\2\2W\u018b\3\2\2\2Y\u018e\3\2\2\2[\u0190\3\2\2\2]\u0193"
|
||||
+ "\3\2\2\2_\u0196\3\2\2\2a\u0199\3\2\2\2c\u019d\3\2\2\2e\u019f\3\2\2\2g"
|
||||
+ "\u01a2\3\2\2\2i\u01a5\3\2\2\2k\u01a8\3\2\2\2m\u01ac\3\2\2\2o\u01af\3\2"
|
||||
+ "\2\2q\u01b2\3\2\2\2s\u01b5\3\2\2\2u\u01b9\3\2\2\2w\u01bd\3\2\2\2y\u01c5"
|
||||
+ "\3\2\2\2{\u01d5\3\2\2\2}\u01e0\3\2\2\2\177\u01e3\3\2\2\2\u0081\u01ee\3"
|
||||
+ "\2\2\2\u0083\u01f5\3\2\2\2\u0085\u01f7\3\2\2\2\u0087\u0202\3\2\2\2\u0089"
|
||||
+ "\u008a\7u\2\2\u008a\u008b\7g\2\2\u008b\u008c\7n\2\2\u008c\u008d\7g\2\2"
|
||||
+ "\u008d\u008e\7e\2\2\u008e\u008f\7v\2\2\u008f\4\3\2\2\2\u0090\u0091\7*"
|
||||
+ "\2\2\u0091\6\3\2\2\2\u0092\u0093\7+\2\2\u0093\b\3\2\2\2\u0094\u0095\7"
|
||||
+ "f\2\2\u0095\u0096\7k\2\2\u0096\u0097\7u\2\2\u0097\u0098\7v\2\2\u0098\u0099"
|
||||
+ "\7k\2\2\u0099\u009a\7p\2\2\u009a\u009b\7e\2\2\u009b\u009c\7v\2\2\u009c"
|
||||
+ "\n\3\2\2\2\u009d\u009e\7y\2\2\u009e\u009f\7j\2\2\u009f\u00a0\7g\2\2\u00a0"
|
||||
+ "\u00a1\7t\2\2\u00a1\u00a2\7g\2\2\u00a2\f\3\2\2\2\u00a3\u00a4\7q\2\2\u00a4"
|
||||
+ "\u00a5\7t\2\2\u00a5\u00a6\7f\2\2\u00a6\u00a7\7g\2\2\u00a7\u00a8\7t\2\2"
|
||||
+ "\u00a8\16\3\2\2\2\u00a9\u00aa\7d\2\2\u00aa\u00ab\7{\2\2\u00ab\20\3\2\2"
|
||||
+ "\2\u00ac\u00ad\7.\2\2\u00ad\22\3\2\2\2\u00ae\u00af\7p\2\2\u00af\u00b0"
|
||||
+ "\7w\2\2\u00b0\u00b1\7n\2\2\u00b1\u00b2\7n\2\2\u00b2\u00b3\7u\2\2\u00b3"
|
||||
+ "\24\3\2\2\2\u00b4\u00b5\7h\2\2\u00b5\u00b6\7k\2\2\u00b6\u00b7\7t\2\2\u00b7"
|
||||
+ "\u00b8\7u\2\2\u00b8\u00b9\7v\2\2\u00b9\26\3\2\2\2\u00ba\u00bb\7n\2\2\u00bb"
|
||||
+ "\u00bc\7c\2\2\u00bc\u00bd\7u\2\2\u00bd\u00be\7v\2\2\u00be\30\3\2\2\2\u00bf"
|
||||
+ "\u00c0\7c\2\2\u00c0\u00c1\7u\2\2\u00c1\u00c2\7e\2\2\u00c2\32\3\2\2\2\u00c3"
|
||||
+ "\u00c4\7f\2\2\u00c4\u00c5\7g\2\2\u00c5\u00c6\7u\2\2\u00c6\u00c7\7e\2\2"
|
||||
+ "\u00c7\34\3\2\2\2\u00c8\u00c9\7n\2\2\u00c9\u00ca\7k\2\2\u00ca\u00cb\7"
|
||||
+ "o\2\2\u00cb\u00cc\7k\2\2\u00cc\u00cd\7v\2\2\u00cd\36\3\2\2\2\u00ce\u00cf"
|
||||
+ "\7q\2\2\u00cf\u00d0\7h\2\2\u00d0\u00d1\7h\2\2\u00d1\u00d2\7u\2\2\u00d2"
|
||||
+ "\u00d3\7g\2\2\u00d3\u00d4\7v\2\2\u00d4 \3\2\2\2\u00d5\u00d6\7h\2\2\u00d6"
|
||||
+ "\u00d7\7g\2\2\u00d7\u00d8\7v\2\2\u00d8\u00d9\7e\2\2\u00d9\u00da\7j\2\2"
|
||||
+ "\u00da\"\3\2\2\2\u00db\u00dc\7-\2\2\u00dc$\3\2\2\2\u00dd\u00de\7s\2\2"
|
||||
+ "\u00de\u00df\7w\2\2\u00df\u00e0\7g\2\2\u00e0\u00e1\7t\2\2\u00e1\u00e2"
|
||||
+ "\7{\2\2\u00e2&\3\2\2\2\u00e3\u00e4\7n\2\2\u00e4\u00e5\7c\2\2\u00e5\u00e6"
|
||||
+ "\7|\2\2\u00e6\u00e7\7{\2\2\u00e7(\3\2\2\2\u00e8\u00e9\7q\2\2\u00e9\u00ea"
|
||||
+ "\7t\2\2\u00ea*\3\2\2\2\u00eb\u00ec\7c\2\2\u00ec\u00ed\7p\2\2\u00ed\u00ee"
|
||||
+ "\7f\2\2\u00ee,\3\2\2\2\u00ef\u00f0\7p\2\2\u00f0\u00f1\7q\2\2\u00f1\u00f2"
|
||||
+ "\7v\2\2\u00f2.\3\2\2\2\u00f3\u00f4\7k\2\2\u00f4\u00f5\7p\2\2\u00f5\60"
|
||||
+ "\3\2\2\2\u00f6\u00f7\7d\2\2\u00f7\u00f8\7g\2\2\u00f8\u00f9\7v\2\2\u00f9"
|
||||
+ "\u00fa\7y\2\2\u00fa\u00fb\7g\2\2\u00fb\u00fc\7g\2\2\u00fc\u00fd\7p\2\2"
|
||||
+ "\u00fd\62\3\2\2\2\u00fe\u00ff\7k\2\2\u00ff\u0100\7u\2\2\u0100\64\3\2\2"
|
||||
+ "\2\u0101\u0102\7p\2\2\u0102\u0103\7w\2\2\u0103\u0104\7n\2\2\u0104\u0105"
|
||||
+ "\7n\2\2\u0105\66\3\2\2\2\u0106\u0107\7k\2\2\u0107\u0108\7u\2\2\u0108\u0109"
|
||||
+ "\7P\2\2\u0109\u010a\7w\2\2\u010a\u010b\7n\2\2\u010b\u010c\7n\2\2\u010c"
|
||||
+ "8\3\2\2\2\u010d\u010e\7k\2\2\u010e\u010f\7u\2\2\u010f\u0110\7P\2\2\u0110"
|
||||
+ "\u0111\7q\2\2\u0111\u0112\7v\2\2\u0112\u0113\7P\2\2\u0113\u0114\7w\2\2"
|
||||
+ "\u0114\u0115\7n\2\2\u0115\u0116\7n\2\2\u0116:\3\2\2\2\u0117\u0118\7p\2"
|
||||
+ "\2\u0118\u0119\7q\2\2\u0119\u011a\7v\2\2\u011a\u011b\7P\2\2\u011b\u011c"
|
||||
+ "\7w\2\2\u011c\u011d\7n\2\2\u011d\u011e\7n\2\2\u011e<\3\2\2\2\u011f\u0120"
|
||||
+ "\7g\2\2\u0120\u0121\7o\2\2\u0121\u0122\7r\2\2\u0122\u0123\7v\2\2\u0123"
|
||||
+ "\u0124\7{\2\2\u0124>\3\2\2\2\u0125\u0126\7k\2\2\u0126\u0127\7u\2\2\u0127"
|
||||
+ "\u0128\7G\2\2\u0128\u0129\7o\2\2\u0129\u012a\7r\2\2\u012a\u012b\7v\2\2"
|
||||
+ "\u012b\u012c\7{\2\2\u012c@\3\2\2\2\u012d\u012e\7k\2\2\u012e\u012f\7u\2"
|
||||
+ "\2\u012f\u0130\7P\2\2\u0130\u0131\7q\2\2\u0131\u0132\7v\2\2\u0132\u0133"
|
||||
+ "\7G\2\2\u0133\u0134\7o\2\2\u0134\u0135\7r\2\2\u0135\u0136\7v\2\2\u0136"
|
||||
+ "\u0137\7{\2\2\u0137B\3\2\2\2\u0138\u0139\7p\2\2\u0139\u013a\7q\2\2\u013a"
|
||||
+ "\u013b\7v\2\2\u013b\u013c\7G\2\2\u013c\u013d\7o\2\2\u013d\u013e\7r\2\2"
|
||||
+ "\u013e\u013f\7v\2\2\u013f\u0140\7{\2\2\u0140D\3\2\2\2\u0141\u0142\7n\2"
|
||||
+ "\2\u0142\u0143\7k\2\2\u0143\u0144\7m\2\2\u0144\u0145\7g\2\2\u0145F\3\2"
|
||||
+ "\2\2\u0146\u0147\7k\2\2\u0147\u0148\7n\2\2\u0148\u0149\7k\2\2\u0149\u014a"
|
||||
+ "\7m\2\2\u014a\u014b\7g\2\2\u014bH\3\2\2\2\u014c\u014d\7e\2\2\u014d\u014e"
|
||||
+ "\7q\2\2\u014e\u014f\7p\2\2\u014f\u0150\7v\2\2\u0150\u0151\7c\2\2\u0151"
|
||||
+ "\u0152\7k\2\2\u0152\u0153\7p\2\2\u0153\u0154\7u\2\2\u0154J\3\2\2\2\u0155"
|
||||
+ "\u0156\7k\2\2\u0156\u0157\7e\2\2\u0157\u0158\7q\2\2\u0158\u0159\7p\2\2"
|
||||
+ "\u0159\u015a\7v\2\2\u015a\u015b\7c\2\2\u015b\u015c\7k\2\2\u015c\u015d"
|
||||
+ "\7p\2\2\u015d\u015e\7u\2\2\u015eL\3\2\2\2\u015f\u0160\7u\2\2\u0160\u0161"
|
||||
+ "\7v\2\2\u0161\u0162\7c\2\2\u0162\u0163\7t\2\2\u0163\u0164\7v\2\2\u0164"
|
||||
+ "\u0165\7u\2\2\u0165\u0166\7Y\2\2\u0166\u0167\7k\2\2\u0167\u0168\7v\2\2"
|
||||
+ "\u0168\u0169\7j\2\2\u0169N\3\2\2\2\u016a\u016b\7k\2\2\u016b\u016c\7u\2"
|
||||
+ "\2\u016c\u016d\7v\2\2\u016d\u016e\7c\2\2\u016e\u016f\7t\2\2\u016f\u0170"
|
||||
+ "\7v\2\2\u0170\u0171\7u\2\2\u0171\u0172\7Y\2\2\u0172\u0173\7k\2\2\u0173"
|
||||
+ "\u0174\7v\2\2\u0174\u0175\7j\2\2\u0175P\3\2\2\2\u0176\u0177\7g\2\2\u0177"
|
||||
+ "\u0178\7p\2\2\u0178\u0179\7f\2\2\u0179\u017a\7u\2\2\u017a\u017b\7Y\2\2"
|
||||
+ "\u017b\u017c\7k\2\2\u017c\u017d\7v\2\2\u017d\u017e\7j\2\2\u017eR\3\2\2"
|
||||
+ "\2\u017f\u0180\7k\2\2\u0180\u0181\7g\2\2\u0181\u0182\7p\2\2\u0182\u0183"
|
||||
+ "\7f\2\2\u0183\u0184\7u\2\2\u0184\u0185\7Y\2\2\u0185\u0186\7k\2\2\u0186"
|
||||
+ "\u0187\7v\2\2\u0187\u0188\7j\2\2\u0188T\3\2\2\2\u0189\u018a\7?\2\2\u018a"
|
||||
+ "V\3\2\2\2\u018b\u018c\7g\2\2\u018c\u018d\7s\2\2\u018dX\3\2\2\2\u018e\u018f"
|
||||
+ "\7@\2\2\u018fZ\3\2\2\2\u0190\u0191\7i\2\2\u0191\u0192\7v\2\2\u0192\\\3"
|
||||
+ "\2\2\2\u0193\u0194\7@\2\2\u0194\u0195\7?\2\2\u0195^\3\2\2\2\u0196\u0197"
|
||||
+ "\7i\2\2\u0197\u0198\7g\2\2\u0198`\3\2\2\2\u0199\u019a\7i\2\2\u019a\u019b"
|
||||
+ "\7v\2\2\u019b\u019c\7g\2\2\u019cb\3\2\2\2\u019d\u019e\7>\2\2\u019ed\3"
|
||||
+ "\2\2\2\u019f\u01a0\7n\2\2\u01a0\u01a1\7v\2\2\u01a1f\3\2\2\2\u01a2\u01a3"
|
||||
+ "\7>\2\2\u01a3\u01a4\7?\2\2\u01a4h\3\2\2\2\u01a5\u01a6\7n\2\2\u01a6\u01a7"
|
||||
+ "\7g\2\2\u01a7j\3\2\2\2\u01a8\u01a9\7n\2\2\u01a9\u01aa\7v\2\2\u01aa\u01ab"
|
||||
+ "\7g\2\2\u01abl\3\2\2\2\u01ac\u01ad\7>\2\2\u01ad\u01ae\7@\2\2\u01aen\3"
|
||||
+ "\2\2\2\u01af\u01b0\7#\2\2\u01b0\u01b1\7?\2\2\u01b1p\3\2\2\2\u01b2\u01b3"
|
||||
+ "\7p\2\2\u01b3\u01b4\7g\2\2\u01b4r\3\2\2\2\u01b5\u01b6\7k\2\2\u01b6\u01b7"
|
||||
+ "\7g\2\2\u01b7\u01b8\7s\2\2\u01b8t\3\2\2\2\u01b9\u01ba\7k\2\2\u01ba\u01bb"
|
||||
+ "\7p\2\2\u01bb\u01bc\7g\2\2\u01bcv\3\2\2\2\u01bd\u01be\7<\2\2\u01be\u01c2"
|
||||
+ "\t\2\2\2\u01bf\u01c1\t\3\2\2\u01c0\u01bf\3\2\2\2\u01c1\u01c4\3\2\2\2\u01c2"
|
||||
+ "\u01c0\3\2\2\2\u01c2\u01c3\3\2\2\2\u01c3x\3\2\2\2\u01c4\u01c2\3\2\2\2"
|
||||
+ "\u01c5\u01c9\t\2\2\2\u01c6\u01c8\t\4\2\2\u01c7\u01c6\3\2\2\2\u01c8\u01cb"
|
||||
+ "\3\2\2\2\u01c9\u01c7\3\2\2\2\u01c9\u01ca\3\2\2\2\u01caz\3\2\2\2\u01cb"
|
||||
+ "\u01c9\3\2\2\2\u01cc\u01cd\7v\2\2\u01cd\u01ce\7t\2\2\u01ce\u01cf\7w\2"
|
||||
+ "\2\u01cf\u01d6\7g\2\2\u01d0\u01d1\7h\2\2\u01d1\u01d2\7c\2\2\u01d2\u01d3"
|
||||
+ "\7n\2\2\u01d3\u01d4\7u\2\2\u01d4\u01d6\7g\2\2\u01d5\u01cc\3\2\2\2\u01d5"
|
||||
+ "\u01d0\3\2\2\2\u01d6|\3\2\2\2\u01d7\u01d9\7/\2\2\u01d8\u01d7\3\2\2\2\u01d8"
|
||||
+ "\u01d9\3\2\2\2\u01d9\u01da\3\2\2\2\u01da\u01e1\5\177@\2\u01db\u01dd\7"
|
||||
+ "/\2\2\u01dc\u01db\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd\u01de\3\2\2\2\u01de"
|
||||
+ "\u01e1\5\u0081A\2\u01df\u01e1\5\u0083B\2\u01e0\u01d8\3\2\2\2\u01e0\u01dc"
|
||||
+ "\3\2\2\2\u01e0\u01df\3\2\2\2\u01e1~\3\2\2\2\u01e2\u01e4\t\5\2\2\u01e3"
|
||||
+ "\u01e2\3\2\2\2\u01e4\u01e5\3\2\2\2\u01e5\u01e3\3\2\2\2\u01e5\u01e6\3\2"
|
||||
+ "\2\2\u01e6\u01e7\3\2\2\2\u01e7\u01eb\7\60\2\2\u01e8\u01ea\t\5\2\2\u01e9"
|
||||
+ "\u01e8\3\2\2\2\u01ea\u01ed\3\2\2\2\u01eb\u01e9\3\2\2\2\u01eb\u01ec\3\2"
|
||||
+ "\2\2\u01ec\u0080\3\2\2\2\u01ed\u01eb\3\2\2\2\u01ee\u01f2\t\6\2\2\u01ef"
|
||||
+ "\u01f1\t\5\2\2\u01f0\u01ef\3\2\2\2\u01f1\u01f4\3\2\2\2\u01f2\u01f0\3\2"
|
||||
+ "\2\2\u01f2\u01f3\3\2\2\2\u01f3\u0082\3\2\2\2\u01f4\u01f2\3\2\2\2\u01f5"
|
||||
+ "\u01f6\7\62\2\2\u01f6\u0084\3\2\2\2\u01f7\u01fd\7)\2\2\u01f8\u01fc\n\7"
|
||||
+ "\2\2\u01f9\u01fa\7)\2\2\u01fa\u01fc\7)\2\2\u01fb\u01f8\3\2\2\2\u01fb\u01f9"
|
||||
+ "\3\2\2\2\u01fc\u01ff\3\2\2\2\u01fd\u01fb\3\2\2\2\u01fd\u01fe\3\2\2\2\u01fe"
|
||||
+ "\u0200\3\2\2\2\u01ff\u01fd\3\2\2\2\u0200\u0201\7)\2\2\u0201\u0086\3\2"
|
||||
+ "\2\2\u0202\u0203\t\b\2\2\u0203\u0204\3\2\2\2\u0204\u0205\bD\2\2\u0205"
|
||||
+ "\u0088\3\2\2\2\16\2\u01c2\u01c9\u01d5\u01d8\u01dc\u01e0\u01e5\u01eb\u01f2" + "\u01fb\u01fd\3\b\2\2";
|
||||
public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2I\u0249\b\1\4\2\t"+
|
||||
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
|
||||
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
|
||||
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
|
||||
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
|
||||
"\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+
|
||||
",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+
|
||||
"\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+
|
||||
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\3\2"+
|
||||
"\3\2\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
|
||||
"\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3\b\3\t"+
|
||||
"\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\f\3\f\3\f"+
|
||||
"\3\f\3\f\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17"+
|
||||
"\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21"+
|
||||
"\3\21\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\24"+
|
||||
"\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3\27\3\30\3\30\3\30"+
|
||||
"\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32"+
|
||||
"\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\35\3\36"+
|
||||
"\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3\37\3\37\3\37"+
|
||||
"\3\37\3\37\3 \3 \3 \3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3!\3\"\3\"\3\"\3\"\3"+
|
||||
"\"\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3$\3"+
|
||||
"$\3$\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3\'\3\'\3\'"+
|
||||
"\3\'\3(\3(\3(\3(\3(\3(\3(\3(\3(\3(\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3)\3"+
|
||||
"*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3+\3+\3+\3,\3,\3"+
|
||||
",\3,\3,\3,\3,\3,\3,\3,\3-\3-\3.\3.\3.\3/\3/\3\60\3\60\3\60\3\61\3\61\3"+
|
||||
"\61\3\62\3\62\3\62\3\63\3\63\3\63\3\63\3\64\3\64\3\65\3\65\3\65\3\66\3"+
|
||||
"\66\3\66\3\67\3\67\3\67\38\38\38\38\39\39\39\3:\3:\3:\3;\3;\3;\3<\3<\3"+
|
||||
"<\3<\3=\3=\3=\3=\3>\3>\3>\7>\u01d4\n>\f>\16>\u01d7\13>\3?\3?\7?\u01db"+
|
||||
"\n?\f?\16?\u01de\13?\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3"+
|
||||
"A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3A\3"+
|
||||
"A\3A\3A\3A\3A\3A\3A\5A\u020e\nA\3B\3B\3B\3B\3B\3B\3B\3B\3B\5B\u0219\n"+
|
||||
"B\3C\5C\u021c\nC\3C\3C\5C\u0220\nC\3C\3C\5C\u0224\nC\3D\6D\u0227\nD\r"+
|
||||
"D\16D\u0228\3D\3D\7D\u022d\nD\fD\16D\u0230\13D\3E\3E\7E\u0234\nE\fE\16"+
|
||||
"E\u0237\13E\3F\3F\3G\3G\3G\3G\7G\u023f\nG\fG\16G\u0242\13G\3G\3G\3H\3"+
|
||||
"H\3H\3H\2\2I\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16"+
|
||||
"\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34"+
|
||||
"\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g"+
|
||||
"\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087E\u0089F"+
|
||||
"\u008bG\u008dH\u008fI\3\2\t\5\2C\\aac|\6\2\62;C\\aac|\7\2\60\60\62;C\\"+
|
||||
"aac|\3\2\62;\3\2\63;\3\2))\5\2\13\f\17\17\"\"\2\u0258\2\3\3\2\2\2\2\5"+
|
||||
"\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2"+
|
||||
"\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33"+
|
||||
"\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2"+
|
||||
"\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2"+
|
||||
"\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2"+
|
||||
"\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K"+
|
||||
"\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2"+
|
||||
"\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2"+
|
||||
"\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2\2\2o\3\2\2\2\2q"+
|
||||
"\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3\2"+
|
||||
"\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085\3\2\2\2\2\u0087"+
|
||||
"\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2\2\2\u008f\3\2\2"+
|
||||
"\2\3\u0091\3\2\2\2\5\u0093\3\2\2\2\7\u0095\3\2\2\2\t\u009c\3\2\2\2\13"+
|
||||
"\u00a5\3\2\2\2\r\u00ab\3\2\2\2\17\u00b1\3\2\2\2\21\u00b4\3\2\2\2\23\u00b6"+
|
||||
"\3\2\2\2\25\u00bc\3\2\2\2\27\u00c2\3\2\2\2\31\u00c7\3\2\2\2\33\u00cb\3"+
|
||||
"\2\2\2\35\u00d0\3\2\2\2\37\u00d6\3\2\2\2!\u00dd\3\2\2\2#\u00e3\3\2\2\2"+
|
||||
"%\u00e5\3\2\2\2\'\u00eb\3\2\2\2)\u00f0\3\2\2\2+\u00f3\3\2\2\2-\u00f7\3"+
|
||||
"\2\2\2/\u00fb\3\2\2\2\61\u00fe\3\2\2\2\63\u0106\3\2\2\2\65\u010e\3\2\2"+
|
||||
"\2\67\u0111\3\2\2\29\u0114\3\2\2\2;\u0119\3\2\2\2=\u0120\3\2\2\2?\u012a"+
|
||||
"\3\2\2\2A\u0132\3\2\2\2C\u0138\3\2\2\2E\u0140\3\2\2\2G\u014b\3\2\2\2I"+
|
||||
"\u0154\3\2\2\2K\u0159\3\2\2\2M\u015f\3\2\2\2O\u0168\3\2\2\2Q\u0172\3\2"+
|
||||
"\2\2S\u017d\3\2\2\2U\u0189\3\2\2\2W\u0192\3\2\2\2Y\u019c\3\2\2\2[\u019e"+
|
||||
"\3\2\2\2]\u01a1\3\2\2\2_\u01a3\3\2\2\2a\u01a6\3\2\2\2c\u01a9\3\2\2\2e"+
|
||||
"\u01ac\3\2\2\2g\u01b0\3\2\2\2i\u01b2\3\2\2\2k\u01b5\3\2\2\2m\u01b8\3\2"+
|
||||
"\2\2o\u01bb\3\2\2\2q\u01bf\3\2\2\2s\u01c2\3\2\2\2u\u01c5\3\2\2\2w\u01c8"+
|
||||
"\3\2\2\2y\u01cc\3\2\2\2{\u01d0\3\2\2\2}\u01d8\3\2\2\2\177\u01df\3\2\2"+
|
||||
"\2\u0081\u020d\3\2\2\2\u0083\u0218\3\2\2\2\u0085\u0223\3\2\2\2\u0087\u0226"+
|
||||
"\3\2\2\2\u0089\u0231\3\2\2\2\u008b\u0238\3\2\2\2\u008d\u023a\3\2\2\2\u008f"+
|
||||
"\u0245\3\2\2\2\u0091\u0092\7*\2\2\u0092\4\3\2\2\2\u0093\u0094\7+\2\2\u0094"+
|
||||
"\6\3\2\2\2\u0095\u0096\7u\2\2\u0096\u0097\7g\2\2\u0097\u0098\7n\2\2\u0098"+
|
||||
"\u0099\7g\2\2\u0099\u009a\7e\2\2\u009a\u009b\7v\2\2\u009b\b\3\2\2\2\u009c"+
|
||||
"\u009d\7f\2\2\u009d\u009e\7k\2\2\u009e\u009f\7u\2\2\u009f\u00a0\7v\2\2"+
|
||||
"\u00a0\u00a1\7k\2\2\u00a1\u00a2\7p\2\2\u00a2\u00a3\7e\2\2\u00a3\u00a4"+
|
||||
"\7v\2\2\u00a4\n\3\2\2\2\u00a5\u00a6\7y\2\2\u00a6\u00a7\7j\2\2\u00a7\u00a8"+
|
||||
"\7g\2\2\u00a8\u00a9\7t\2\2\u00a9\u00aa\7g\2\2\u00aa\f\3\2\2\2\u00ab\u00ac"+
|
||||
"\7q\2\2\u00ac\u00ad\7t\2\2\u00ad\u00ae\7f\2\2\u00ae\u00af\7g\2\2\u00af"+
|
||||
"\u00b0\7t\2\2\u00b0\16\3\2\2\2\u00b1\u00b2\7d\2\2\u00b2\u00b3\7{\2\2\u00b3"+
|
||||
"\20\3\2\2\2\u00b4\u00b5\7.\2\2\u00b5\22\3\2\2\2\u00b6\u00b7\7p\2\2\u00b7"+
|
||||
"\u00b8\7w\2\2\u00b8\u00b9\7n\2\2\u00b9\u00ba\7n\2\2\u00ba\u00bb\7u\2\2"+
|
||||
"\u00bb\24\3\2\2\2\u00bc\u00bd\7h\2\2\u00bd\u00be\7k\2\2\u00be\u00bf\7"+
|
||||
"t\2\2\u00bf\u00c0\7u\2\2\u00c0\u00c1\7v\2\2\u00c1\26\3\2\2\2\u00c2\u00c3"+
|
||||
"\7n\2\2\u00c3\u00c4\7c\2\2\u00c4\u00c5\7u\2\2\u00c5\u00c6\7v\2\2\u00c6"+
|
||||
"\30\3\2\2\2\u00c7\u00c8\7c\2\2\u00c8\u00c9\7u\2\2\u00c9\u00ca\7e\2\2\u00ca"+
|
||||
"\32\3\2\2\2\u00cb\u00cc\7f\2\2\u00cc\u00cd\7g\2\2\u00cd\u00ce\7u\2\2\u00ce"+
|
||||
"\u00cf\7e\2\2\u00cf\34\3\2\2\2\u00d0\u00d1\7n\2\2\u00d1\u00d2\7k\2\2\u00d2"+
|
||||
"\u00d3\7o\2\2\u00d3\u00d4\7k\2\2\u00d4\u00d5\7v\2\2\u00d5\36\3\2\2\2\u00d6"+
|
||||
"\u00d7\7q\2\2\u00d7\u00d8\7h\2\2\u00d8\u00d9\7h\2\2\u00d9\u00da\7u\2\2"+
|
||||
"\u00da\u00db\7g\2\2\u00db\u00dc\7v\2\2\u00dc \3\2\2\2\u00dd\u00de\7h\2"+
|
||||
"\2\u00de\u00df\7g\2\2\u00df\u00e0\7v\2\2\u00e0\u00e1\7e\2\2\u00e1\u00e2"+
|
||||
"\7j\2\2\u00e2\"\3\2\2\2\u00e3\u00e4\7-\2\2\u00e4$\3\2\2\2\u00e5\u00e6"+
|
||||
"\7s\2\2\u00e6\u00e7\7w\2\2\u00e7\u00e8\7g\2\2\u00e8\u00e9\7t\2\2\u00e9"+
|
||||
"\u00ea\7{\2\2\u00ea&\3\2\2\2\u00eb\u00ec\7n\2\2\u00ec\u00ed\7c\2\2\u00ed"+
|
||||
"\u00ee\7|\2\2\u00ee\u00ef\7{\2\2\u00ef(\3\2\2\2\u00f0\u00f1\7q\2\2\u00f1"+
|
||||
"\u00f2\7t\2\2\u00f2*\3\2\2\2\u00f3\u00f4\7c\2\2\u00f4\u00f5\7p\2\2\u00f5"+
|
||||
"\u00f6\7f\2\2\u00f6,\3\2\2\2\u00f7\u00f8\7p\2\2\u00f8\u00f9\7q\2\2\u00f9"+
|
||||
"\u00fa\7v\2\2\u00fa.\3\2\2\2\u00fb\u00fc\7k\2\2\u00fc\u00fd\7p\2\2\u00fd"+
|
||||
"\60\3\2\2\2\u00fe\u00ff\7d\2\2\u00ff\u0100\7g\2\2\u0100\u0101\7v\2\2\u0101"+
|
||||
"\u0102\7y\2\2\u0102\u0103\7g\2\2\u0103\u0104\7g\2\2\u0104\u0105\7p\2\2"+
|
||||
"\u0105\62\3\2\2\2\u0106\u0107\7k\2\2\u0107\u0108\7p\2\2\u0108\u0109\7"+
|
||||
"t\2\2\u0109\u010a\7c\2\2\u010a\u010b\7p\2\2\u010b\u010c\7i\2\2\u010c\u010d"+
|
||||
"\7g\2\2\u010d\64\3\2\2\2\u010e\u010f\7v\2\2\u010f\u0110\7q\2\2\u0110\66"+
|
||||
"\3\2\2\2\u0111\u0112\7k\2\2\u0112\u0113\7u\2\2\u01138\3\2\2\2\u0114\u0115"+
|
||||
"\7p\2\2\u0115\u0116\7w\2\2\u0116\u0117\7n\2\2\u0117\u0118\7n\2\2\u0118"+
|
||||
":\3\2\2\2\u0119\u011a\7k\2\2\u011a\u011b\7u\2\2\u011b\u011c\7P\2\2\u011c"+
|
||||
"\u011d\7w\2\2\u011d\u011e\7n\2\2\u011e\u011f\7n\2\2\u011f<\3\2\2\2\u0120"+
|
||||
"\u0121\7k\2\2\u0121\u0122\7u\2\2\u0122\u0123\7P\2\2\u0123\u0124\7q\2\2"+
|
||||
"\u0124\u0125\7v\2\2\u0125\u0126\7P\2\2\u0126\u0127\7w\2\2\u0127\u0128"+
|
||||
"\7n\2\2\u0128\u0129\7n\2\2\u0129>\3\2\2\2\u012a\u012b\7p\2\2\u012b\u012c"+
|
||||
"\7q\2\2\u012c\u012d\7v\2\2\u012d\u012e\7P\2\2\u012e\u012f\7w\2\2\u012f"+
|
||||
"\u0130\7n\2\2\u0130\u0131\7n\2\2\u0131@\3\2\2\2\u0132\u0133\7g\2\2\u0133"+
|
||||
"\u0134\7o\2\2\u0134\u0135\7r\2\2\u0135\u0136\7v\2\2\u0136\u0137\7{\2\2"+
|
||||
"\u0137B\3\2\2\2\u0138\u0139\7k\2\2\u0139\u013a\7u\2\2\u013a\u013b\7G\2"+
|
||||
"\2\u013b\u013c\7o\2\2\u013c\u013d\7r\2\2\u013d\u013e\7v\2\2\u013e\u013f"+
|
||||
"\7{\2\2\u013fD\3\2\2\2\u0140\u0141\7k\2\2\u0141\u0142\7u\2\2\u0142\u0143"+
|
||||
"\7P\2\2\u0143\u0144\7q\2\2\u0144\u0145\7v\2\2\u0145\u0146\7G\2\2\u0146"+
|
||||
"\u0147\7o\2\2\u0147\u0148\7r\2\2\u0148\u0149\7v\2\2\u0149\u014a\7{\2\2"+
|
||||
"\u014aF\3\2\2\2\u014b\u014c\7p\2\2\u014c\u014d\7q\2\2\u014d\u014e\7v\2"+
|
||||
"\2\u014e\u014f\7G\2\2\u014f\u0150\7o\2\2\u0150\u0151\7r\2\2\u0151\u0152"+
|
||||
"\7v\2\2\u0152\u0153\7{\2\2\u0153H\3\2\2\2\u0154\u0155\7n\2\2\u0155\u0156"+
|
||||
"\7k\2\2\u0156\u0157\7m\2\2\u0157\u0158\7g\2\2\u0158J\3\2\2\2\u0159\u015a"+
|
||||
"\7k\2\2\u015a\u015b\7n\2\2\u015b\u015c\7k\2\2\u015c\u015d\7m\2\2\u015d"+
|
||||
"\u015e\7g\2\2\u015eL\3\2\2\2\u015f\u0160\7e\2\2\u0160\u0161\7q\2\2\u0161"+
|
||||
"\u0162\7p\2\2\u0162\u0163\7v\2\2\u0163\u0164\7c\2\2\u0164\u0165\7k\2\2"+
|
||||
"\u0165\u0166\7p\2\2\u0166\u0167\7u\2\2\u0167N\3\2\2\2\u0168\u0169\7k\2"+
|
||||
"\2\u0169\u016a\7e\2\2\u016a\u016b\7q\2\2\u016b\u016c\7p\2\2\u016c\u016d"+
|
||||
"\7v\2\2\u016d\u016e\7c\2\2\u016e\u016f\7k\2\2\u016f\u0170\7p\2\2\u0170"+
|
||||
"\u0171\7u\2\2\u0171P\3\2\2\2\u0172\u0173\7u\2\2\u0173\u0174\7v\2\2\u0174"+
|
||||
"\u0175\7c\2\2\u0175\u0176\7t\2\2\u0176\u0177\7v\2\2\u0177\u0178\7u\2\2"+
|
||||
"\u0178\u0179\7Y\2\2\u0179\u017a\7k\2\2\u017a\u017b\7v\2\2\u017b\u017c"+
|
||||
"\7j\2\2\u017cR\3\2\2\2\u017d\u017e\7k\2\2\u017e\u017f\7u\2\2\u017f\u0180"+
|
||||
"\7v\2\2\u0180\u0181\7c\2\2\u0181\u0182\7t\2\2\u0182\u0183\7v\2\2\u0183"+
|
||||
"\u0184\7u\2\2\u0184\u0185\7Y\2\2\u0185\u0186\7k\2\2\u0186\u0187\7v\2\2"+
|
||||
"\u0187\u0188\7j\2\2\u0188T\3\2\2\2\u0189\u018a\7g\2\2\u018a\u018b\7p\2"+
|
||||
"\2\u018b\u018c\7f\2\2\u018c\u018d\7u\2\2\u018d\u018e\7Y\2\2\u018e\u018f"+
|
||||
"\7k\2\2\u018f\u0190\7v\2\2\u0190\u0191\7j\2\2\u0191V\3\2\2\2\u0192\u0193"+
|
||||
"\7k\2\2\u0193\u0194\7g\2\2\u0194\u0195\7p\2\2\u0195\u0196\7f\2\2\u0196"+
|
||||
"\u0197\7u\2\2\u0197\u0198\7Y\2\2\u0198\u0199\7k\2\2\u0199\u019a\7v\2\2"+
|
||||
"\u019a\u019b\7j\2\2\u019bX\3\2\2\2\u019c\u019d\7?\2\2\u019dZ\3\2\2\2\u019e"+
|
||||
"\u019f\7g\2\2\u019f\u01a0\7s\2\2\u01a0\\\3\2\2\2\u01a1\u01a2\7@\2\2\u01a2"+
|
||||
"^\3\2\2\2\u01a3\u01a4\7i\2\2\u01a4\u01a5\7v\2\2\u01a5`\3\2\2\2\u01a6\u01a7"+
|
||||
"\7@\2\2\u01a7\u01a8\7?\2\2\u01a8b\3\2\2\2\u01a9\u01aa\7i\2\2\u01aa\u01ab"+
|
||||
"\7g\2\2\u01abd\3\2\2\2\u01ac\u01ad\7i\2\2\u01ad\u01ae\7v\2\2\u01ae\u01af"+
|
||||
"\7g\2\2\u01aff\3\2\2\2\u01b0\u01b1\7>\2\2\u01b1h\3\2\2\2\u01b2\u01b3\7"+
|
||||
"n\2\2\u01b3\u01b4\7v\2\2\u01b4j\3\2\2\2\u01b5\u01b6\7>\2\2\u01b6\u01b7"+
|
||||
"\7?\2\2\u01b7l\3\2\2\2\u01b8\u01b9\7n\2\2\u01b9\u01ba\7g\2\2\u01ban\3"+
|
||||
"\2\2\2\u01bb\u01bc\7n\2\2\u01bc\u01bd\7v\2\2\u01bd\u01be\7g\2\2\u01be"+
|
||||
"p\3\2\2\2\u01bf\u01c0\7>\2\2\u01c0\u01c1\7@\2\2\u01c1r\3\2\2\2\u01c2\u01c3"+
|
||||
"\7#\2\2\u01c3\u01c4\7?\2\2\u01c4t\3\2\2\2\u01c5\u01c6\7p\2\2\u01c6\u01c7"+
|
||||
"\7g\2\2\u01c7v\3\2\2\2\u01c8\u01c9\7k\2\2\u01c9\u01ca\7g\2\2\u01ca\u01cb"+
|
||||
"\7s\2\2\u01cbx\3\2\2\2\u01cc\u01cd\7k\2\2\u01cd\u01ce\7p\2\2\u01ce\u01cf"+
|
||||
"\7g\2\2\u01cfz\3\2\2\2\u01d0\u01d1\7<\2\2\u01d1\u01d5\t\2\2\2\u01d2\u01d4"+
|
||||
"\t\3\2\2\u01d3\u01d2\3\2\2\2\u01d4\u01d7\3\2\2\2\u01d5\u01d3\3\2\2\2\u01d5"+
|
||||
"\u01d6\3\2\2\2\u01d6|\3\2\2\2\u01d7\u01d5\3\2\2\2\u01d8\u01dc\t\2\2\2"+
|
||||
"\u01d9\u01db\t\4\2\2\u01da\u01d9\3\2\2\2\u01db\u01de\3\2\2\2\u01dc\u01da"+
|
||||
"\3\2\2\2\u01dc\u01dd\3\2\2\2\u01dd~\3\2\2\2\u01de\u01dc\3\2\2\2\u01df"+
|
||||
"\u01e0\7b\2\2\u01e0\u01e1\5}?\2\u01e1\u01e2\7b\2\2\u01e2\u0080\3\2\2\2"+
|
||||
"\u01e3\u01e4\7u\2\2\u01e4\u01e5\7w\2\2\u01e5\u01e6\7o\2\2\u01e6\u01e7"+
|
||||
"\7*\2\2\u01e7\u01e8\3\2\2\2\u01e8\u01e9\5}?\2\u01e9\u01ea\7+\2\2\u01ea"+
|
||||
"\u020e\3\2\2\2\u01eb\u01ec\7o\2\2\u01ec\u01ed\7c\2\2\u01ed\u01ee\7z\2"+
|
||||
"\2\u01ee\u01ef\7*\2\2\u01ef\u01f0\3\2\2\2\u01f0\u01f1\5}?\2\u01f1\u01f2"+
|
||||
"\7+\2\2\u01f2\u020e\3\2\2\2\u01f3\u01f4\7o\2\2\u01f4\u01f5\7k\2\2\u01f5"+
|
||||
"\u01f6\7p\2\2\u01f6\u01f7\7*\2\2\u01f7\u01f8\3\2\2\2\u01f8\u01f9\5}?\2"+
|
||||
"\u01f9\u01fa\7+\2\2\u01fa\u020e\3\2\2\2\u01fb\u01fc\7c\2\2\u01fc\u01fd"+
|
||||
"\7x\2\2\u01fd\u01fe\7i\2\2\u01fe\u01ff\7*\2\2\u01ff\u0200\3\2\2\2\u0200"+
|
||||
"\u0201\5}?\2\u0201\u0202\7+\2\2\u0202\u020e\3\2\2\2\u0203\u0204\7e\2\2"+
|
||||
"\u0204\u0205\7q\2\2\u0205\u0206\7w\2\2\u0206\u0207\7p\2\2\u0207\u0208"+
|
||||
"\7v\2\2\u0208\u0209\7*\2\2\u0209\u020a\3\2\2\2\u020a\u020b\5}?\2\u020b"+
|
||||
"\u020c\7+\2\2\u020c\u020e\3\2\2\2\u020d\u01e3\3\2\2\2\u020d\u01eb\3\2"+
|
||||
"\2\2\u020d\u01f3\3\2\2\2\u020d\u01fb\3\2\2\2\u020d\u0203\3\2\2\2\u020e"+
|
||||
"\u0082\3\2\2\2\u020f\u0210\7v\2\2\u0210\u0211\7t\2\2\u0211\u0212\7w\2"+
|
||||
"\2\u0212\u0219\7g\2\2\u0213\u0214\7h\2\2\u0214\u0215\7c\2\2\u0215\u0216"+
|
||||
"\7n\2\2\u0216\u0217\7u\2\2\u0217\u0219\7g\2\2\u0218\u020f\3\2\2\2\u0218"+
|
||||
"\u0213\3\2\2\2\u0219\u0084\3\2\2\2\u021a\u021c\7/\2\2\u021b\u021a\3\2"+
|
||||
"\2\2\u021b\u021c\3\2\2\2\u021c\u021d\3\2\2\2\u021d\u0224\5\u0087D\2\u021e"+
|
||||
"\u0220\7/\2\2\u021f\u021e\3\2\2\2\u021f\u0220\3\2\2\2\u0220\u0221\3\2"+
|
||||
"\2\2\u0221\u0224\5\u0089E\2\u0222\u0224\5\u008bF\2\u0223\u021b\3\2\2\2"+
|
||||
"\u0223\u021f\3\2\2\2\u0223\u0222\3\2\2\2\u0224\u0086\3\2\2\2\u0225\u0227"+
|
||||
"\t\5\2\2\u0226\u0225\3\2\2\2\u0227\u0228\3\2\2\2\u0228\u0226\3\2\2\2\u0228"+
|
||||
"\u0229\3\2\2\2\u0229\u022a\3\2\2\2\u022a\u022e\7\60\2\2\u022b\u022d\t"+
|
||||
"\5\2\2\u022c\u022b\3\2\2\2\u022d\u0230\3\2\2\2\u022e\u022c\3\2\2\2\u022e"+
|
||||
"\u022f\3\2\2\2\u022f\u0088\3\2\2\2\u0230\u022e\3\2\2\2\u0231\u0235\t\6"+
|
||||
"\2\2\u0232\u0234\t\5\2\2\u0233\u0232\3\2\2\2\u0234\u0237\3\2\2\2\u0235"+
|
||||
"\u0233\3\2\2\2\u0235\u0236\3\2\2\2\u0236\u008a\3\2\2\2\u0237\u0235\3\2"+
|
||||
"\2\2\u0238\u0239\7\62\2\2\u0239\u008c\3\2\2\2\u023a\u0240\7)\2\2\u023b"+
|
||||
"\u023f\n\7\2\2\u023c\u023d\7)\2\2\u023d\u023f\7)\2\2\u023e\u023b\3\2\2"+
|
||||
"\2\u023e\u023c\3\2\2\2\u023f\u0242\3\2\2\2\u0240\u023e\3\2\2\2\u0240\u0241"+
|
||||
"\3\2\2\2\u0241\u0243\3\2\2\2\u0242\u0240\3\2\2\2\u0243\u0244\7)\2\2\u0244"+
|
||||
"\u008e\3\2\2\2\u0245\u0246\t\b\2\2\u0246\u0247\3\2\2\2\u0247\u0248\bH"+
|
||||
"\2\2\u0248\u0090\3\2\2\2\17\2\u01d5\u01dc\u020d\u0218\u021b\u021f\u0223"+
|
||||
"\u0228\u022e\u0235\u023e\u0240\3\b\2\2";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,18 +56,22 @@ T__54=55
|
||||
T__55=56
|
||||
T__56=57
|
||||
T__57=58
|
||||
INPUT_VARIABLE=59
|
||||
PATH_VARIABLE=60
|
||||
BOOLEAN_LITERAL=61
|
||||
NUMBER_LITERAL=62
|
||||
DOUBLE=63
|
||||
INT=64
|
||||
ZERO=65
|
||||
STRING_LITERAL=66
|
||||
WS=67
|
||||
'select'=1
|
||||
'('=2
|
||||
')'=3
|
||||
T__58=59
|
||||
T__59=60
|
||||
INPUT_VARIABLE=61
|
||||
PATH_VARIABLE=62
|
||||
QUOTED_PATH_VARIABLE=63
|
||||
PROP_FORMULA=64
|
||||
BOOLEAN_LITERAL=65
|
||||
NUMBER_LITERAL=66
|
||||
DOUBLE=67
|
||||
INT=68
|
||||
ZERO=69
|
||||
STRING_LITERAL=70
|
||||
WS=71
|
||||
'('=1
|
||||
')'=2
|
||||
'select'=3
|
||||
'distinct'=4
|
||||
'where'=5
|
||||
'order'=6
|
||||
@@ -89,38 +93,40 @@ WS=67
|
||||
'not'=22
|
||||
'in'=23
|
||||
'between'=24
|
||||
'is'=25
|
||||
'null'=26
|
||||
'isNull'=27
|
||||
'isNotNull'=28
|
||||
'notNull'=29
|
||||
'empty'=30
|
||||
'isEmpty'=31
|
||||
'isNotEmpty'=32
|
||||
'notEmpty'=33
|
||||
'like'=34
|
||||
'ilike'=35
|
||||
'contains'=36
|
||||
'icontains'=37
|
||||
'startsWith'=38
|
||||
'istartsWith'=39
|
||||
'endsWith'=40
|
||||
'iendsWith'=41
|
||||
'='=42
|
||||
'eq'=43
|
||||
'>'=44
|
||||
'gt'=45
|
||||
'>='=46
|
||||
'ge'=47
|
||||
'gte'=48
|
||||
'<'=49
|
||||
'lt'=50
|
||||
'<='=51
|
||||
'le'=52
|
||||
'lte'=53
|
||||
'<>'=54
|
||||
'!='=55
|
||||
'ne'=56
|
||||
'ieq'=57
|
||||
'ine'=58
|
||||
'0'=65
|
||||
'inrange'=25
|
||||
'to'=26
|
||||
'is'=27
|
||||
'null'=28
|
||||
'isNull'=29
|
||||
'isNotNull'=30
|
||||
'notNull'=31
|
||||
'empty'=32
|
||||
'isEmpty'=33
|
||||
'isNotEmpty'=34
|
||||
'notEmpty'=35
|
||||
'like'=36
|
||||
'ilike'=37
|
||||
'contains'=38
|
||||
'icontains'=39
|
||||
'startsWith'=40
|
||||
'istartsWith'=41
|
||||
'endsWith'=42
|
||||
'iendsWith'=43
|
||||
'='=44
|
||||
'eq'=45
|
||||
'>'=46
|
||||
'gt'=47
|
||||
'>='=48
|
||||
'ge'=49
|
||||
'gte'=50
|
||||
'<'=51
|
||||
'lt'=52
|
||||
'<='=53
|
||||
'le'=54
|
||||
'lte'=55
|
||||
'<>'=56
|
||||
'!='=57
|
||||
'ne'=58
|
||||
'ieq'=59
|
||||
'ine'=60
|
||||
'0'=69
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -267,8 +267,8 @@ public final class BatchControl {
|
||||
if (transaction.isLogSummary()) {
|
||||
transaction.logSummary("BatchControl flush " + Arrays.toString(bsArray));
|
||||
}
|
||||
for (BatchedBeanHolder aBsArray : bsArray) {
|
||||
aBsArray.executeNow();
|
||||
for (BatchedBeanHolder beanHolder : bsArray) {
|
||||
beanHolder.executeNow();
|
||||
}
|
||||
|
||||
if (resetTop) {
|
||||
@@ -327,14 +327,16 @@ public final class BatchControl {
|
||||
return maxDepth + 1;
|
||||
}
|
||||
|
||||
int parentMaxDepth = -1;
|
||||
|
||||
for (BeanPropertyAssocOne<?> parent : imported) {
|
||||
BatchedBeanHolder parentBatch = beanHoldMap.get(parent.getTargetDescriptor().rootName());
|
||||
if (parentBatch != null) {
|
||||
// deeper that the parent
|
||||
return parentBatch.getOrder() + 1;
|
||||
parentMaxDepth = Math.max(parentMaxDepth, parentBatch.getOrder() + 1);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return parentMaxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -446,6 +446,10 @@ public final class DefaultPersister implements Persister {
|
||||
public void insert(EntityBean bean, Transaction t) {
|
||||
|
||||
PersistRequestBean<?> req = createRequest(bean, t, PersistRequest.Type.INSERT);
|
||||
if (req.isReference()) {
|
||||
// skip insert on reference bean
|
||||
return;
|
||||
}
|
||||
try {
|
||||
req.initTransIfRequiredWithBatchCascade();
|
||||
insert(req);
|
||||
|
||||
@@ -24,6 +24,8 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DmlHandler.class);
|
||||
|
||||
private static final int[] GENERATED_KEY_COLUMNS = new int[]{1};
|
||||
private static final int BATCHED_FIRST = 1;
|
||||
private static final int BATCHED = 2;
|
||||
|
||||
/**
|
||||
* The originating request.
|
||||
@@ -49,6 +51,8 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
|
||||
protected String sql;
|
||||
|
||||
private short batchedStatus;
|
||||
|
||||
protected DmlHandler(PersistRequestBean<?> persistRequest, boolean emptyStringToNull) {
|
||||
this.now = System.currentTimeMillis();
|
||||
this.persistRequest = persistRequest;
|
||||
@@ -150,8 +154,20 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
*/
|
||||
protected void logSql(String sql) {
|
||||
if (logLevelSql) {
|
||||
sql = Str.add(sql, "; --bind(", bindLog.toString(), ")");
|
||||
transaction.logSql(sql);
|
||||
switch (batchedStatus) {
|
||||
case BATCHED_FIRST: {
|
||||
transaction.logSql(sql);
|
||||
transaction.logSql(Str.add(" -- bind(", bindLog.toString(), ")"));
|
||||
return;
|
||||
}
|
||||
case BATCHED: {
|
||||
transaction.logSql(Str.add(" -- bind(", bindLog.toString(), ")"));
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
transaction.logSql(Str.add(sql, "; -- bind(", bindLog.toString(), ")"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,9 +266,11 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
|
||||
BatchedPstmtHolder batch = t.getBatchControl().getPstmtHolder();
|
||||
batchedPstmt = batch.getBatchedPstmt(sql, request);
|
||||
if (batchedPstmt != null) {
|
||||
batchedStatus = BATCHED;
|
||||
return batchedPstmt.getStatement();
|
||||
}
|
||||
|
||||
batchedStatus = BATCHED_FIRST;
|
||||
PreparedStatement stmt = getPstmt(t, sql, genKeys);
|
||||
|
||||
batchedPstmt = new BatchedPstmt(stmt, genKeys, sql, t);
|
||||
|
||||
@@ -18,7 +18,6 @@ import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.autotune.ProfilingListener;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanCollectionHelp;
|
||||
import io.ebeaninternal.server.deploy.BeanCollectionHelpFactory;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -236,7 +235,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
this.collection = (help != null ? help.createEmptyNoParent() : null);
|
||||
}
|
||||
|
||||
private BeanCollectionHelp<T> createHelp(OrmQueryRequest<T> request) {
|
||||
private CQueryCollectionAdd<T> createHelp(OrmQueryRequest<T> request) {
|
||||
if (request.isFindById()) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
@@ -43,8 +43,11 @@ import java.util.List;
|
||||
*/
|
||||
class CQueryBuilder {
|
||||
|
||||
protected final String tableAliasPlaceHolder;
|
||||
protected final String columnAliasPrefix;
|
||||
private static final String DELETE = "Delete";
|
||||
private static final String UPDATE = "Update";
|
||||
|
||||
final String tableAliasPlaceHolder;
|
||||
final String columnAliasPrefix;
|
||||
|
||||
private final SqlLimiter sqlLimiter;
|
||||
|
||||
@@ -98,8 +101,9 @@ class CQueryBuilder {
|
||||
/**
|
||||
* Build the delete query.
|
||||
*/
|
||||
<T> CQueryUpdate buildUpdateQuery(String type, OrmQueryRequest<T> request) {
|
||||
<T> CQueryUpdate buildUpdateQuery(boolean deleteRequest, OrmQueryRequest<T> request) {
|
||||
|
||||
String type = (deleteRequest) ? DELETE : UPDATE;
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
String rootTableAlias = query.getAlias();
|
||||
query.setDelete();
|
||||
@@ -117,7 +121,7 @@ class CQueryBuilder {
|
||||
SqlTree sqlTree = createSqlTree(request, predicates);
|
||||
|
||||
String sql;
|
||||
if (type.equals("Delete")) {
|
||||
if (deleteRequest) {
|
||||
sql = buildDeleteSql(request, rootTableAlias, predicates, sqlTree);
|
||||
} else {
|
||||
sql = buildUpdateSql(request, rootTableAlias, predicates, sqlTree);
|
||||
|
||||
@@ -68,12 +68,12 @@ public class CQueryEngine {
|
||||
}
|
||||
|
||||
public <T> int delete(OrmQueryRequest<T> request) {
|
||||
CQueryUpdate query = queryBuilder.buildUpdateQuery("Delete", request);
|
||||
CQueryUpdate query = queryBuilder.buildUpdateQuery(true, request);
|
||||
return executeUpdate(request, query);
|
||||
}
|
||||
|
||||
public <T> int update(OrmQueryRequest<T> request) {
|
||||
CQueryUpdate query = queryBuilder.buildUpdateQuery("Update", request);
|
||||
CQueryUpdate query = queryBuilder.buildUpdateQuery(false, request);
|
||||
return executeUpdate(request, query);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ public class NativeSqlQueryPlanKey implements CQueryPlanKey {
|
||||
return getPartialKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey withDeleteByIds() {
|
||||
throw new IllegalStateException("Not allowed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as a partial key. For rawSql hash the sql is part of the key and as such
|
||||
* needs to be included in order to have a complete key. Typically the MD5 of the sql
|
||||
|
||||
@@ -24,6 +24,11 @@ class RawSqlQueryPlanKey implements CQueryPlanKey {
|
||||
return getPartialKey() + ":r";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey withDeleteByIds() {
|
||||
throw new IllegalStateException("Not allowed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as a partial key. For rawSql hash the sql is part of the key and as such
|
||||
* needs to be included in order to have a complete key. Typically the MD5 of the sql
|
||||
|
||||
@@ -120,7 +120,7 @@ public interface STreeType {
|
||||
/**
|
||||
* Find and return property allowing for dynamic formula properties.
|
||||
*/
|
||||
STreeProperty findPropertyWithDynamic(String baseName);
|
||||
STreeProperty findPropertyWithDynamic(String baseName, String path);
|
||||
|
||||
/**
|
||||
* Return an extra join if the property path requires it.
|
||||
|
||||
@@ -273,7 +273,10 @@ public final class SqlTreeBuilder {
|
||||
OrmQueryProperties queryProps = queryDetail.getChunk(prefix, false);
|
||||
SqlTreeProperties props = getBaseSelect(desc, queryProps);
|
||||
|
||||
if (prefix == null && !rawSql) {
|
||||
if (prefix != null) {
|
||||
// check for aggregation on a fetch
|
||||
props.checkAggregation();
|
||||
} else if (!rawSql) {
|
||||
if (props.requireSqlDistinct(manyWhereJoins)) {
|
||||
sqlDistinct = true;
|
||||
}
|
||||
@@ -417,10 +420,10 @@ public final class SqlTreeBuilder {
|
||||
|
||||
// make sure we only included the base/embedded bean once
|
||||
if (!selectProps.containsProperty(baseName)) {
|
||||
STreeProperty p = desc.findPropertyWithDynamic(baseName);
|
||||
STreeProperty p = desc.findPropertyWithDynamic(baseName, null);
|
||||
if (p == null) {
|
||||
// maybe dynamic formula with schema prefix
|
||||
p = desc.findPropertyWithDynamic(propName);
|
||||
p = desc.findPropertyWithDynamic(propName, null);
|
||||
if (p != null) {
|
||||
selectProps.add(p);
|
||||
} else {
|
||||
@@ -437,7 +440,7 @@ public final class SqlTreeBuilder {
|
||||
} else {
|
||||
// find the property including searching the
|
||||
// sub class hierarchy if required
|
||||
STreeProperty p = desc.findPropertyWithDynamic(propName);
|
||||
STreeProperty p = desc.findPropertyWithDynamic(propName, queryProps.getPath());
|
||||
if (p == null) {
|
||||
logger.error("property [" + propName + "] not found on " + desc + " for query - excluding it.");
|
||||
p = desc.findProperty("id");
|
||||
|
||||
@@ -378,7 +378,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
if (!readId || temporalVersions) {
|
||||
// a bean with no Id (never found in context)
|
||||
if (lazyLoadParentId != null && desc.isElementType()) {
|
||||
if (lazyLoadParentId != null) {
|
||||
ctx.setLazyLoadedChildBean(localBean, lazyLoadParentId);
|
||||
}
|
||||
return localBean;
|
||||
@@ -422,6 +422,9 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
ctx.pushJoin(prefix);
|
||||
ctx.pushTableAlias(prefix);
|
||||
if (lazyLoadParent != null) {
|
||||
lazyLoadParent.addSelectExported(ctx, prefix);
|
||||
}
|
||||
if (readId) {
|
||||
appendSelectId(ctx, idBinder.getBeanProperty());
|
||||
}
|
||||
@@ -486,7 +489,15 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
@Override
|
||||
public boolean isAggregation() {
|
||||
return aggregation;
|
||||
if (aggregation) {
|
||||
return true;
|
||||
}
|
||||
for (SqlTreeNode child : children) {
|
||||
if (child.isAggregation()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -92,6 +92,13 @@ public class SqlTreeProperties {
|
||||
return aggregation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for aggregation (need for groug by clause).
|
||||
*/
|
||||
public void checkAggregation() {
|
||||
aggregationJoin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property to join for aggregation.
|
||||
*/
|
||||
|
||||
@@ -679,6 +679,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
setSelectId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey setDeleteByIdsPlan() {
|
||||
// re-build plan for cascading via delete by ids
|
||||
queryPlanKey = queryPlanKey.withDeleteByIds();
|
||||
return queryPlanKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the select clause to select the Id property.
|
||||
*/
|
||||
@@ -1062,9 +1069,9 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* Calculate the query hash for either AutoTune query tuning or Query Plan caching.
|
||||
*/
|
||||
CQueryPlanKey createQueryPlanKey() {
|
||||
|
||||
if (isNativeSql()) {
|
||||
queryPlanKey = new NativeSqlQueryPlanKey(type.ordinal() + nativeSql + "-" + firstRow + "-" + maxRows);
|
||||
String bindHash = (bindParams == null) ? "" : bindParams.calcQueryPlanHash();
|
||||
queryPlanKey = new NativeSqlQueryPlanKey(type.ordinal() + nativeSql + "-" + firstRow + "-" + maxRows + "-" + bindHash);
|
||||
} else {
|
||||
queryPlanKey = new OrmQueryPlanKey(planDescription(), maxRows, firstRow, rawSql);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ class OrmQueryPlanKey implements CQueryPlanKey {
|
||||
this.planHash = hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey withDeleteByIds() {
|
||||
return new OrmQueryPlanKey(description + ":deleteByIds", 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPartialKey() {
|
||||
return description;
|
||||
|
||||
@@ -91,7 +91,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,7 +117,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.get(0)).contains("select t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -147,7 +147,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
} else {
|
||||
assertThat(sql.get(0)).contains("select t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
} else {
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.get(0)).contains(
|
||||
"select t0.last_name, count(*) totalCount from contact t0 where t0.last_name is not null group by t0.last_name having count(*) > ?");
|
||||
"select t0.last_name, count(*) totalCount from contact t0 where t0.last_name is not null group by t0.last_name having count(*) > ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -23,10 +23,9 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
|
||||
// assert
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
for (String insertSql : loggedSql) {
|
||||
assertThat(insertSql).contains("insert into e_basicver (");
|
||||
assertThat(insertSql).contains("name, description, other, last_update) values (");
|
||||
}
|
||||
assertThat(loggedSql).hasSize(4);
|
||||
assertThat(loggedSql.get(0)).contains("insert into e_basicver (");
|
||||
assertThat(loggedSql.get(0)).contains("name, description, other, last_update) values (");
|
||||
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
someBean.setName(someBean.getName() + "-mod");
|
||||
@@ -37,20 +36,17 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
Ebean.updateAll(someBeans);
|
||||
|
||||
loggedSql = LoggedSqlCollector.stop();
|
||||
for (String updateSql : loggedSql) {
|
||||
assertThat(updateSql).contains("update e_basicver set name=?, last_update=? where id=? ");
|
||||
}
|
||||
|
||||
assertThat(loggedSql).hasSize(3);
|
||||
assertThat(loggedSql.get(0)).contains("update e_basicver set name=?, last_update=? where id=? ");
|
||||
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.deleteAll(someBeans);
|
||||
|
||||
loggedSql = LoggedSqlCollector.stop();
|
||||
for (String updateSql : loggedSql) {
|
||||
assertThat(updateSql).contains("delete from e_basicver where id=? ");
|
||||
}
|
||||
|
||||
assertThat(loggedSql).hasSize(4);
|
||||
assertThat(loggedSql.get(0)).contains("delete from e_basicver where id=?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -58,8 +54,7 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
Transaction transaction = server.beginTransaction();
|
||||
try {
|
||||
try (Transaction transaction = server.beginTransaction()) {
|
||||
transaction.setBatchMode(true);
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
@@ -86,9 +81,6 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
|
||||
// and we have our SQL from jdbc batch flush
|
||||
assertThat(LoggedSqlCollector.stop()).isNotEmpty();
|
||||
|
||||
} finally {
|
||||
transaction.end();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -121,20 +113,16 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = server.beginTransaction();
|
||||
try {
|
||||
try (Transaction txn = server.beginTransaction()) {
|
||||
server.saveAll(someBeans, txn);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
// assert
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
for (String insertSql : loggedSql) {
|
||||
assertThat(insertSql).contains("insert into e_basicver (");
|
||||
assertThat(insertSql).contains("name, description, other, last_update) values (");
|
||||
}
|
||||
assertThat(loggedSql).hasSize(4);
|
||||
assertThat(loggedSql.get(0)).contains("insert into e_basicver (");
|
||||
assertThat(loggedSql.get(0)).contains("name, description, other, last_update) values (");
|
||||
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
someBean.setName(someBean.getName() + "-mod");
|
||||
@@ -142,33 +130,24 @@ public class EbeanServer_saveAllTest extends BaseTestCase {
|
||||
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
txn = server.beginTransaction();
|
||||
try {
|
||||
|
||||
try (Transaction txn = server.beginTransaction()) {
|
||||
server.updateAll(someBeans, txn);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
loggedSql = LoggedSqlCollector.stop();
|
||||
for (String updateSql : loggedSql) {
|
||||
assertThat(updateSql).contains("update e_basicver set name=?, last_update=? where id=? ");
|
||||
}
|
||||
|
||||
assertThat(loggedSql).hasSize(3);
|
||||
assertThat(loggedSql.get(0)).contains("update e_basicver set name=?, last_update=? where id=? ");
|
||||
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
txn = server.beginTransaction();
|
||||
try {
|
||||
try (Transaction txn = server.beginTransaction()) {
|
||||
server.deleteAll(someBeans, txn);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
loggedSql = LoggedSqlCollector.stop();
|
||||
for (String updateSql : loggedSql) {
|
||||
assertThat(updateSql).contains("delete from e_basicver where id=? ");
|
||||
}
|
||||
|
||||
assertThat(loggedSql).hasSize(4);
|
||||
assertThat(loggedSql.get(0)).contains("delete from e_basicver where id=?");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
|
||||
query.update();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("update o_customer set status=?, updtime=? where status = ? and id > ?");
|
||||
assertThat(query.getGeneratedSql()).contains("update o_customer set status=?, updtime=? where status = ? and id > ?");
|
||||
|
||||
BasicMetricVisitor basic = visitMetricsBasic();
|
||||
List<MetaOrmQueryMetric> ormQueryMetrics = basic.getOrmQueryMetrics();
|
||||
@@ -166,7 +166,7 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
|
||||
query.update();
|
||||
|
||||
assertThat(sqlOf(query)).contains("update o_customer set status=?, updtime=? where id in (select t0.id from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and t1.country_code = ? and t0.id > ? )");
|
||||
assertThat(sqlOf(query)).contains("update o_customer set status=?, updtime=? where id in (select t0.id from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and t1.country_code = ? and t0.id > ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -61,7 +61,7 @@ public class FormulaPropertyPathTest extends BaseTestCase {
|
||||
|
||||
private void assertFormula(String input, String funcName, String expression, String cast, String alias) {
|
||||
|
||||
FormulaPropertyPath propertyPath = new FormulaPropertyPath(customerDesc, input);
|
||||
FormulaPropertyPath propertyPath = new FormulaPropertyPath(customerDesc, input, null);
|
||||
|
||||
assertThat(propertyPath.internalExpression()).isEqualTo(expression);
|
||||
assertThat(propertyPath.outerFunction()).isEqualTo(funcName);
|
||||
|
||||
@@ -8,18 +8,18 @@ import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
|
||||
@Test
|
||||
public void addSql() throws Exception {
|
||||
public void addSql() {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
BetweenExpression exp = new BetweenExpression("startDate", 1, 2);
|
||||
exp.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("startDate between ? and ? ");
|
||||
assertThat(expReq.getSql()).isEqualTo("startDate between ? and ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameInstance() throws Exception {
|
||||
public void copyForPlanKey_isSameInstance() {
|
||||
|
||||
BetweenExpression exp = new BetweenExpression("startDate", 1, 2);
|
||||
SpiExpression other = exp.copyForPlanKey();
|
||||
@@ -28,7 +28,7 @@ public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_match() throws Exception {
|
||||
public void isSameByPlan_when_properties_match() {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 3, 4);
|
||||
@@ -38,7 +38,7 @@ public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_do_not_match() throws Exception {
|
||||
public void isSameByPlan_when_properties_do_not_match() {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("endDate", 1, 2);
|
||||
@@ -48,7 +48,7 @@ public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_do_not_match() throws Exception {
|
||||
public void isSameByBind_when_values_do_not_match() {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 1, 3);
|
||||
@@ -58,7 +58,7 @@ public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_match() throws Exception {
|
||||
public void isSameByBind_when_values_match() {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 1, 2);
|
||||
|
||||
@@ -14,7 +14,7 @@ public class BetweenPropertyExpressionTest extends BaseExpressionTest {
|
||||
public void sqlExpression() {
|
||||
TDSpiExpressionRequest request = new TDSpiExpressionRequest(null);
|
||||
exp("a", "b", 10).addSql(request);
|
||||
assertThat(request.getSql()).isEqualTo(" ? between a and b ");
|
||||
assertThat(request.getSql()).isEqualTo(" ? between a and b");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class InRangeExpressionTest extends BaseExpressionTest {
|
||||
|
||||
@Test
|
||||
public void addSql() {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
InRangeExpression exp = new InRangeExpression("startDate", 1, 2);
|
||||
exp.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("(startDate >= ? and startDate < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameInstance() {
|
||||
|
||||
InRangeExpression exp = new InRangeExpression("startDate", 1, 2);
|
||||
SpiExpression other = exp.copyForPlanKey();
|
||||
|
||||
assertThat(exp).isSameAs(other);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_match() {
|
||||
|
||||
InRangeExpression exp0 = new InRangeExpression("startDate", 1, 2);
|
||||
InRangeExpression exp1 = new InRangeExpression("startDate", 3, 4);
|
||||
|
||||
same(exp0, exp1);
|
||||
same(exp1, exp0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_do_not_match() {
|
||||
|
||||
InRangeExpression exp0 = new InRangeExpression("startDate", 1, 2);
|
||||
InRangeExpression exp1 = new InRangeExpression("endDate", 1, 2);
|
||||
|
||||
different(exp0, exp1);
|
||||
different(exp1, exp0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_do_not_match() {
|
||||
|
||||
InRangeExpression exp0 = new InRangeExpression("startDate", 1, 2);
|
||||
InRangeExpression exp1 = new InRangeExpression("startDate", 1, 3);
|
||||
|
||||
assertThat(exp0.isSameByBind(exp1)).isFalse();
|
||||
assertThat(exp1.isSameByBind(exp0)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_match() {
|
||||
|
||||
InRangeExpression exp0 = new InRangeExpression("startDate", 1, 2);
|
||||
InRangeExpression exp1 = new InRangeExpression("startDate", 1, 2);
|
||||
|
||||
assertThat(exp0.isSameByBind(exp1)).isTrue();
|
||||
assertThat(exp1.isSameByBind(exp0)).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,17 @@ public class LogicExpressionTest extends BaseExpressionTest {
|
||||
return new LogicExpression.Or(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSql() {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
LogicExpression and = and(eq("a", 10), eq("b", 10));
|
||||
and.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("(a = ? and b = ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public class NoopExpressionTest extends BaseExpressionTest {
|
||||
query.findList();
|
||||
String generatedSql = sqlOf(query);
|
||||
|
||||
assertThat(generatedSql).contains("select t0.id from o_customer t0 where t0.name is null and 1=1 and t0.status is not null");
|
||||
assertThat(generatedSql).contains("select t0.id from o_customer t0 where t0.name is null and 1=1 and t0.status is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -2,8 +2,8 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -22,7 +22,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("id", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is not null ");
|
||||
assertThat(expReq.getSql()).isEqualTo("id is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -32,7 +32,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("id", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is null ");
|
||||
assertThat(expReq.getSql()).isEqualTo("id is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -42,7 +42,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("customer", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is not null ");
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -52,7 +52,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("customer", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is null ");
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -64,6 +64,6 @@ public class HanaDbExpressionTest {
|
||||
public void testJson() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.json(request, "jsonproperty", "path", Op.EQ, "val");
|
||||
assertEquals("json_value(jsonproperty, '$.path') = ? ", request.getSql());
|
||||
assertEquals("json_value(jsonproperty, '$.path') = ?", request.getSql());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.OrderDetail;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -80,7 +82,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where name ieq 'Rob'");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?");
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,7 +91,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where name ine 'Rob'");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) !=?");
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) != ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,7 +99,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
|
||||
Query<Customer> query = parse("where 'Rob' ieq name");
|
||||
query.findList();
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) =?");
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -106,7 +108,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where 'Rob' ine name");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) !=?");
|
||||
assertThat(query.getGeneratedSql()).contains("where lower(t0.name) != ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,7 +156,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where name = 'Rob' or (status = 'NEW' and smallnote is null)");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.name = ? or (t0.status = ? and t0.smallnote is null ) )");
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.name = ? or (t0.status = ? and t0.smallnote is null))");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,7 +176,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where (name = 'Rob' or status = 'NEW') and smallnote is null");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where ((t0.name = ? or t0.status = ? ) and t0.smallnote is null )");
|
||||
assertThat(query.getGeneratedSql()).contains("where ((t0.name = ? or t0.status = ?) and t0.smallnote is null)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -193,15 +195,15 @@ public class EqlParserTest extends BaseTestCase {
|
||||
|
||||
Query<Customer> query = parse("where not (name = 'Rob' and status = 'NEW')");
|
||||
query.findList();
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )");
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ?)");
|
||||
|
||||
query = parse("where not ((name = 'Rob' and status = 'NEW'))");
|
||||
query.findList();
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )");
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ?)");
|
||||
|
||||
query = parse("where not (((name = 'Rob') and (status = 'NEW')))");
|
||||
query.findList();
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )");
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -221,14 +223,13 @@ public class EqlParserTest extends BaseTestCase {
|
||||
assertThat(query.getGeneratedSql()).contains("where not (t0.name = ? and t0.status = ? )");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void where_in() {
|
||||
|
||||
Query<Customer> query = parse("where name in ('Rob','Jim')");
|
||||
query.findList();
|
||||
|
||||
platformAssertIn(query.getGeneratedSql(),"where t0.name");
|
||||
platformAssertIn(query.getGeneratedSql(), "where t0.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -239,7 +240,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
query.setParameter("two", "Bar");
|
||||
query.findList();
|
||||
|
||||
platformAssertIn(query.getGeneratedSql(),"where t0.name");
|
||||
platformAssertIn(query.getGeneratedSql(), "where t0.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -250,7 +251,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
query.setParameter("two", "Bar");
|
||||
query.findList();
|
||||
|
||||
platformAssertIn(query.getGeneratedSql(),"where t0.name");
|
||||
platformAssertIn(query.getGeneratedSql(), "where t0.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -261,7 +262,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
query.setParameter("two", "Bar");
|
||||
query.findList();
|
||||
|
||||
platformAssertIn(query.getGeneratedSql(),"where t0.name");
|
||||
platformAssertIn(query.getGeneratedSql(), "where t0.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -271,7 +272,27 @@ public class EqlParserTest extends BaseTestCase {
|
||||
query.setParameter("names", Arrays.asList("Baz", "Maz", "Jim"));
|
||||
query.findList();
|
||||
|
||||
platformAssertIn(query.getGeneratedSql(),"where t0.name");
|
||||
platformAssertIn(query.getGeneratedSql(), "where t0.name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void where_inrange() {
|
||||
|
||||
Query<Customer> query = parse("where name inrange 'As' to 'B'");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.name >= ? and t0.name < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void where_inrange_withNamedParams() {
|
||||
|
||||
Query<Customer> query = parse("where name inrange :one to :two");
|
||||
query.setParameter("one", "a");
|
||||
query.setParameter("two", "b");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.name >= ? and t0.name < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -280,7 +301,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("where name between 'As' and 'B'");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ? ");
|
||||
assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -291,7 +312,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
query.setParameter("two", "b");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ? ");
|
||||
assertThat(query.getGeneratedSql()).contains("where t0.name between ? and ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -313,6 +334,79 @@ public class EqlParserTest extends BaseTestCase {
|
||||
assertThat(query.getGeneratedSql()).contains("where ? between t0.name and t0.smallnote");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetch_basic() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.line_2, t1.city, t1.cretime, t1.updtime, t1.country_code from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetch_basic2() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = parse("select name, status fetch billingAddress");
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id, t0.name, t0.status, t1.id, t1.line_1, t1.line_2, t1.city, t1.cretime, t1.updtime, t1.country_code from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetch_withProperties() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) ");
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query, 12)).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.city from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetchFetchLimit() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) fetch shippingAddress (line1) limit 10");
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query, 12)).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.city, t2.id, t2.line_1 from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id left join o_address t2 on t2.id = t0.shipping_address_id order by t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetchFetchMany() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) fetch contacts");
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query, 12)).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.city, t2.id, t2.first_name, t2.last_name, t2.phone, t2.mobile, t2.email, t2.cretime, t2.updtime, t2.customer_id, t2.group_id from o_customer t0");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void selectFetchFetchManyProperties() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) fetch contacts (email)");
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query, 12)).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.city, t2.id, t2.email from o_customer t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectFetchFetchManyPropertiesLimit() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) fetch contacts (email) limit 10");
|
||||
query.findList();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name, t1.id, t1.line_1, t1.city from o_customer t0 left join o_address");
|
||||
assertThat(sql.get(1)).contains("select t0.customer_id, t0.id, t0.email from contact t0 where (t0.customer_id)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetch_basic() {
|
||||
|
||||
@@ -418,6 +512,58 @@ public class EqlParserTest extends BaseTestCase {
|
||||
Query<Customer> query = parse("select (name)");
|
||||
query.findList();
|
||||
assertThat(sqlOf(query, 1)).contains("select t0.id, t0.name from o_customer t0");
|
||||
|
||||
Query<Customer> query2 = parse("select name");
|
||||
query2.findList();
|
||||
assertThat(sqlOf(query2, 1)).contains("select t0.id, t0.name from o_customer t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_sum() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = parse("select (sum(id))");
|
||||
query.findSingleAttribute();
|
||||
assertThat(sqlOf(query, 1)).contains("select sum(t0.id) from o_customer t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_max() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = parse("select (max(cretime))");
|
||||
query.findSingleAttribute();
|
||||
assertThat(sqlOf(query, 1)).contains("select max(t0.cretime) from o_customer t0");
|
||||
|
||||
Query<Customer> query2 = parse("select max(cretime)");
|
||||
query2.findSingleAttribute();
|
||||
assertThat(sqlOf(query2, 1)).contains("select max(t0.cretime) from o_customer t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_agg() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = parse("select status, max(cretime)");
|
||||
List<Customer> customers = query.findList();
|
||||
|
||||
assertThat(customers).isNotEmpty();
|
||||
assertThat(sqlOf(query, 1)).contains("select t0.status, max(t0.cretime) from o_customer t0 group by t0.status");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_agg_sum() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<OrderDetail> query = Ebean.createQuery(OrderDetail.class, "select sum(orderQty) fetch `order` (id)");
|
||||
List<OrderDetail> details = query.findList();
|
||||
|
||||
assertThat(details).isNotEmpty();
|
||||
assertThat(sqlOf(query, 1)).contains("select sum(t0.order_qty), t1.id from o_order_detail t0 join o_order t1 on t1.id = t0.order_id group by t1.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -5,10 +5,10 @@ import io.ebean.Ebean;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import org.tests.model.basic.OrderAggregate;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.OrderAggregate;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -128,7 +128,7 @@ public class TestOrderTotalAmountReportBean extends BaseTestCase {
|
||||
.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("count(*) as total_items, sum(order_qty*unit_price) as total_amount, max(order_qty*unit_price) as maxAmount from o_order_detail");
|
||||
assertThat(query.getGeneratedSql()).contains("from o_order_detail where order_id > ? group by order_id having count(*) > ? order by sum(order_qty*unit_price) desc");
|
||||
assertThat(query.getGeneratedSql()).contains("from o_order_detail where order_id > ? group by order_id having count(*) > ? order by sum(order_qty*unit_price) desc");
|
||||
assertNotNull(list);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public class TestOrderTotalAmountReportBean extends BaseTestCase {
|
||||
.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount from o_order_detail");
|
||||
assertThat(query.getGeneratedSql()).contains("from o_order_detail where id > ? and order_id is not null group by order_id having sum(order_qty*unit_price) < ? order by sum(order_qty*unit_price) desc");
|
||||
assertThat(query.getGeneratedSql()).contains("from o_order_detail where id > ? and order_id is not null group by order_id having sum(order_qty*unit_price) < ? order by sum(order_qty*unit_price) desc");
|
||||
assertNotNull(list);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Query;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class TestQueryWhereInRange extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void inRange() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query= Ebean.find(Order.class)
|
||||
.where().inRange("orderDate", today.minusDays(7), today)
|
||||
.isNotNull("id")
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
sqlOf(query).contains("(order_date >= ? and order_date < ?)");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -67,9 +67,9 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
|
||||
// we get the 2 master inserts first
|
||||
assertThat(sql.get(0)).contains("insert into t_atable_thatisrelatively");
|
||||
assertThat(sql.get(1)).contains("insert into t_atable_thatisrelatively");
|
||||
assertThat(sql.get(1)).contains("-- bind(");
|
||||
// detail
|
||||
assertThat(sql.get(2)).contains("insert into t_detail_with_other_namexxxyy");
|
||||
assertThat(sql.get(3)).contains("insert into t_detail_with_other_namexxxyy");
|
||||
|
||||
assertThat(((SpiTransaction)transaction).getLabel()).isEqualTo("TestBatchInsertFlush.no_cascade");
|
||||
|
||||
@@ -137,7 +137,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
assertThat(LoggedSqlCollector.current()).isEmpty();
|
||||
Integer id = b1.getId();
|
||||
assertNotNull(id);
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(2);
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(3);
|
||||
|
||||
EBasicVer b3 = new EBasicVer("b3");
|
||||
server.save(b3);
|
||||
@@ -163,7 +163,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
assertThat(LoggedSqlCollector.current()).isEmpty();
|
||||
Integer id = b1.getId();
|
||||
assertNotNull(id);
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(2);
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(3);
|
||||
|
||||
EBasicVer b3 = new EBasicVer("b3");
|
||||
server.save(b3, txn);
|
||||
@@ -229,7 +229,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
server.save(b3, txn);
|
||||
|
||||
txn.commit();
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(3);
|
||||
assertThat(LoggedSqlCollector.current()).hasSize(5);
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.tests.batchinsert;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import org.junit.Test;
|
||||
import org.tests.batchinsert.o2o.MeterAddressData;
|
||||
import org.tests.batchinsert.o2o.MeterContractData;
|
||||
import org.tests.batchinsert.o2o.MeterSpecialNeedsClient;
|
||||
import org.tests.batchinsert.o2o.MeterSpecialNeedsContact;
|
||||
import org.tests.batchinsert.o2o.MeterVersion;
|
||||
|
||||
public class TestBatchInsertOneToOne {
|
||||
private MeterVersion build(){
|
||||
MeterAddressData addressData = new MeterAddressData();
|
||||
addressData.setStreet("street");
|
||||
MeterContractData contractData = new MeterContractData();
|
||||
|
||||
MeterSpecialNeedsClient specialNeedsClient = new MeterSpecialNeedsClient();
|
||||
contractData.setSpecialNeedsClient(specialNeedsClient);
|
||||
|
||||
MeterSpecialNeedsContact contact1 = new MeterSpecialNeedsContact();
|
||||
|
||||
specialNeedsClient.setPrimary(contact1);
|
||||
|
||||
MeterVersion meterVersion = new MeterVersion();
|
||||
meterVersion.setAddressData(addressData);
|
||||
meterVersion.setContractData(contractData);
|
||||
|
||||
return meterVersion;
|
||||
}
|
||||
|
||||
@Transactional(batch = PersistBatch.ALL, batchOnCascade = PersistBatch.ALL, batchSize = 10)
|
||||
@Test
|
||||
public void test() {
|
||||
MeterVersion meterVersion = build();
|
||||
|
||||
Ebean.save(meterVersion);
|
||||
}
|
||||
}
|
||||
@@ -40,12 +40,8 @@ public class TestBatchInsertWithInitialisedCollection extends BaseTestCase {
|
||||
}
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertThat(loggedSql).hasSize(3);
|
||||
|
||||
for (String sql : loggedSql) {
|
||||
assertThat(sql).contains("insert into o_cached_bean (");
|
||||
assertThat(sql).contains("name) values (?");
|
||||
}
|
||||
|
||||
assertThat(loggedSql).hasSize(4);
|
||||
assertThat(loggedSql.get(0)).contains("insert into o_cached_bean (");
|
||||
assertThat(loggedSql.get(0)).contains("name) values (?");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.tests.batchinsert.o2o;
|
||||
|
||||
import io.ebean.annotation.NotNull;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class MeterAddressData {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
@NotNull
|
||||
private String street;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.tests.batchinsert.o2o;
|
||||
|
||||
import io.ebean.annotation.NotNull;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
public class MeterContractData {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
@NotNull
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
private MeterSpecialNeedsClient specialNeedsClient;
|
||||
|
||||
public MeterSpecialNeedsClient getSpecialNeedsClient() {
|
||||
return specialNeedsClient;
|
||||
}
|
||||
|
||||
public void setSpecialNeedsClient(MeterSpecialNeedsClient specialNeedsClient) {
|
||||
this.specialNeedsClient = specialNeedsClient;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.tests.batchinsert.o2o;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
public class MeterSpecialNeedsClient {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
private MeterSpecialNeedsContact primary;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public MeterSpecialNeedsContact getPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
public void setPrimary(MeterSpecialNeedsContact primary) {
|
||||
this.primary = primary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.tests.batchinsert.o2o;
|
||||
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class MeterSpecialNeedsContact {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.tests.batchinsert.o2o;
|
||||
|
||||
import io.ebean.annotation.NotNull;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
public class MeterVersion {
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
//@NotNull
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
private MeterAddressData addressData;
|
||||
|
||||
@NotNull
|
||||
@OneToOne(cascade = CascadeType.ALL)
|
||||
private MeterContractData contractData;
|
||||
|
||||
public MeterAddressData getAddressData() {
|
||||
return addressData;
|
||||
}
|
||||
|
||||
public void setAddressData(MeterAddressData addressData) {
|
||||
this.addressData = addressData;
|
||||
}
|
||||
|
||||
public MeterContractData getContractData() {
|
||||
return contractData;
|
||||
}
|
||||
|
||||
public void setContractData(MeterContractData contractData) {
|
||||
this.contractData = contractData;
|
||||
}
|
||||
}
|
||||
@@ -149,7 +149,7 @@ public class TestSecondaryQueries extends TransactionalTestCase {
|
||||
|
||||
String generatedSql = sqlOf(query, 2);
|
||||
//select t0.id c0, t0.status c1, t0.kcustomer_id c2 from o_order t0 where t0.status = ? ; --bind(NEW)
|
||||
assertEquals("select t0.id, t0.status, t0.kcustomer_id from o_order t0 where t0.status = ? ", generatedSql);
|
||||
assertEquals("select t0.id, t0.status, t0.kcustomer_id from o_order t0 where t0.status = ?", generatedSql);
|
||||
|
||||
|
||||
//List<SpiQuery<?>> secondaryQueries = spiQuery.getLoggedSecondaryQueries();
|
||||
|
||||
@@ -78,7 +78,7 @@ public class TestOrderedList extends BaseTestCase {
|
||||
Ebean.save(fresh);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql).hasSize(7);
|
||||
assertThat(sql.get(0)).contains("update om_ordered_master set name=?, version=?");
|
||||
assertThat(sql.get(1)).contains("update om_ordered_detail set version=?, sort_order=? where id=? and version=?");
|
||||
|
||||
@@ -87,10 +87,10 @@ public class TestOrderedList extends BaseTestCase {
|
||||
Ebean.save(fresh);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql).hasSize(8);
|
||||
assertThat(sql.get(0)).contains("update om_ordered_master set name=?, version=?");
|
||||
assertThat(sql.get(1)).contains("update om_ordered_detail set version=?, sort_order=? where id=? and version=?");
|
||||
assertThat(sql.get(2)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?");
|
||||
assertThat(sql.get(3)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?");
|
||||
|
||||
|
||||
Ebean.delete(fresh);
|
||||
|
||||
+4
-3
@@ -37,8 +37,8 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
Ebean.deleteAll(Ebean.find(User.class).findList());
|
||||
|
||||
// insert 2 User records
|
||||
Ebean.save(new User(1L));
|
||||
Ebean.save(new User(2L));
|
||||
Ebean.save(new User(1L, "one"));
|
||||
Ebean.save(new User(2L, "two"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,8 +99,9 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
public User() {
|
||||
}
|
||||
|
||||
public User(Long id) {
|
||||
public User(Long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
|
||||
@@ -4,16 +4,16 @@ import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.BBookmarkUser;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -126,6 +126,23 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
Ebean.delete(Contact.class, 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryDelete_withTransactionNoCascade() {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
transaction.setPersistCascade(false);
|
||||
|
||||
Ebean.find(Contact.class).where().eq("id", 7001).delete();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.get(0)).contains("delete from contact where id = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithForUpdate() {
|
||||
|
||||
|
||||
@@ -60,20 +60,19 @@ public class TestMergeBasic extends BaseTestCase {
|
||||
|
||||
// persist children ...
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
assertThat(sql.get(4)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
|
||||
assertThat(sql.get(5)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?)");
|
||||
assertThat(sql.get(4)).contains("-- bind(");
|
||||
assertThat(sql.get(5)).contains("-- bind(");
|
||||
assertThat(sql.get(6)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(7)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
}
|
||||
else {
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
assertThat(sql.get(7)).contains("-- bind(");
|
||||
assertThat(sql.get(8)).contains("-- bind(");
|
||||
assertThat(sql.get(9)).contains("-- bind(");
|
||||
|
||||
} else {
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
assertThat(sql.get(4)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(5)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(6)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
|
||||
assertThat(sql.get(7)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
}
|
||||
}
|
||||
@@ -109,23 +108,16 @@ public class TestMergeBasic extends BaseTestCase {
|
||||
|
||||
// persist children ...
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
assertThat(sql.get(4)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
|
||||
assertThat(sql.get(5)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?)");
|
||||
assertThat(sql.get(4)).contains("-- bind(");
|
||||
assertThat(sql.get(5)).contains("-- bind(");
|
||||
assertThat(sql.get(6)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(7)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
}
|
||||
else {
|
||||
assertThat(sql.get(9)).contains("-- bind(");
|
||||
|
||||
} else {
|
||||
assertThat(sql.get(3)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
|
||||
assertThat(sql.get(4)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(5)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
assertThat(sql.get(6)).contains("update uutwo set name=?, notes=?, version=?, master_id=? where id=? and version=?");
|
||||
|
||||
assertThat(sql.get(7)).contains("insert into uutwo (id, name, notes, version, master_id) values (?,?,?,?,?);");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private UUOne buildGraph() {
|
||||
|
||||
@@ -279,11 +279,9 @@ public class TestMergeCustomer extends BaseTestCase {
|
||||
assertThat(sql.get(5)).contains("update mcustomer set name=?, version=?, shipping_address_id=?, billing_address_id=? where id=? and version=?");
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql.get(6)).contains("insert into mcontact");
|
||||
assertThat(sql.get(7)).contains("insert into mcontact");
|
||||
assertThat(sql.get(8)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
assertThat(sql.get(11)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
}
|
||||
else {
|
||||
assertThat(sql.get(7)).contains("-- bind(");
|
||||
assertThat(sql.get(9)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
} else {
|
||||
assertThat(sql.get(6)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
assertThat(sql.get(7)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
assertThat(sql.get(10)).contains("insert into mcontact");
|
||||
@@ -327,14 +325,12 @@ public class TestMergeCustomer extends BaseTestCase {
|
||||
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql.get(8)).contains("insert into mcontact");
|
||||
assertThat(sql.get(9)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
|
||||
assertThat(sql.get(13)).contains("update mcontact_message set title=?, subject=?, notes=?, version=?, contact_id=? where id=? and version=?");
|
||||
}
|
||||
else {
|
||||
assertThat(sql.get(10)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
assertThat(sql.get(15)).contains("update mcontact_message set title=?, subject=?, notes=?, version=?, contact_id=? where id=? and version=?");
|
||||
} else {
|
||||
assertThat(sql.get(8)).contains("update mcontact set email=?, first_name=?, last_name=?, version=?, customer_id=? where id=? and version=?");
|
||||
assertThat(sql.get(9)).contains("update mcontact_message set title=?, subject=?, notes=?, version=?, contact_id=? where id=? and version=?");
|
||||
|
||||
|
||||
assertThat(sql.get(sql.size()-1)).contains("insert into mcontact");
|
||||
}
|
||||
|
||||
|
||||
@@ -4,23 +4,41 @@ import io.ebean.Model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Version;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class DMachine extends Model {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
private long id;
|
||||
|
||||
String name;
|
||||
private String name;
|
||||
|
||||
@ManyToOne
|
||||
private final DOrg organisation;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
private long version;
|
||||
|
||||
public DMachine(String name) {
|
||||
@OneToMany(mappedBy = "machine")
|
||||
private List<DMachineStats> machineStats;
|
||||
|
||||
@OneToMany(mappedBy = "machine")
|
||||
private List<DMachineAuxUseAgg> auxUseAggs;
|
||||
|
||||
public DMachine(DOrg organisation, String name) {
|
||||
this.organisation = organisation;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -37,6 +55,10 @@ public class DMachine extends Model {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public DOrg getOrganisation() {
|
||||
return organisation;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
@@ -44,4 +66,20 @@ public class DMachine extends Model {
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public List<DMachineStats> getMachineStats() {
|
||||
return machineStats;
|
||||
}
|
||||
|
||||
public void setMachineStats(List<DMachineStats> machineStats) {
|
||||
this.machineStats = machineStats;
|
||||
}
|
||||
|
||||
public List<DMachineAuxUseAgg> getAuxUseAggs() {
|
||||
return auxUseAggs;
|
||||
}
|
||||
|
||||
public void setAuxUseAggs(List<DMachineAuxUseAgg> auxUseAggs) {
|
||||
this.auxUseAggs = auxUseAggs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.tests.model.aggregation;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity
|
||||
@Table(name = "d_machine_aux_use")
|
||||
public class DMachineAuxUse extends Model {
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
private DMachine machine;
|
||||
|
||||
private String name;
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
private long useSecs;
|
||||
|
||||
private BigDecimal fuel;
|
||||
|
||||
@Version
|
||||
private long version;
|
||||
|
||||
public DMachineAuxUse(DMachine machine, LocalDate date, String name) {
|
||||
this.machine = machine;
|
||||
this.date = date;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DMachine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
public void setMachine(DMachine machine) {
|
||||
this.machine = machine;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public long getUseSecs() {
|
||||
return useSecs;
|
||||
}
|
||||
|
||||
public void setUseSecs(long useSecs) {
|
||||
this.useSecs = useSecs;
|
||||
}
|
||||
|
||||
public BigDecimal getFuel() {
|
||||
return fuel;
|
||||
}
|
||||
|
||||
public void setFuel(BigDecimal fuel) {
|
||||
this.fuel = fuel;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.tests.model.aggregation;
|
||||
|
||||
import io.ebean.annotation.Sum;
|
||||
import io.ebean.annotation.View;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity
|
||||
@View(name = "d_machine_aux_use")
|
||||
public class DMachineAuxUseAgg {
|
||||
|
||||
@ManyToOne
|
||||
private DMachine machine;
|
||||
|
||||
private String name;
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
@Sum
|
||||
private long useSecs;
|
||||
|
||||
@Sum
|
||||
private BigDecimal fuel;
|
||||
|
||||
public DMachine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
public void setMachine(DMachine machine) {
|
||||
this.machine = machine;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public long getUseSecs() {
|
||||
return useSecs;
|
||||
}
|
||||
|
||||
public void setUseSecs(long useSecs) {
|
||||
this.useSecs = useSecs;
|
||||
}
|
||||
|
||||
public BigDecimal getFuel() {
|
||||
return fuel;
|
||||
}
|
||||
|
||||
public void setFuel(BigDecimal fuel) {
|
||||
this.fuel = fuel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public class DMachineStats {
|
||||
@Id
|
||||
long id;
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(optional = false)
|
||||
DMachine machine;
|
||||
|
||||
LocalDate date;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.tests.model.aggregation;
|
||||
|
||||
import io.ebean.annotation.Aggregation;
|
||||
import io.ebean.annotation.Sum;
|
||||
import io.ebean.annotation.View;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
@@ -17,16 +18,10 @@ public class DMachineStatsAgg {
|
||||
|
||||
LocalDate date;
|
||||
|
||||
/**
|
||||
* Matching with column underscore.
|
||||
*/
|
||||
@Aggregation("sum(totalKms)")
|
||||
@Sum // which is the same as: @Aggregation("sum(totalKms)")
|
||||
long totalKms;
|
||||
|
||||
/**
|
||||
* Matching with no underscore.
|
||||
*/
|
||||
@Aggregation("sum(hours)")
|
||||
@Aggregation("sum(hours)") // which is the same as: @Sum
|
||||
long hours;
|
||||
|
||||
@Aggregation("max(rate)")
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.tests.model.aggregation;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Entity
|
||||
@Table(name = "d_machine_use")
|
||||
public class DMachineUse extends Model {
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
private DMachine machine;
|
||||
|
||||
private LocalDate date;
|
||||
|
||||
private long distanceKms;
|
||||
|
||||
private long timeSecs;
|
||||
|
||||
private BigDecimal fuel;
|
||||
|
||||
@Version
|
||||
private long version;
|
||||
|
||||
public DMachineUse(DMachine machine, LocalDate date) {
|
||||
this.machine = machine;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DMachine getMachine() {
|
||||
return machine;
|
||||
}
|
||||
|
||||
public void setMachine(DMachine machine) {
|
||||
this.machine = machine;
|
||||
}
|
||||
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(LocalDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public long getDistanceKms() {
|
||||
return distanceKms;
|
||||
}
|
||||
|
||||
public void setDistanceKms(long distanceKms) {
|
||||
this.distanceKms = distanceKms;
|
||||
}
|
||||
|
||||
public long getTimeSecs() {
|
||||
return timeSecs;
|
||||
}
|
||||
|
||||
public void setTimeSecs(long timeSecs) {
|
||||
this.timeSecs = timeSecs;
|
||||
}
|
||||
|
||||
public BigDecimal getFuel() {
|
||||
return fuel;
|
||||
}
|
||||
|
||||
public void setFuel(BigDecimal fuel) {
|
||||
this.fuel = fuel;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.tests.model.aggregation;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class DOrg extends Model {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public DOrg(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user