提交 ea889d5a authored 作者: Noel Grandin's avatar Noel Grandin

remove JaQu

this has been unmaintained for a very long time, mostly because there is an active forked project based on this, so people should rather be using that
上级 d4ed1a5d
...@@ -104,9 +104,6 @@ The build system can generate smaller jar files as well. The following targets a ...@@ -104,9 +104,6 @@ The build system can generate smaller jar files as well. The following targets a
</li><li><code>jarSmall</code> </li><li><code>jarSmall</code>
creates the file <code>h2small.jar</code>. creates the file <code>h2small.jar</code>.
This only contains the embedded database. Debug information is disabled. This only contains the embedded database. Debug information is disabled.
</li><li><code>jarJaqu</code>
creates the file <code>h2jaqu.jar</code>.
This only contains the JaQu (Java Query) implementation. All other jar files do not include JaQu.
</li><li><code>javadocImpl</code> creates the Javadocs of the implementation. </li><li><code>javadocImpl</code> creates the Javadocs of the implementation.
</li></ul> </li></ul>
<p> <p>
......
...@@ -94,7 +94,6 @@ translate --> ...@@ -94,7 +94,6 @@ translate -->
<a href="license.html">License</a><br /> <a href="license.html">License</a><br />
<a href="build.html">Build</a><br /> <a href="build.html">Build</a><br />
<a href="links.html">Links</a><br /> <a href="links.html">Links</a><br />
<a href="jaqu.html">JaQu</a><br />
<a href="mvstore.html">MVStore</a><br /> <a href="mvstore.html">MVStore</a><br />
<a href="architecture.html">Architecture</a><br /> <a href="architecture.html">Architecture</a><br />
<br /> <br />
......
差异被折叠。
...@@ -288,7 +288,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -288,7 +288,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Server mode: improve performance for batch updates. </li><li>Server mode: improve performance for batch updates.
</li><li>Applets: support read-only databases in a zip file (accessed as a resource). </li><li>Applets: support read-only databases in a zip file (accessed as a resource).
</li><li>Long running queries / errors / trace system table. </li><li>Long running queries / errors / trace system table.
</li><li>H2 Console should support JaQu directly.
</li><li>Better document FTL_SEARCH, FTL_SEARCH_DATA. </li><li>Better document FTL_SEARCH, FTL_SEARCH_DATA.
</li><li>Sequences: CURRVAL should be session specific. Compatibility with PostgreSQL. </li><li>Sequences: CURRVAL should be session specific. Compatibility with PostgreSQL.
</li><li>Index creation using deterministic functions. </li><li>Index creation using deterministic functions.
...@@ -481,7 +480,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -481,7 +480,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
select * from test a inner join test b on a.id=b.id inner join o on o.id=a.id where b.x=1 select * from test a inner join test b on a.id=b.id inner join o on o.id=a.id where b.x=1
(the optimizer should swap a and b here). (the optimizer should swap a and b here).
See also TestNestedJoins, tag "swapInnerJoinTables". See also TestNestedJoins, tag "swapInnerJoinTables".
</li><li>JaQu should support a DataSource and a way to create a Db object using a Connection (for multi-threaded usage with a connection pool).
</li><li>Move table to a different schema (rename table to a different schema), possibly using ALTER TABLE ... SET SCHEMA ...; </li><li>Move table to a different schema (rename table to a different schema), possibly using ALTER TABLE ... SET SCHEMA ...;
</li><li>nioMapped file system: automatically fall back to regular (non mapped) IO if there is a problem (out of memory exception for example). </li><li>nioMapped file system: automatically fall back to regular (non mapped) IO if there is a problem (out of memory exception for example).
</li><li>Column as parameter of function table. Issue 228. </li><li>Column as parameter of function table. Issue 228.
......
...@@ -84,12 +84,6 @@ import org.h2.test.db.TestUsingIndex; ...@@ -84,12 +84,6 @@ import org.h2.test.db.TestUsingIndex;
import org.h2.test.db.TestView; import org.h2.test.db.TestView;
import org.h2.test.db.TestViewAlterTable; import org.h2.test.db.TestViewAlterTable;
import org.h2.test.db.TestViewDropView; import org.h2.test.db.TestViewDropView;
import org.h2.test.jaqu.AliasMapTest;
import org.h2.test.jaqu.AnnotationsTest;
import org.h2.test.jaqu.ClobTest;
import org.h2.test.jaqu.ModelsTest;
import org.h2.test.jaqu.SamplesTest;
import org.h2.test.jaqu.UpdateTest;
import org.h2.test.jdbc.TestBatchUpdates; import org.h2.test.jdbc.TestBatchUpdates;
import org.h2.test.jdbc.TestCallableStatement; import org.h2.test.jdbc.TestCallableStatement;
import org.h2.test.jdbc.TestCancel; import org.h2.test.jdbc.TestCancel;
...@@ -793,15 +787,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -793,15 +787,6 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestSynonymForTable()); addTest(new TestSynonymForTable());
addTest(new TestColumnNamer()); addTest(new TestColumnNamer());
// jaqu
addTest(new AliasMapTest());
addTest(new AnnotationsTest());
addTest(new ClobTest());
addTest(new ModelsTest());
addTest(new SamplesTest());
addTest(new UpdateTest());
// jdbc // jdbc
addTest(new TestBatchUpdates()); addTest(new TestBatchUpdates());
addTest(new TestCallableStatement()); addTest(new TestCallableStatement());
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import java.util.List;
import org.h2.jaqu.Db;
import org.h2.test.TestBase;
/**
* Tests that columns (p.unitsInStock) are not compared by value with the value
* (9), but by reference (using an identity hash map).
* See http://code.google.com/p/h2database/issues/detail?id=119
*
* @author d moebius at scoop slash gmbh dot de
*/
public class AliasMapTest extends TestBase {
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) throws Exception {
new AliasMapTest().test();
}
@Override
public void test() throws Exception {
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.insertAll(Product.getList());
Product p = new Product();
List<Product> products = db
.from(p)
.where(p.unitsInStock).is(9)
.orderBy(p.productId).select();
assertEquals("[]", products.toString());
db.close();
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.jaqu.Db;
import org.h2.test.TestBase;
import org.h2.util.JdbcUtils;
/**
* Test annotation processing.
*/
public class AnnotationsTest extends TestBase {
/**
* This object represents a database (actually a connection to the
* database).
*/
private Db db;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) throws SQLException {
new AnnotationsTest().test();
}
@Override
public void test() throws SQLException {
db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.insertAll(Product.getList());
db.insertAll(ProductAnnotationOnly.getList());
db.insertAll(ProductMixedAnnotation.getList());
testIndexCreation();
testProductAnnotationOnly();
testProductMixedAnnotation();
testTrimStringAnnotation();
testCreateTableIfRequiredAnnotation();
testColumnInheritanceAnnotation();
db.close();
}
private void testIndexCreation() throws SQLException {
// test indexes are created, and columns are in the right order
DatabaseMetaData meta = db.getConnection().getMetaData();
ResultSet rs = meta.getIndexInfo(null, "PUBLIC",
"ANNOTATED" + "PRODUCT", false, true);
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME"), "PRIMARY_KEY");
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATED" + "PRODUCT_");
assertStartsWith(rs.getString("COLUMN_NAME"), "NAME");
assertTrue(rs.next());
assertStartsWith(rs.getString("INDEX_NAME"), "ANNOTATED" + "PRODUCT_");
assertStartsWith(rs.getString("COLUMN_NAME"), "CAT");
assertFalse(rs.next());
}
private void testProductAnnotationOnly() {
ProductAnnotationOnly p = new ProductAnnotationOnly();
assertEquals(10, db.from(p).selectCount());
// test JQColumn.name="cat"
assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
// test JQTable.annotationsOnly=true
// public String unmappedField is ignored by JaQu
assertEquals(0, db.from(p).where(p.unmappedField).is("unmapped").selectCount());
// test JQColumn.autoIncrement=true
// 10 objects, 10 autoIncremented unique values
assertEquals(10, db.from(p).selectDistinct(p.autoIncrement).size());
// test JQTable.primaryKey=id
try {
db.insertAll(ProductAnnotationOnly.getList());
} catch (RuntimeException r) {
SQLException s = (SQLException) r.getCause();
assertEquals(ErrorCode.DUPLICATE_KEY_1, s.getErrorCode());
}
}
private void testProductMixedAnnotation() {
ProductMixedAnnotation p = new ProductMixedAnnotation();
// test JQColumn.name="cat"
assertEquals(2, db.from(p).where(p.category).is("Beverages").selectCount());
// test JQTable.annotationsOnly=false
// public String mappedField is reflectively mapped by JaQu
assertEquals(10, db.from(p).where(p.mappedField).is("mapped").selectCount());
// test JQColumn.primaryKey=true
try {
db.insertAll(ProductMixedAnnotation.getList());
} catch (RuntimeException r) {
SQLException s = (SQLException) r.getCause();
assertEquals(ErrorCode.DUPLICATE_KEY_1, s.getErrorCode());
}
}
private void testTrimStringAnnotation() {
ProductAnnotationOnly p = new ProductAnnotationOnly();
ProductAnnotationOnly prod = db.from(p).selectFirst();
String oldValue = prod.category;
String newValue = "01234567890123456789";
// 2 chars exceeds field max
prod.category = newValue;
db.update(prod);
ProductAnnotationOnly newProd = db.from(p)
.where(p.productId)
.is(prod.productId)
.selectFirst();
assertEquals(newValue.substring(0, 15), newProd.category);
newProd.category = oldValue;
db.update(newProd);
}
private void testColumnInheritanceAnnotation() {
ProductInheritedAnnotation table = new ProductInheritedAnnotation();
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
List<ProductInheritedAnnotation> inserted = ProductInheritedAnnotation
.getData();
db.insertAll(inserted);
List<ProductInheritedAnnotation> retrieved = db.from(table).select();
for (int j = 0; j < retrieved.size(); j++) {
ProductInheritedAnnotation i = inserted.get(j);
ProductInheritedAnnotation r = retrieved.get(j);
assertEquals(i.category, r.category);
assertEquals(i.mappedField, r.mappedField);
assertEquals(i.unitsInStock, r.unitsInStock);
assertEquals(i.unitPrice, r.unitPrice);
assertEquals(i.name(), r.name());
assertEquals(i.id(), r.id());
}
db.close();
}
private void testCreateTableIfRequiredAnnotation() {
// tests JQTable.createTableIfRequired=false
Db noCreateDb = null;
try {
noCreateDb = Db.open("jdbc:h2:mem:", "sa", "sa");
noCreateDb.insertAll(ProductNoCreateTable.getList());
noCreateDb.close();
} catch (RuntimeException r) {
SQLException s = (SQLException) r.getCause();
assertEquals(ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1, s.getErrorCode());
}
if (noCreateDb != null) {
JdbcUtils.closeSilently(noCreateDb.getConnection());
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import static org.h2.jaqu.Define.primaryKey;
import static org.h2.jaqu.Define.tableName;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Db;
import org.h2.jaqu.Table;
import org.h2.test.TestBase;
/**
* Tests if converting a CLOB to a String works.
*/
public class ClobTest extends TestBase {
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) throws Exception {
new ClobTest().test();
}
@Override
public void test() throws Exception {
String create = "CREATE TABLE CLOB_TEST(ID INT PRIMARY KEY, WORDS {0})";
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.executeUpdate(MessageFormat.format(create, "VARCHAR(255)"));
db.insertAll(StringRecord.getList());
testSimpleUpdate(db, "VARCHAR fail");
db.close();
db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.executeUpdate(MessageFormat.format(create, "TEXT"));
db.insertAll(StringRecord.getList());
testSimpleUpdate(db, "CLOB fail because of single quote artifacts");
db.close();
}
private void testSimpleUpdate(Db db, String failureMsg) {
String newWords = "I changed the words";
StringRecord r = new StringRecord();
StringRecord originalRecord = db.from(r).where(r.id).is(2).selectFirst();
String oldWords = originalRecord.words;
originalRecord.words = newWords;
db.update(originalRecord);
StringRecord r2 = new StringRecord();
StringRecord revisedRecord = db.from(r2).where(r2.id).is(2).selectFirst();
assertEquals(failureMsg, newWords, revisedRecord.words);
// undo update
originalRecord.words = oldWords;
db.update(originalRecord);
}
/**
* A simple class used in this test.
*/
public static class StringRecord implements Table {
public Integer id;
public String words;
public StringRecord() {
// public constructor
}
private StringRecord(int id, String words) {
this.id = id;
this.words = words;
}
@Override
public void define() {
tableName("CLOB_TEST");
primaryKey(id);
}
private static StringRecord create(int id, String words) {
return new StringRecord(id, words);
}
public static List<StringRecord> getList() {
StringRecord[] list = {
create(1, "Once upon a midnight dreary, while I pondered weak and weary,"),
create(2, "Over many a quaint and curious volume of forgotten lore,"),
create(3, "While I nodded, nearly napping, suddenly there came a tapping,"),
create(4, "As of some one gently rapping, rapping at my chamber door."),
create(5, "`'Tis some visitor,' I muttered, `tapping at my chamber door -"),
create(6, "Only this, and nothing more.'") };
return Arrays.asList(list);
}
@Override
public String toString() {
return id + ": " + words;
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import static org.h2.jaqu.Define.primaryKey;
import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.h2.jaqu.Table;
/**
* A table containing all possible data types.
*/
public class ComplexObject implements Table {
public Integer id;
public Long amount;
public String name;
public BigDecimal value;
public Date birthday;
public Time time;
public Timestamp created;
static ComplexObject build(Integer id, boolean isNull) {
ComplexObject obj = new ComplexObject();
obj.id = id;
obj.amount = isNull ? null : Long.valueOf(1);
obj.name = isNull ? null : "hello";
obj.value = isNull ? null : new BigDecimal("1");
obj.birthday = isNull ? null : java.sql.Date.valueOf("2001-01-01");
obj.time = isNull ? null : Time.valueOf("10:20:30");
obj.created = isNull ? null : Timestamp.valueOf("2002-02-02 02:02:02");
return obj;
}
@Override
public void define() {
primaryKey(id);
}
public static List<ComplexObject> getList() {
return Arrays.asList(new ComplexObject[] { build(0, true), build(1, false) });
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import java.util.Arrays;
import java.util.List;
/**
* A table containing customer data.
*/
public class Customer {
public String customerId;
public String region;
public Customer() {
// public constructor
}
public Customer(String customerId, String region) {
this.customerId = customerId;
this.region = region;
}
@Override
public String toString() {
return customerId;
}
public static List<Customer> getList() {
Customer[] list = {
new Customer("ALFKI", "WA"),
new Customer("ANATR", "WA"),
new Customer("ANTON", "CA") };
return Arrays.asList(list);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import org.h2.jaqu.Db;
import org.h2.jaqu.DbInspector;
import org.h2.jaqu.DbUpgrader;
import org.h2.jaqu.DbVersion;
import org.h2.jaqu.Table.JQDatabase;
import org.h2.jaqu.ValidationRemark;
import org.h2.test.TestBase;
import org.h2.test.jaqu.SupportedTypes.SupportedTypes2;
/**
* Test that the mapping between classes and tables is done correctly.
*/
public class ModelsTest extends TestBase {
/**
* This object represents a database (actually a connection to the
* database).
*/
private Db db;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) throws Exception {
ModelsTest test = new ModelsTest();
test.init();
test.config.traceTest = true;
test.test();
}
@Override
public void test() {
// @TODO Turkey has weird uppercasing rules
if (Locale.getDefault().getCountry().equals("TR")) {
return;
}
db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.insertAll(Product.getList());
db.insertAll(ProductAnnotationOnly.getList());
db.insertAll(ProductMixedAnnotation.getList());
testValidateModels();
testSupportedTypes();
testModelGeneration();
testDatabaseUpgrade();
testTableUpgrade();
db.close();
}
private void testValidateModels() {
DbInspector inspector = new DbInspector(db);
validateModel(inspector, new Product());
validateModel(inspector, new ProductAnnotationOnly());
validateModel(inspector, new ProductMixedAnnotation());
}
private void validateModel(DbInspector inspector, Object o) {
List<ValidationRemark> remarks = inspector.validateModel(o, false);
if (config.traceTest && remarks.size() > 0) {
trace("Validation remarks for " + o.getClass().getName());
for (ValidationRemark remark : remarks) {
trace(remark.toString());
}
trace("");
}
for (ValidationRemark remark : remarks) {
assertFalse(remark.toString(), remark.isError());
}
}
private void testSupportedTypes() {
List<SupportedTypes> original = SupportedTypes.createList();
db.insertAll(original);
List<SupportedTypes> retrieved = db.from(SupportedTypes.SAMPLE).select();
assertEquals(original.size(), retrieved.size());
for (int i = 0; i < original.size(); i++) {
SupportedTypes o = original.get(i);
SupportedTypes r = retrieved.get(i);
if (!o.equivalentTo(r)) {
assertTrue(o.equivalentTo(r));
}
}
}
private void testModelGeneration() {
DbInspector inspector = new DbInspector(db);
List<String> models = inspector.generateModel(null,
"SupportedTypes",
"org.h2.test.jaqu", true, true);
assertEquals(1, models.size());
// a poor test, but a start
assertEquals(1364, models.get(0).length());
}
private void testDatabaseUpgrade() {
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
// insert a database version record
db.insert(new DbVersion(1));
TestDbUpgrader dbUpgrader = new TestDbUpgrader();
db.setDbUpgrader(dbUpgrader);
List<SupportedTypes> original = SupportedTypes.createList();
db.insertAll(original);
assertEquals(1, dbUpgrader.oldVersion.get());
assertEquals(2, dbUpgrader.newVersion.get());
db.close();
}
private void testTableUpgrade() {
Db db = Db.open("jdbc:h2:mem:", "sa", "sa");
// insert first, this will create version record automatically
List<SupportedTypes> original = SupportedTypes.createList();
db.insertAll(original);
// reset the dbUpgrader (clears the update check cache)
TestDbUpgrader dbUpgrader = new TestDbUpgrader();
db.setDbUpgrader(dbUpgrader);
SupportedTypes2 s2 = new SupportedTypes2();
List<SupportedTypes2> types = db.from(s2).select();
assertEquals(10, types.size());
assertEquals(1, dbUpgrader.oldVersion.get());
assertEquals(2, dbUpgrader.newVersion.get());
db.close();
}
/**
* A sample database upgrader class.
*/
@JQDatabase(version = 2)
class TestDbUpgrader implements DbUpgrader {
final AtomicInteger oldVersion = new AtomicInteger(0);
final AtomicInteger newVersion = new AtomicInteger(0);
@Override
public boolean upgradeTable(Db db, String schema, String table,
int fromVersion, int toVersion) {
// just claims success on upgrade request
oldVersion.set(fromVersion);
newVersion.set(toVersion);
return true;
}
@Override
public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
// just claims success on upgrade request
oldVersion.set(fromVersion);
newVersion.set(toVersion);
return true;
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import static org.h2.jaqu.Define.primaryKey;
import static org.h2.jaqu.Define.tableName;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.h2.jaqu.Table;
/**
* A table containing order data.
*/
public class Order implements Table {
public String customerId;
public Integer orderId;
public Date orderDate;
public BigDecimal total;
public Order(String customerId, Integer orderId,
String total, String orderDate) {
this.customerId = customerId;
this.orderId = orderId;
this.total = new BigDecimal(total);
this.orderDate = java.sql.Date.valueOf(orderDate);
}
public Order() {
// public constructor
}
@Override
public void define() {
tableName("Orders");
primaryKey(customerId, orderId);
}
public static List<Order> getList() {
Order[] list = {
new Order("ALFKI", 10702, "330.00", "2007-01-02"),
new Order("ALFKI", 10952, "471.20", "2007-02-03"),
new Order("ANATR", 10308, "88.80", "2007-01-03"),
new Order("ANATR", 10625, "479.75", "2007-03-03"),
new Order("ANATR", 10759, "320.00", "2007-04-01"),
new Order("ANTON", 10365, "403.20", "2007-02-13"),
new Order("ANTON", 10682, "375.50", "2007-03-13"),
new Order("ANTON", 10355, "480.00", "2007-04-11") };
return Arrays.asList(list);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import static org.h2.jaqu.Define.index;
import static org.h2.jaqu.Define.maxLength;
import static org.h2.jaqu.Define.primaryKey;
import static org.h2.jaqu.Define.tableName;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Table;
/**
* A table containing product data.
*/
public class Product implements Table {
public Integer productId;
public String productName;
public String category;
public Double unitPrice;
public Integer unitsInStock;
public Product() {
// public constructor
}
private Product(int productId, String productName,
String category, double unitPrice, int unitsInStock) {
this.productId = productId;
this.productName = productName;
this.category = category;
this.unitPrice = unitPrice;
this.unitsInStock = unitsInStock;
}
@Override
public void define() {
tableName("Product");
primaryKey(productId);
maxLength(category, 255);
index(productName, category);
}
private static Product create(int productId, String productName,
String category, double unitPrice, int unitsInStock) {
return new Product(productId, productName, category,
unitPrice, unitsInStock);
}
public static List<Product> getList() {
Product[] list = {
create(1, "Chai", "Beverages", 18, 39),
create(2, "Chang", "Beverages", 19.0, 17),
create(3, "Aniseed Syrup", "Condiments", 10.0, 13),
create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53),
create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0),
create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120),
create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15),
create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6),
create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29),
create(10, "Ikura", "Seafood", 31.0, 31),
};
return Arrays.asList(list);
}
@Override
public String toString() {
return productName + ": " + unitsInStock;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Table.JQColumn;
import org.h2.jaqu.Table.JQIndex;
import org.h2.jaqu.Table.JQTable;
/**
* A table containing product data.
*/
@JQTable(name = "AnnotatedProduct", primaryKey = "id")
@JQIndex(standard = "name, cat")
public class ProductAnnotationOnly {
@JQColumn(autoIncrement = true)
public Integer autoIncrement;
public String unmappedField;
@JQColumn(name = "id")
Integer productId;
@JQColumn(name = "cat", maxLength = 15, trimString = true)
String category;
@JQColumn(name = "name")
private String productName;
@JQColumn
private Double unitPrice;
@JQColumn
private Integer unitsInStock;
public ProductAnnotationOnly() {
// public constructor
}
private ProductAnnotationOnly(int productId, String productName,
String category, double unitPrice, int unitsInStock,
String unmappedField) {
this.productId = productId;
this.productName = productName;
this.category = category;
this.unitPrice = unitPrice;
this.unitsInStock = unitsInStock;
this.unmappedField = unmappedField;
}
private static ProductAnnotationOnly create(int productId,
String productName, String category, double unitPrice,
int unitsInStock, String unmappedField) {
return new ProductAnnotationOnly(productId, productName, category,
unitPrice, unitsInStock, unmappedField);
}
public static List<ProductAnnotationOnly> getList() {
String unmappedField = "unmapped";
ProductAnnotationOnly[] list = {
create(1, "Chai", "Beverages", 18, 39,
unmappedField),
create(2, "Chang", "Beverages", 19.0, 17,
unmappedField),
create(3, "Aniseed Syrup", "Condiments", 10.0, 13,
unmappedField),
create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53,
unmappedField),
create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0,
unmappedField),
create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120,
unmappedField),
create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15,
unmappedField),
create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6,
unmappedField),
create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29,
unmappedField),
create(10, "Ikura", "Seafood", 31.0, 31,
unmappedField), };
return Arrays.asList(list);
}
@Override
public String toString() {
return productName + ": " + unitsInStock;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Table.JQTable;
/**
* This class inherits all its fields from a parent class which has annotated
* columns. The JQTable annotation of the parent class is ignored and only
* the JQTable annotation of this class matters.
* However, this table inherits JQColumns from its super class.
*/
@JQTable(inheritColumns = true, annotationsOnly = false)
public class ProductInheritedAnnotation extends ProductMixedAnnotation {
public ProductInheritedAnnotation() {
// public constructor
}
private ProductInheritedAnnotation(int productId, String productName,
String category, double unitPrice, int unitsInStock,
String mappedField) {
super(productId, productName, category, unitPrice, unitsInStock,
mappedField);
}
private static ProductInheritedAnnotation create(int productId,
String productName, String category, double unitPrice,
int unitsInStock, String mappedField) {
return new ProductInheritedAnnotation(productId, productName, category,
unitPrice, unitsInStock, mappedField);
}
public static List<ProductInheritedAnnotation> getData() {
String mappedField = "mapped";
ProductInheritedAnnotation[] list = {
create(1, "Chai", "Beverages", 18, 39, mappedField),
create(2, "Chang", "Beverages", 19.0, 17, mappedField),
create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
create(10, "Ikura", "Seafood", 31.0, 31, mappedField), };
return Arrays.asList(list);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Table.JQColumn;
import org.h2.jaqu.Table.JQIndex;
import org.h2.jaqu.Table.JQTable;
/**
* A table containing product data.
*/
@JQTable(annotationsOnly = false)
@JQIndex(standard = "name, cat")
public class ProductMixedAnnotation {
public Double unitPrice;
public Integer unitsInStock;
public String mappedField;
@JQColumn(name = "cat", maxLength = 255)
String category;
@JQColumn(name = "id", primaryKey = true)
private Integer productId;
@JQColumn(name = "name")
private String productName;
public ProductMixedAnnotation() {
// public constructor
}
protected ProductMixedAnnotation(int productId, String productName,
String category, double unitPrice, int unitsInStock,
String mappedField) {
this.productId = productId;
this.productName = productName;
this.category = category;
this.unitPrice = unitPrice;
this.unitsInStock = unitsInStock;
this.mappedField = mappedField;
}
private static ProductMixedAnnotation create(int productId,
String productName, String category, double unitPrice,
int unitsInStock, String mappedField) {
return new ProductMixedAnnotation(productId, productName, category,
unitPrice, unitsInStock, mappedField);
}
public static List<ProductMixedAnnotation> getList() {
String mappedField = "mapped";
ProductMixedAnnotation[] list = {
create(1, "Chai", "Beverages", 18, 39, mappedField),
create(2, "Chang", "Beverages", 19.0, 17, mappedField),
create(3, "Aniseed Syrup", "Condiments", 10.0, 13, mappedField),
create(4, "Chef Anton's Cajun Seasoning", "Condiments", 22.0, 53, mappedField),
create(5, "Chef Anton's Gumbo Mix", "Condiments", 21.3500, 0, mappedField),
create(6, "Grandma's Boysenberry Spread", "Condiments", 25.0, 120, mappedField),
create(7, "Uncle Bob's Organic Dried Pears", "Produce", 30.0, 15, mappedField),
create(8, "Northwoods Cranberry Sauce", "Condiments", 40.0, 6, mappedField),
create(9, "Mishi Kobe Niku", "Meat/Poultry", 97.0, 29, mappedField),
create(10, "Ikura", "Seafood", 31.0, 31, mappedField), };
return Arrays.asList(list);
}
@Override
public String toString() {
return productName + ": " + unitsInStock;
}
public int id() {
return productId;
}
public String name() {
return productName;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.util.Arrays;
import java.util.List;
import org.h2.jaqu.Table.JQColumn;
import org.h2.jaqu.Table.JQTable;
/**
* A table containing product data.
*/
@JQTable(createIfRequired = false)
public class ProductNoCreateTable {
@JQColumn(name = "id")
private Integer productId;
@JQColumn(name = "name")
private String productName;
public ProductNoCreateTable() {
// public constructor
}
private ProductNoCreateTable(int productId, String productName) {
this.productId = productId;
this.productName = productName;
}
private static ProductNoCreateTable create(int productId, String productName) {
return new ProductNoCreateTable(productId, productName);
}
public static List<ProductNoCreateTable> getList() {
ProductNoCreateTable[] list = { create(1, "Chai"), create(2, "Chang") };
return Arrays.asList(list);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.test.jaqu;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.h2.jaqu.Table.JQColumn;
import org.h2.jaqu.Table.JQTable;
/**
* A data class that contains a column for each data type.
*/
@JQTable(strictTypeMapping = true, version = 1)
public class SupportedTypes {
static final SupportedTypes SAMPLE = new SupportedTypes();
@JQColumn(primaryKey = true, autoIncrement = true)
public Integer id;
@JQColumn
private Boolean myBool = false;
@JQColumn
private Byte myByte = 2;
@JQColumn
private Short myShort;
@JQColumn
private Integer myInteger;
@JQColumn
private Long myLong;
@JQColumn
private Float myFloat = 1.0f;
@JQColumn
private Double myDouble;
@JQColumn
private BigDecimal myBigDecimal;
@JQColumn
private String myString;
@JQColumn
private java.util.Date myUtilDate;
@JQColumn
private java.sql.Date mySqlDate;
@JQColumn
private java.sql.Time mySqlTime;
@JQColumn
private java.sql.Timestamp mySqlTimestamp;
static List<SupportedTypes> createList() {
List<SupportedTypes> list = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
list.add(randomValue());
}
return list;
}
static SupportedTypes randomValue() {
Random rand = new Random();
SupportedTypes s = new SupportedTypes();
s.myBool = rand.nextBoolean();
s.myByte = (byte) rand.nextInt(Byte.MAX_VALUE);
s.myShort = (short) rand.nextInt(Short.MAX_VALUE);
s.myInteger = rand.nextInt();
s.myLong = rand.nextLong();
s.myFloat = rand.nextFloat();
s.myDouble = rand.nextDouble();
s.myBigDecimal = new BigDecimal(rand.nextDouble());
s.myString = Long.toHexString(rand.nextLong());
s.myUtilDate = new java.util.Date(rand.nextLong());
s.mySqlDate = new java.sql.Date(rand.nextLong());
s.mySqlTime = new java.sql.Time(rand.nextLong() / 1_000 * 1_000);
s.mySqlTimestamp = new java.sql.Timestamp(rand.nextLong());
return s;
}
public boolean equivalentTo(SupportedTypes s) {
boolean same = true;
same &= myBool.equals(s.myBool);
same &= myByte.equals(s.myByte);
same &= myShort.equals(s.myShort);
same &= myInteger.equals(s.myInteger);
same &= myLong.equals(s.myLong);
same &= myFloat.equals(s.myFloat);
same &= myDouble.equals(s.myDouble);
same &= myBigDecimal.equals(s.myBigDecimal);
Timestamp a = new Timestamp(myUtilDate.getTime());
same &= a.toString().equals(s.myUtilDate.toString());
same &= mySqlTimestamp.toString().equals(s.mySqlTimestamp.toString());
same &= mySqlDate.toString().equals(s.mySqlDate.toString());
same &= mySqlTime.toString().equals(s.mySqlTime.toString());
same &= myString.equals(s.myString);
same &= true;
return same;
}
/**
* This class demonstrates the table upgrade.
*/
@JQTable(name = "SupportedTypes", version = 2,
inheritColumns = true, strictTypeMapping = true)
public static class SupportedTypes2 extends SupportedTypes {
public SupportedTypes2() {
// nothing to do
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.jaqu;
import static java.sql.Date.valueOf;
import org.h2.jaqu.Db;
import org.h2.test.TestBase;
/**
* Tests the Db.update() function.
*
* @author dmoebius at scoop slash gmbh dot de
*/
public class UpdateTest extends TestBase {
private Db db;
/**
* This method is called when executing this application from the command
* line.
*
* @param args the command line parameters
*/
public static void main(String... args) throws Exception {
new UpdateTest().test();
}
@Override
public void test() throws Exception {
db = Db.open("jdbc:h2:mem:", "sa", "sa");
db.insertAll(Product.getList());
db.insertAll(Customer.getList());
db.insertAll(Order.getList());
testSimpleUpdate();
testSimpleUpdateWithCombinedPrimaryKey();
testSimpleMerge();
testSimpleMergeWithCombinedPrimaryKey();
testSetColumns();
db.close();
}
private void testSimpleUpdate() {
Product p = new Product();
Product pChang = db.from(p).where(p.productName).is("Chang")
.selectFirst();
// update unitPrice from 19.0 to 19.5
pChang.unitPrice = 19.5;
// update unitsInStock from 17 to 16
pChang.unitsInStock = 16;
db.update(pChang);
Product p2 = new Product();
Product pChang2 = db.from(p2).where(p2.productName).is("Chang")
.selectFirst();
assertEquals((Double) 19.5, pChang2.unitPrice);
assertEquals(16, pChang2.unitsInStock.intValue());
// undo update
pChang.unitPrice = 19.0;
pChang.unitsInStock = 17;
db.update(pChang);
}
private void testSimpleUpdateWithCombinedPrimaryKey() {
Order o = new Order();
Order ourOrder = db.from(o).where(o.orderDate)
.is(valueOf("2007-01-02")).selectFirst();
ourOrder.orderDate = valueOf("2007-01-03");
db.update(ourOrder);
Order ourUpdatedOrder = db.from(o).where(o.orderDate)
.is(valueOf("2007-01-03")).selectFirst();
assertNotNull("updated order not found", ourUpdatedOrder);
// undo update
ourOrder.orderDate = valueOf("2007-01-02");
db.update(ourOrder);
}
private void testSimpleMerge() {
Product p = new Product();
Product pChang = db.from(p).where(p.productName).is("Chang")
.selectFirst();
// update unitPrice from 19.0 to 19.5
pChang.unitPrice = 19.5;
// update unitsInStock from 17 to 16
pChang.unitsInStock = 16;
db.merge(pChang);
Product p2 = new Product();
Product pChang2 = db.from(p2).where(p2.productName).is("Chang")
.selectFirst();
assertEquals((Double) 19.5, pChang2.unitPrice);
assertEquals(16, pChang2.unitsInStock.intValue());
// undo update
pChang.unitPrice = 19.0;
pChang.unitsInStock = 17;
db.merge(pChang);
}
private void testSimpleMergeWithCombinedPrimaryKey() {
Order o = new Order();
Order ourOrder = db.from(o).where(o.orderDate)
.is(valueOf("2007-01-02")).selectFirst();
ourOrder.orderDate = valueOf("2007-01-03");
db.merge(ourOrder);
Order ourUpdatedOrder = db.from(o).where(o.orderDate)
.is(valueOf("2007-01-03")).selectFirst();
assertNotNull("updated order not found", ourUpdatedOrder);
// undo update
ourOrder.orderDate = valueOf("2007-01-02");
db.merge(ourOrder);
}
private void testSetColumns() {
Product p = new Product();
Product original = db.from(p).where(p.productId).is(1).selectFirst();
// update string and double columns
db.from(p)
.set(p.productName).to("updated")
.increment(p.unitPrice).by(3.14)
.increment(p.unitsInStock).by(2)
.where(p.productId)
.is(1).
update();
// confirm the data was properly updated
Product revised = db.from(p).where(p.productId).is(1).selectFirst();
assertEquals("updated", revised.productName);
assertEquals((Double) (original.unitPrice + 3.14), revised.unitPrice);
assertEquals(original.unitsInStock + 2, revised.unitsInStock.intValue());
// restore the data
db.from(p)
.set(p.productName).to(original.productName)
.set(p.unitPrice).to(original.unitPrice)
.increment(p.unitsInStock).by(-2)
.where(p.productId).is(1).update();
// confirm the data was properly restored
Product restored = db.from(p).
where(p.productId).is(1).selectFirst();
assertEquals(original.productName, restored.productName);
assertEquals(original.unitPrice, restored.unitPrice);
assertEquals(original.unitsInStock, restored.unitsInStock);
double unitPriceOld = db.from(p).
where(p.productId).is(1).selectFirst().unitPrice;
// double the unit price
db.from(p).increment(p.unitPrice).by(p.unitPrice).where(p.productId)
.is(1).update();
double unitPriceNew = db.from(p).
where(p.productId).is(1).selectFirst().unitPrice;
assertEquals(unitPriceOld * 2, unitPriceNew);
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--
Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0, Version 1.0,
and under the Eclipse Public License, Version 1.0
Initial Developer: H2 Group
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><title>
Javadoc package documentation
</title></head><body style="font: 9pt/130% Tahoma, Arial, Helvetica, sans-serif; font-weight: normal;"><p>
JaQu (Java Query) test cases.
</p></body></html>
\ No newline at end of file
...@@ -525,7 +525,6 @@ public class Build extends BuildBase { ...@@ -525,7 +525,6 @@ public class Build extends BuildBase {
exclude("temp/org/h2/build/*"). exclude("temp/org/h2/build/*").
exclude("temp/org/h2/dev/*"). exclude("temp/org/h2/dev/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
exclude("temp/org/h2/jaqu/*").
exclude("temp/org/h2/java/*"). exclude("temp/org/h2/java/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
exclude("temp/org/h2/mode/*"). exclude("temp/org/h2/mode/*").
...@@ -555,7 +554,6 @@ public class Build extends BuildBase { ...@@ -555,7 +554,6 @@ public class Build extends BuildBase {
exclude("temp/org/h2/build/*"). exclude("temp/org/h2/build/*").
exclude("temp/org/h2/dev/*"). exclude("temp/org/h2/dev/*").
exclude("temp/org/h2/fulltext/*"). exclude("temp/org/h2/fulltext/*").
exclude("temp/org/h2/jaqu/*").
exclude("temp/org/h2/java/*"). exclude("temp/org/h2/java/*").
exclude("temp/org/h2/jdbcx/*"). exclude("temp/org/h2/jdbcx/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
...@@ -586,7 +584,6 @@ public class Build extends BuildBase { ...@@ -586,7 +584,6 @@ public class Build extends BuildBase {
FileList files = files("temp"). FileList files = files("temp").
exclude("temp/org/h2/build/*"). exclude("temp/org/h2/build/*").
exclude("temp/org/h2/dev/*"). exclude("temp/org/h2/dev/*").
exclude("temp/org/h2/jaqu/*").
exclude("temp/org/h2/java/*"). exclude("temp/org/h2/java/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
exclude("temp/org/h2/mode/*"). exclude("temp/org/h2/mode/*").
...@@ -631,7 +628,6 @@ public class Build extends BuildBase { ...@@ -631,7 +628,6 @@ public class Build extends BuildBase {
exclude("temp/org/h2/build/*"). exclude("temp/org/h2/build/*").
exclude("temp/org/h2/dev/*"). exclude("temp/org/h2/dev/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
exclude("temp/org/h2/jaqu/*").
exclude("temp/org/h2/java/*"). exclude("temp/org/h2/java/*").
exclude("temp/org/h2/jcr/*"). exclude("temp/org/h2/jcr/*").
exclude("temp/org/h2/mode/*"). exclude("temp/org/h2/mode/*").
...@@ -654,21 +650,6 @@ public class Build extends BuildBase { ...@@ -654,21 +650,6 @@ public class Build extends BuildBase {
jar("bin/h2small" + getJarSuffix(), files, "temp"); jar("bin/h2small" + getJarSuffix(), files, "temp");
} }
/**
* Create the file h2jaqu.jar. This only contains the JaQu (Java Query)
* implementation. All other jar files do not include JaQu.
*/
@Description(summary = "Create jaqu.jar with only the Java Query implementation.")
public void jarJaqu() {
compile(true, false, true);
manifest("H2 JaQu", "");
FileList files = files("temp/org/h2/jaqu");
files.addAll(files("temp/META-INF/MANIFEST.MF"));
files.exclude("*.DS_Store");
files = excludeTestMetaInfFiles(files);
jar("bin/h2jaqu" + getJarSuffix(), files, "temp");
}
/** /**
* Create the Javadocs of the API (incl. the JDBC API) and tools. * Create the Javadocs of the API (incl. the JDBC API) and tools.
*/ */
...@@ -708,8 +689,7 @@ public class Build extends BuildBase { ...@@ -708,8 +689,7 @@ public class Build extends BuildBase {
File.pathSeparator + "ext/org.osgi.core-4.2.0.jar" + File.pathSeparator + "ext/org.osgi.core-4.2.0.jar" +
File.pathSeparator + "ext/org.osgi.enterprise-4.2.0.jar" + File.pathSeparator + "ext/org.osgi.enterprise-4.2.0.jar" +
File.pathSeparator + "ext/jts-core-1.15.0.jar", File.pathSeparator + "ext/jts-core-1.15.0.jar",
"-subpackages", "org.h2", "-subpackages", "org.h2");
"-exclude", "org.h2.test.jaqu:org.h2.jaqu");
mkdir("docs/javadocImpl3"); mkdir("docs/javadocImpl3");
javadoc("-sourcepath", "src/main", javadoc("-sourcepath", "src/main",
...@@ -739,7 +719,6 @@ public class Build extends BuildBase { ...@@ -739,7 +719,6 @@ public class Build extends BuildBase {
File.pathSeparator + "ext/org.osgi.enterprise-4.2.0.jar" + File.pathSeparator + "ext/org.osgi.enterprise-4.2.0.jar" +
File.pathSeparator + "ext/jts-core-1.15.0.jar", File.pathSeparator + "ext/jts-core-1.15.0.jar",
"-subpackages", "org.h2", "-subpackages", "org.h2",
"-exclude", "org.h2.test.jaqu:org.h2.jaqu",
"-package", "-package",
"-docletpath", "bin" + File.pathSeparator + "temp", "-docletpath", "bin" + File.pathSeparator + "temp",
"-doclet", "org.h2.build.doclet.Doclet"); "-doclet", "org.h2.build.doclet.Doclet");
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* An enumeration of compare operations.
*/
enum CompareType {
EQUAL("=", true),
BIGGER(">", true),
BIGGER_EQUAL(">=", true),
SMALLER("<", true),
SMALLER_EQUAL("<=", true),
NOT_EQUAL("<>", true),
IS_NOT_NULL("IS NOT NULL", false),
IS_NULL("IS NULL", false),
LIKE("LIKE", true);
private String text;
private boolean hasRightExpression;
CompareType(String text, boolean hasRightExpression) {
this.text = text;
this.hasRightExpression = hasRightExpression;
}
String getString() {
return text;
}
boolean hasRightExpression() {
return hasRightExpression;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* A condition contains one or two operands and a compare operation.
*
* @param <A> the operand type
*/
class Condition<A> implements Token {
CompareType compareType;
A x, y;
Condition(A x, A y, CompareType compareType) {
this.compareType = compareType;
this.x = x;
this.y = y;
}
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
query.appendSQL(stat, x);
stat.appendSQL(" ");
stat.appendSQL(compareType.getString());
if (compareType.hasRightExpression()) {
stat.appendSQL(" ");
query.appendSQL(stat, y);
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* An OR or an AND condition.
*/
enum ConditionAndOr implements Token {
AND("AND"),
OR("OR");
private String text;
ConditionAndOr(String text) {
this.text = text;
}
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
stat.appendSQL(text);
}
}
差异被折叠。
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.jaqu;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import org.h2.jaqu.Table.JQTable;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils;
/**
* Class to inspect a model and a database for the purposes of model validation
* and automatic model generation. This class finds the available schemas and
* tables and serves as the entry point for model generation and validation.
*/
public class DbInspector {
private final Db db;
private DatabaseMetaData metaData;
private Class<? extends java.util.Date> dateTimeClass = java.util.Date.class;
public DbInspector(Db db) {
this.db = db;
}
/**
* Set the preferred class to store date and time. Possible values are:
* java.util.Date (default) and java.sql.Timestamp.
*
* @param dateTimeClass the new class
*/
public void setPreferredDateTimeClass(
Class<? extends java.util.Date> dateTimeClass) {
this.dateTimeClass = dateTimeClass;
}
/**
* Generates models class skeletons for schemas and tables. If the table
* name is undefined, models will be generated for every table within the
* specified schema. Additionally, if no schema is defined, models will be
* generated for all schemas and all tables.
*
* @param schema the schema name (optional)
* @param table the table name (optional)
* @param packageName the package name (optional)
* @param annotateSchema (includes schema name in annotation)
* @param trimStrings (trims strings to maxLength of column)
* @return a list of complete model classes as strings, each element a class
*/
public List<String> generateModel(String schema, String table,
String packageName, boolean annotateSchema, boolean trimStrings) {
try {
List<TableInspector> tables = getTables(schema, table);
List<String> models = new ArrayList<>(tables.size());
for (TableInspector t : tables) {
t.read(metaData);
String model = t.generateModel(packageName, annotateSchema,
trimStrings);
models.add(model);
}
return models;
} catch (SQLException s) {
throw new RuntimeException(s);
}
}
/**
* Validates a model.
*
* @param <T> the model class
* @param model an instance of the model class
* @param throwOnError if errors should cause validation to fail
* @return a list of validation remarks
*/
public <T> List<ValidationRemark> validateModel(T model,
boolean throwOnError) {
try {
TableInspector inspector = getTable(model);
inspector.read(metaData);
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) model.getClass();
TableDefinition<T> def = db.define(clazz);
return inspector.validate(def, throwOnError);
} catch (SQLException s) {
throw new RuntimeException(s);
}
}
private DatabaseMetaData getMetaData() throws SQLException {
if (metaData == null) {
metaData = db.getConnection().getMetaData();
}
return metaData;
}
/**
* Get the table in the database based on the model definition.
*
* @param <T> the model class
* @param model an instance of the model class
* @return the table inspector
*/
private <T> TableInspector getTable(T model) throws SQLException {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) model.getClass();
TableDefinition<T> def = db.define(clazz);
boolean forceUpperCase = getMetaData().storesUpperCaseIdentifiers();
String schema = (forceUpperCase && def.schemaName != null) ? def.schemaName
.toUpperCase() : def.schemaName;
String table = forceUpperCase ? def.tableName.toUpperCase()
: def.tableName;
List<TableInspector> tables = getTables(schema, table);
return tables.get(0);
}
/**
* Returns a list of tables. This method always returns at least one
* element. If no table is found, an exception is thrown.
*
* @param schema the schema name
* @param table the table name
* @return a list of table inspectors (always contains at least one element)
*/
private List<TableInspector> getTables(String schema, String table)
throws SQLException {
ResultSet rs = null;
try {
rs = getMetaData().getSchemas();
ArrayList<String> schemaList = new ArrayList<>();
while (rs.next()) {
schemaList.add(rs.getString("TABLE_SCHEM"));
}
JdbcUtils.closeSilently(rs);
String jaquTables = DbVersion.class.getAnnotation(JQTable.class)
.name();
List<TableInspector> tables = new ArrayList<>();
if (schemaList.size() == 0) {
schemaList.add(null);
}
for (String s : schemaList) {
rs = getMetaData().getTables(null, s, null,
new String[] { "TABLE" });
while (rs.next()) {
String t = rs.getString("TABLE_NAME");
if (!t.equalsIgnoreCase(jaquTables)) {
tables.add(new TableInspector(s, t, getMetaData()
.storesUpperCaseIdentifiers(), dateTimeClass));
}
}
}
if (StringUtils.isNullOrEmpty(schema)
&& StringUtils.isNullOrEmpty(table)) {
// all schemas and tables
return tables;
}
// schema subset OR table subset OR exact match
List<TableInspector> matches = new ArrayList<>();
for (TableInspector t : tables) {
if (t.matches(schema, table)) {
matches.add(t);
}
}
if (matches.size() == 0) {
throw new RuntimeException(MessageFormat.format(
"Failed to find schema={0} table={1}",
schema == null ? "" : schema, table == null ? ""
: table));
}
return matches;
} finally {
JdbcUtils.closeSilently(rs);
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.jaqu;
import org.h2.jaqu.Table.JQDatabase;
/**
* Interface which defines a class to handle table changes based on model
* versions. An implementation of <i>DbUpgrader</i> must be annotated with the
* <i>JQDatabase</i> annotation, which defines the expected database version
* number.
*/
public interface DbUpgrader {
/**
* Defines method interface to handle database upgrades. This method is only
* called if your <i>DbUpgrader</i> implementation is annotated with
* JQDatabase.
*
* @param db the database
* @param fromVersion the old version
* @param toVersion the new version
* @return true for successful upgrade. If the upgrade is successful, the
* version registry is automatically updated.
*/
boolean upgradeDatabase(Db db, int fromVersion, int toVersion);
/**
* Defines method interface to handle table upgrades.
*
* @param db the database
* @param schema the schema
* @param table the table
* @param fromVersion the old version
* @param toVersion the new version
* @return true for successful upgrade. If the upgrade is successful, the
* version registry is automatically updated.
*/
boolean upgradeTable(Db db, String schema, String table, int fromVersion,
int toVersion);
/**
* The default database upgrader. It throws runtime exception instead of
* handling upgrade requests.
*/
@JQDatabase(version = 0)
public static class DefaultDbUpgrader implements DbUpgrader {
@Override
public boolean upgradeDatabase(Db db, int fromVersion, int toVersion) {
throw new RuntimeException(
"Please provide your own DbUpgrader implementation.");
}
@Override
public boolean upgradeTable(Db db, String schema, String table,
int fromVersion, int toVersion) {
throw new RuntimeException(
"Please provide your own DbUpgrader implementation.");
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.jaqu;
import org.h2.jaqu.Table.JQColumn;
import org.h2.jaqu.Table.JQTable;
/**
* A system table to track database and table versions.
*/
@JQTable(name = "_jq_versions",
primaryKey = "schemaName tableName", memoryTable = true)
public class DbVersion {
@JQColumn(name = "schemaName", allowNull = false)
String schema = "";
@JQColumn(name = "tableName", allowNull = false)
String table = "";
@JQColumn(name = "version")
Integer version;
public DbVersion() {
// nothing to do
}
/**
* Constructor for defining a version entry. Both the schema and the table
* are empty strings, which means this is the row for the 'database'.
*
* @param version the database version
*/
public DbVersion(int version) {
this.schema = "";
this.table = "";
this.version = version;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import org.h2.jaqu.Table.IndexType;
/**
* This class provides utility methods to define primary keys, indexes, and set
* the name of the table.
*/
public class Define {
private static TableDefinition<?> currentTableDefinition;
private static Table currentTable;
public static void primaryKey(Object... columns) {
checkInDefine();
currentTableDefinition.setPrimaryKey(columns);
}
public static void index(Object... columns) {
checkInDefine();
currentTableDefinition.addIndex(IndexType.STANDARD, columns);
}
public static void uniqueIndex(Object... columns) {
checkInDefine();
currentTableDefinition.addIndex(IndexType.UNIQUE, columns);
}
public static void hashIndex(Object column) {
checkInDefine();
currentTableDefinition
.addIndex(IndexType.HASH, new Object[] { column });
}
public static void uniqueHashIndex(Object column) {
checkInDefine();
currentTableDefinition.addIndex(IndexType.UNIQUE_HASH,
new Object[] { column });
}
public static void maxLength(Object column, int length) {
checkInDefine();
currentTableDefinition.setMaxLength(column, length);
}
public static void tableName(String tableName) {
currentTableDefinition.setTableName(tableName);
}
static synchronized <T> void define(TableDefinition<T> tableDefinition,
Table table) {
currentTableDefinition = tableDefinition;
currentTable = table;
tableDefinition.mapObject(table);
table.define();
currentTable = null;
}
private static void checkInDefine() {
if (currentTable == null) {
throw new RuntimeException(
"This method may only be called "
+ "from within the define() method, and the define() method "
+ "is called by the framework.");
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* Represents the WHERE clause of a query.
*/
public interface Filter {
boolean where();
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import org.h2.jaqu.util.ClassUtils;
/**
* This class provides static methods that represents common SQL functions.
*/
public class Function implements Token {
// must be a new instance
private static final Long COUNT_STAR = Long.valueOf(0);
protected Object[] x;
private final String name;
protected Function(String name, Object... x) {
this.name = name;
this.x = x;
}
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
stat.appendSQL(name).appendSQL("(");
int i = 0;
for (Object o : x) {
if (i++ > 0) {
stat.appendSQL(",");
}
query.appendSQL(stat, o);
}
stat.appendSQL(")");
}
public static Long count() {
return COUNT_STAR;
}
public static Integer length(Object x) {
return Db.registerToken(
ClassUtils.newObject(Integer.class), new Function("LENGTH", x));
}
@SuppressWarnings("unchecked")
public static <T extends Number> T sum(T x) {
return (T) Db.registerToken(
ClassUtils.newObject(x.getClass()), new Function("SUM", x));
}
public static Long count(Object x) {
return Db.registerToken(
ClassUtils.newObject(Long.class), new Function("COUNT", x));
}
public static Boolean isNull(Object x) {
return Db.registerToken(
ClassUtils.newObject(Boolean.class), new Function("", x) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
query.appendSQL(stat, x[0]);
stat.appendSQL(" IS NULL");
}
});
}
public static Boolean isNotNull(Object x) {
return Db.registerToken(
ClassUtils.newObject(Boolean.class), new Function("", x) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
query.appendSQL(stat, x[0]);
stat.appendSQL(" IS NOT NULL");
}
});
}
public static Boolean not(Boolean x) {
return Db.registerToken(
ClassUtils.newObject(Boolean.class), new Function("", x) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
stat.appendSQL("NOT ");
query.appendSQL(stat, x[0]);
}
});
}
public static Boolean or(Boolean... x) {
return Db.registerToken(
ClassUtils.newObject(Boolean.class),
new Function("", (Object[]) x) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
int i = 0;
for (Object o : x) {
if (i++ > 0) {
stat.appendSQL(" OR ");
}
query.appendSQL(stat, o);
}
}
});
}
public static Boolean and(Boolean... x) {
return Db.registerToken(
ClassUtils.newObject(Boolean.class),
new Function("", (Object[]) x) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
int i = 0;
for (Object o : x) {
if (i++ > 0) {
stat.appendSQL(" AND ");
}
query.appendSQL(stat, o);
}
}
});
}
@SuppressWarnings("unchecked")
public static <X> X min(X x) {
Class<X> clazz = (Class<X>) x.getClass();
X o = ClassUtils.newObject(clazz);
return Db.registerToken(o, new Function("MIN", x));
}
@SuppressWarnings("unchecked")
public static <X> X max(X x) {
Class<X> clazz = (Class<X>) x.getClass();
X o = ClassUtils.newObject(clazz);
return Db.registerToken(o, new Function("MAX", x));
}
public static Boolean like(String x, String pattern) {
Boolean o = ClassUtils.newObject(Boolean.class);
return Db.registerToken(o, new Function("LIKE", x, pattern) {
@Override
public <T> void appendSQL(SQLStatement stat, Query<T> query) {
stat.appendSQL("(");
query.appendSQL(stat, x[0]);
stat.appendSQL(" LIKE ");
query.appendSQL(stat, x[1]);
stat.appendSQL(")");
}
});
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* An expression to order by in a query.
*
* @param <T> the query data type
*/
class OrderExpression<T> {
private final Query<T> query;
private final Object expression;
private final boolean desc;
private final boolean nullsFirst;
private final boolean nullsLast;
OrderExpression(Query<T> query, Object expression, boolean desc,
boolean nullsFirst, boolean nullsLast) {
this.query = query;
this.expression = expression;
this.desc = desc;
this.nullsFirst = nullsFirst;
this.nullsLast = nullsLast;
}
void appendSQL(SQLStatement stat) {
query.appendSQL(stat, expression);
if (desc) {
stat.appendSQL(" DESC");
}
if (nullsLast) {
stat.appendSQL(" NULLS LAST");
}
if (nullsFirst) {
stat.appendSQL(" NULLS FIRST");
}
}
}
差异被折叠。
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* This class represents a query with an incomplete condition.
*
* @param <T> the return type of the query
* @param <A> the incomplete condition data type
*/
public class QueryCondition<T, A> {
private final Query<T> query;
private final A x;
QueryCondition(Query<T> query, A x) {
this.query = query;
this.x = x;
}
public QueryWhere<T> is(A y) {
query.addConditionToken(
new Condition<>(x, y, CompareType.EQUAL));
return new QueryWhere<>(query);
}
public QueryWhere<T> bigger(A y) {
query.addConditionToken(
new Condition<>(x, y, CompareType.BIGGER));
return new QueryWhere<>(query);
}
public QueryWhere<T> biggerEqual(A y) {
query.addConditionToken(
new Condition<>(x, y, CompareType.BIGGER_EQUAL));
return new QueryWhere<>(query);
}
public QueryWhere<T> smaller(A y) {
query.addConditionToken(
new Condition<>(x, y, CompareType.SMALLER));
return new QueryWhere<>(query);
}
public QueryWhere<T> smallerEqual(A y) {
query.addConditionToken(
new Condition<>(x, y, CompareType.SMALLER_EQUAL));
return new QueryWhere<>(query);
}
public QueryWhere<T> like(A pattern) {
query.addConditionToken(
new Condition<>(x, pattern, CompareType.LIKE));
return new QueryWhere<>(query);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* This class represents a query with a join.
*/
public class QueryJoin {
private final Query<?> query;
private final SelectTable<?> join;
QueryJoin(Query<?> query, SelectTable<?> join) {
this.query = query;
this.join = join;
}
public <A> QueryJoinCondition<A> on(A x) {
return new QueryJoinCondition<>(query, join, x);
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
/**
* This class represents a query with join and an incomplete condition.
*
* @param <A> the incomplete condition data type
*/
public class QueryJoinCondition<A> {
private final Query<?> query;
private final SelectTable<?> join;
private final A x;
QueryJoinCondition(Query<?> query, SelectTable<?> join, A x) {
this.query = query;
this.join = join;
this.x = x;
}
public Query<?> is(A y) {
join.addConditionToken(new Condition<>(x, y, CompareType.EQUAL));
return query;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import java.util.List;
/**
* This class represents a query with a condition.
*
* @param <T> the return type
*/
public class QueryWhere<T> {
Query<T> query;
QueryWhere(Query<T> query) {
this.query = query;
}
public <A> QueryCondition<T, A> and(A x) {
query.addConditionToken(ConditionAndOr.AND);
return new QueryCondition<>(query, x);
}
public <A> QueryCondition<T, A> or(A x) {
query.addConditionToken(ConditionAndOr.OR);
return new QueryCondition<>(query, x);
}
public QueryWhere<T> limit(long limit) {
query.limit(limit);
return this;
}
public QueryWhere<T> offset(long offset) {
query.offset(offset);
return this;
}
public <X, Z> List<X> select(Z x) {
return query.select(x);
}
public String getSQL() {
SQLStatement stat = new SQLStatement(query.getDb());
stat.appendSQL("SELECT *");
query.appendFromWhere(stat);
return stat.getSQL().trim();
}
public <X, Z> List<X> selectDistinct(Z x) {
return query.selectDistinct(x);
}
public <X, Z> X selectFirst(Z x) {
List<X> list = query.select(x);
return list.isEmpty() ? null : list.get(0);
}
public List<T> select() {
return query.select();
}
public T selectFirst() {
List<T> list = select();
return list.isEmpty() ? null : list.get(0);
}
public List<T> selectDistinct() {
return query.selectDistinct();
}
/**
* Order by a number of columns.
*
* @param expressions the order by expressions
* @return the query
*/
public QueryWhere<T> orderBy(Object... expressions) {
for (Object expr : expressions) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, false, false, false);
query.addOrderBy(e);
}
return this;
}
public QueryWhere<T> orderByNullsFirst(Object expr) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, false, true, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByNullsLast(Object expr) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, false, false, true);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDesc(Object expr) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, true, false, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDescNullsFirst(Object expr) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, true, true, false);
query.addOrderBy(e);
return this;
}
public QueryWhere<T> orderByDescNullsLast(Object expr) {
OrderExpression<T> e =
new OrderExpression<>(query, expr, true, false, true);
query.addOrderBy(e);
return this;
}
public int delete() {
return query.delete();
}
public int update() {
return query.update();
}
public long selectCount() {
return query.selectCount();
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: James Moger
*/
package org.h2.jaqu;
import org.h2.jaqu.TableDefinition.IndexDefinition;
import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils;
/**
* This interface defines points where JaQu can build different statements
* depending on the database used.
*/
public interface SQLDialect {
/**
* Get the SQL snippet for the table name.
*
* @param schema the schema name, or null for no schema
* @param table the table name
* @return the SQL snippet
*/
String getTableName(String schema, String table);
/**
* Get the CREATE INDEX statement.
*
* @param schema the schema name
* @param table the table name
* @param index the index definition
* @return the SQL statement
*/
String getCreateIndex(String schema, String table, IndexDefinition index);
/**
* Append "LIMIT limit" to the SQL statement.
*
* @param stat the statement
* @param limit the limit
*/
void appendLimit(SQLStatement stat, long limit);
/**
* Append "OFFSET offset" to the SQL statement.
*
* @param stat the statement
* @param offset the offset
*/
void appendOffset(SQLStatement stat, long offset);
/**
* Whether memory tables are supported.
*
* @return true if they are
*/
boolean supportsMemoryTables();
/**
* Default implementation of an SQL dialect. Designed for an H2 database,
* and may be suitable for others.
*/
public static class DefaultSQLDialect implements SQLDialect {
@Override
public String getTableName(String schema, String table) {
if (StringUtils.isNullOrEmpty(schema)) {
return table;
}
return schema + "." + table;
}
@Override
public boolean supportsMemoryTables() {
return true;
}
@Override
public String getCreateIndex(String schema, String table,
IndexDefinition index) {
StatementBuilder buff = new StatementBuilder();
buff.append("CREATE ");
switch (index.type) {
case STANDARD:
break;
case UNIQUE:
buff.append("UNIQUE ");
break;
case HASH:
buff.append("HASH ");
break;
case UNIQUE_HASH:
buff.append("UNIQUE HASH ");
break;
}
buff.append("INDEX IF NOT EXISTS ");
buff.append(index.indexName);
buff.append(" ON ");
buff.append(table);
buff.append('(');
for (String col : index.columnNames) {
buff.appendExceptFirst(", ");
buff.append(col);
}
buff.append(')');
return buff.toString();
}
@Override
public void appendLimit(SQLStatement stat, long limit) {
stat.appendSQL(" LIMIT " + limit);
}
@Override
public void appendOffset(SQLStatement stat, long offset) {
stat.appendSQL(" OFFSET " + offset);
}
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.util.JdbcUtils;
/**
* This class represents a parameterized SQL statement.
*/
public class SQLStatement {
private final Db db;
private StringBuilder buff = new StringBuilder();
private String sql;
private final ArrayList<Object> params = new ArrayList<>();
SQLStatement(Db db) {
this.db = db;
}
void setSQL(String sql) {
this.sql = sql;
buff = new StringBuilder(sql);
}
public SQLStatement appendSQL(String s) {
buff.append(s);
sql = null;
return this;
}
public SQLStatement appendTable(String schema, String table) {
return appendSQL(db.getDialect().getTableName(schema, table));
}
String getSQL() {
if (sql == null) {
sql = buff.toString();
}
return sql;
}
SQLStatement addParameter(Object o) {
params.add(o);
return this;
}
ResultSet executeQuery() {
try {
return prepare(false).executeQuery();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
int executeUpdate() {
PreparedStatement ps = null;
try {
ps = prepare(false);
return ps.executeUpdate();
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.closeSilently(ps);
}
}
long executeInsert() {
PreparedStatement ps = null;
try {
ps = prepare(true);
ps.executeUpdate();
long identity = -1;
ResultSet rs = ps.getGeneratedKeys();
if (rs != null && rs.next()) {
identity = rs.getLong(1);
}
JdbcUtils.closeSilently(rs);
return identity;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.closeSilently(ps);
}
}
private static void setValue(PreparedStatement prep, int parameterIndex,
Object x) {
try {
prep.setObject(parameterIndex, x);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private PreparedStatement prepare(boolean returnGeneratedKeys) {
PreparedStatement prep = db.prepare(getSQL(), returnGeneratedKeys);
for (int i = 0; i < params.size(); i++) {
Object o = params.get(i);
setValue(prep, i + 1, o);
}
return prep;
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import org.h2.jaqu.TableDefinition.FieldDefinition;
/**
* This class represents a column of a table in a query.
*
* @param <T> the table data type
*/
class SelectColumn<T> {
private final SelectTable<T> selectTable;
private final FieldDefinition fieldDef;
SelectColumn(SelectTable<T> table, FieldDefinition fieldDef) {
this.selectTable = table;
this.fieldDef = fieldDef;
}
void appendSQL(SQLStatement stat) {
if (selectTable.getQuery().isJoin()) {
stat.appendSQL(selectTable.getAs() + "." + fieldDef.columnName);
} else {
stat.appendSQL(fieldDef.columnName);
}
}
FieldDefinition getFieldDefinition() {
return fieldDef;
}
SelectTable<T> getSelectTable() {
return selectTable;
}
Object getCurrentValue() {
return fieldDef.getValue(selectTable.getCurrent());
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jaqu;
import java.util.ArrayList;
import org.h2.jaqu.util.ClassUtils;
/**
* This class represents a table in a query.
*
* @param <T> the table class
*/
class SelectTable<T> {
private static int asCounter;
private final Query<T> query;
private final Class<T> clazz;
private T current;
private final String as;
private final TableDefinition<T> aliasDef;
private final boolean outerJoin;
private final ArrayList<Token> joinConditions = new ArrayList<>();
private final T alias;
@SuppressWarnings("unchecked")
SelectTable(Db db, Query<T> query, T alias, boolean outerJoin) {
this.alias = alias;
this.query = query;
this.outerJoin = outerJoin;
aliasDef = (TableDefinition<T>) db.getTableDefinition(alias.getClass());
clazz = ClassUtils.getClass(alias);
as = "T" + asCounter++;
}
T getAlias() {
return alias;
}
T newObject() {
return ClassUtils.newObject(clazz);
}
TableDefinition<T> getAliasDefinition() {
return aliasDef;
}
void appendSQL(SQLStatement stat) {
if (query.isJoin()) {
stat.appendTable(aliasDef.schemaName, aliasDef.tableName)
.appendSQL(" AS " + as);
} else {
stat.appendTable(aliasDef.schemaName, aliasDef.tableName);
}
}
void appendSQLAsJoin(SQLStatement stat, Query<T> q) {
if (outerJoin) {
stat.appendSQL(" LEFT OUTER JOIN ");
} else {
stat.appendSQL(" INNER JOIN ");
}
appendSQL(stat);
if (!joinConditions.isEmpty()) {
stat.appendSQL(" ON ");
for (Token token : joinConditions) {
token.appendSQL(stat, q);
stat.appendSQL(" ");
}
}
}
boolean getOuterJoin() {
return outerJoin;
}
Query<T> getQuery() {
return query;
}
String getAs() {
return as;
}
void addConditionToken(Token condition) {
joinConditions.add(condition);
}
T getCurrent() {
return current;
}
void setCurrent(T current) {
this.current = current;
}
}
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论