[#1968] Add org.jooq.Meta returned from Executor.meta() to return a
wrapped JDBC DatabaseMetaData object
This commit is contained in:
parent
e1ca385651
commit
02ccfc766d
@ -24,7 +24,7 @@
|
||||
<classpathentry exported="true" kind="lib" path="lib/jconn3.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/jtds-1.2.5.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/iijdbc.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/h2-1.3.168.jar" sourcepath="/jOOQ-sources/h2-1.3.165-sources.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/h2-1.3.168.jar" sourcepath="/h2"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/CUBRID-9.0.0_jdbc.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/rsyntaxtextarea-2.0.2.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/jaybird-2.2.0.jar"/>
|
||||
|
||||
@ -40,18 +40,7 @@ import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.jooq.SQLDialect.ASE;
|
||||
import static org.jooq.SQLDialect.CUBRID;
|
||||
import static org.jooq.SQLDialect.DB2;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
import static org.jooq.SQLDialect.ORACLE;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
import static org.jooq.SQLDialect.SYBASE;
|
||||
import static org.jooq.impl.Factory.castNull;
|
||||
import static org.jooq.impl.Factory.count;
|
||||
import static org.jooq.impl.Factory.deg;
|
||||
@ -68,8 +57,6 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Date;
|
||||
import java.util.Arrays;
|
||||
@ -82,22 +69,16 @@ import org.jooq.Record2;
|
||||
import org.jooq.Record3;
|
||||
import org.jooq.Record6;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.SelectQuery;
|
||||
import org.jooq.Sequence;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UDT;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.UpdatableTable;
|
||||
import org.jooq.UpdateQuery;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.exception.DetachedException;
|
||||
import org.jooq.impl.DefaultExecuteListener;
|
||||
import org.jooq.impl.Executor;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
|
||||
@ -439,290 +420,6 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725,
|
||||
create().select(TBook_TITLE(), TBook_ID()).from(TBook()).fetch()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaModel() throws Exception {
|
||||
|
||||
// Test correct source code generation for the meta model
|
||||
Schema schema = TAuthor().getSchema();
|
||||
if (schema != null) {
|
||||
int sequences = 0;
|
||||
|
||||
if (cSequences() != null) {
|
||||
sequences++;
|
||||
|
||||
// DB2 has an additional sequence for the T_TRIGGERS table
|
||||
if (getDialect() == DB2 ||
|
||||
getDialect() == H2) {
|
||||
|
||||
sequences++;
|
||||
}
|
||||
|
||||
// CUBRID generates sequences for AUTO_INCREMENT columns
|
||||
else if (getDialect() == CUBRID) {
|
||||
sequences += 3;
|
||||
}
|
||||
|
||||
// Oracle has additional sequences for [#961]
|
||||
else if (getDialect() == ORACLE) {
|
||||
sequences += 5;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(sequences, schema.getSequences().size());
|
||||
for (Table<?> table : schema.getTables()) {
|
||||
assertEquals(table, schema.getTable(table.getName()));
|
||||
}
|
||||
for (UDT<?> udt : schema.getUDTs()) {
|
||||
assertEquals(udt, schema.getUDT(udt.getName()));
|
||||
}
|
||||
for (Sequence<?> sequence : schema.getSequences()) {
|
||||
assertEquals(sequence, schema.getSequence(sequence.getName()));
|
||||
}
|
||||
|
||||
int tables = 17;
|
||||
|
||||
// The additional T_DIRECTORY table for recursive queries
|
||||
if (supportsRecursiveQueries()) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_TRIGGERS table for INSERT .. RETURNING
|
||||
if (TTriggers() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_UNSIGNED table
|
||||
if (TUnsigned() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_IDENTITY table
|
||||
if (TIdentity() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_IDENTITY_PK table
|
||||
if (TIdentityPK() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// [#959] The T_959 table for enum collisions with Java keywords
|
||||
if (getDialect() == MYSQL ||
|
||||
getDialect() == POSTGRES) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// [#986] Some foreign key name collision checks
|
||||
if (getDialect() == ASE ||
|
||||
getDialect() == CUBRID ||
|
||||
getDialect() == DB2 ||
|
||||
getDialect() == POSTGRES ||
|
||||
getDialect() == SQLITE ||
|
||||
getDialect() == SYBASE) {
|
||||
|
||||
tables += 2;
|
||||
}
|
||||
|
||||
if (TArrays() == null) {
|
||||
assertEquals(tables, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#877] The T_877 table is only available in H2
|
||||
else if (getDialect() == H2) {
|
||||
assertEquals(tables + 2, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#624] The V_INCOMPLETE view is only available in Oracle
|
||||
else if (getDialect() == ORACLE) {
|
||||
assertEquals(tables + 3, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#610] Collision-prone entities are only available in HSQLDB
|
||||
else if (getDialect() == HSQLDB) {
|
||||
assertEquals(tables + 11, schema.getTables().size());
|
||||
}
|
||||
|
||||
else {
|
||||
assertEquals(tables + 1, schema.getTables().size());
|
||||
}
|
||||
|
||||
if (cUAddressType() == null) {
|
||||
assertEquals(0, schema.getUDTs().size());
|
||||
}
|
||||
// [#643] The U_INVALID types are only available in Oracle
|
||||
// [#799] The member procedure UDT's too
|
||||
else if (getDialect() == ORACLE) {
|
||||
assertEquals(7, schema.getUDTs().size());
|
||||
}
|
||||
else {
|
||||
assertEquals(2, schema.getUDTs().size());
|
||||
}
|
||||
}
|
||||
|
||||
// Test correct source code generation for identity columns
|
||||
assertNull(TAuthor().getIdentity());
|
||||
assertNull(TBook().getIdentity());
|
||||
|
||||
if (TIdentity() != null || TIdentityPK() != null) {
|
||||
if (TIdentity() != null) {
|
||||
assertEquals(TIdentity(), TIdentity().getIdentity().getTable());
|
||||
assertEquals(TIdentity_ID(), TIdentity().getIdentity().getField());
|
||||
}
|
||||
|
||||
if (TIdentityPK() != null) {
|
||||
assertEquals(TIdentityPK(), TIdentityPK().getIdentity().getTable());
|
||||
assertEquals(TIdentityPK_ID(), TIdentityPK().getIdentity().getField());
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("SKIPPING", "Identity tests");
|
||||
}
|
||||
|
||||
// Test correct source code generation for relations
|
||||
assertNotNull(TAuthor().getMainKey());
|
||||
assertNotNull(TAuthor().getKeys());
|
||||
assertTrue(TAuthor().getKeys().contains(TAuthor().getMainKey()));
|
||||
assertEquals(1, TAuthor().getKeys().size());
|
||||
assertEquals(1, TAuthor().getMainKey().getFields().size());
|
||||
assertEquals(TAuthor_ID(), TAuthor().getMainKey().getFields().get(0));
|
||||
assertEquals(Record1.class, TAuthor().getRecordType().getMethod("key").getReturnType());
|
||||
assertTrue(TAuthor().getRecordType().getMethod("key").toGenericString().contains("org.jooq.Record1<java.lang.Integer>"));
|
||||
assertEquals(Record2.class, TBookToBookStore().getRecordType().getMethod("key").getReturnType());
|
||||
assertTrue(TBookToBookStore().getRecordType().getMethod("key").toGenericString().contains("org.jooq.Record2<java.lang.String, java.lang.Integer>"));
|
||||
|
||||
if (supportsReferences()) {
|
||||
|
||||
// Without aliasing
|
||||
assertEquals(0, TAuthor().getReferences().size());
|
||||
assertEquals(2, TAuthor().getMainKey().getReferences().size());
|
||||
assertEquals(TBook(), TAuthor().getMainKey().getReferences().get(0).getTable());
|
||||
assertEquals(TBook(), TAuthor().getMainKey().getReferences().get(1).getTable());
|
||||
assertEquals(Arrays.asList(), TAuthor().getReferencesTo(TBook()));
|
||||
assertTrue(TBook().getReferences().containsAll(TAuthor().getReferencesFrom(TBook())));
|
||||
assertTrue(TBook().getReferences().containsAll(TBook().getReferencesFrom(TAuthor())));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), TAuthor().getReferencesFrom(TBook()));
|
||||
|
||||
// [#1460] With aliasing
|
||||
Table<A> a = TAuthor().as("a");
|
||||
Table<B> b = TBook().as("b");
|
||||
|
||||
assertEquals(0, a.getReferences().size());
|
||||
assertEquals(Arrays.asList(), a.getReferencesTo(b));
|
||||
|
||||
// This should work with both types of meta-models (static, non-static)
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), TBook().getReferencesTo(a));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), b.getReferencesTo(a));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), b.getReferencesTo(TAuthor()));
|
||||
|
||||
// Only with a non-static meta model
|
||||
if (a instanceof UpdatableTable && b instanceof UpdatableTable) {
|
||||
UpdatableTable<A> ua = (UpdatableTable<A>) a;
|
||||
UpdatableTable<B> ub = (UpdatableTable<B>) b;
|
||||
|
||||
assertEquals(2, ua.getMainKey().getReferences().size());
|
||||
assertEquals(TBook(), ua.getMainKey().getReferences().get(0).getTable());
|
||||
assertEquals(TBook(), ua.getMainKey().getReferences().get(1).getTable());
|
||||
assertTrue(b.getReferences().containsAll(ua.getReferencesFrom(b)));
|
||||
assertTrue(b.getReferences().containsAll(ub.getReferencesFrom(a)));
|
||||
assertEquals(b.getReferencesTo(a), ua.getReferencesFrom(b));
|
||||
assertEquals(TBook().getReferencesTo(a), ua.getReferencesFrom(b));
|
||||
assertEquals(b.getReferencesTo(a), TAuthor().getReferencesFrom(b));
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("SKIPPING", "References tests");
|
||||
}
|
||||
|
||||
for (Field<?> field : T639().getFields()) {
|
||||
if ("BYTE".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Byte.class, field.getType());
|
||||
assertEquals(SQLDataType.TINYINT, field.getDataType());
|
||||
}
|
||||
else if ("SHORT".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Short.class, field.getType());
|
||||
assertEquals(SQLDataType.SMALLINT, field.getDataType());
|
||||
}
|
||||
else if ("INTEGER".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Integer.class, field.getType());
|
||||
assertEquals(SQLDataType.INTEGER, field.getDataType());
|
||||
}
|
||||
else if ("LONG".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Long.class, field.getType());
|
||||
assertEquals(SQLDataType.BIGINT, field.getDataType());
|
||||
}
|
||||
else if ("BYTE_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Byte.class, field.getType());
|
||||
assertEquals(SQLDataType.TINYINT, field.getDataType());
|
||||
}
|
||||
else if ("SHORT_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Short.class, field.getType());
|
||||
assertEquals(SQLDataType.SMALLINT, field.getDataType());
|
||||
}
|
||||
else if ("INTEGER_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Integer.class, field.getType());
|
||||
assertEquals(SQLDataType.INTEGER, field.getDataType());
|
||||
}
|
||||
else if ("LONG_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Long.class, field.getType());
|
||||
assertEquals(SQLDataType.BIGINT, field.getDataType());
|
||||
}
|
||||
else if ("BIG_INTEGER".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(BigInteger.class, field.getType());
|
||||
assertEquals(SQLDataType.DECIMAL_INTEGER, field.getDataType());
|
||||
}
|
||||
|
||||
// [#745] TODO: Unify distinction between NUMERIC and DECIMAL
|
||||
else if ("BIG_DECIMAL".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.ORACLE
|
||||
&& getDialect() != SQLDialect.POSTGRES
|
||||
&& getDialect() != SQLDialect.SQLITE
|
||||
&& getDialect() != SQLDialect.SQLSERVER) {
|
||||
|
||||
assertEquals(BigDecimal.class, field.getType());
|
||||
assertEquals(SQLDataType.DECIMAL, field.getDataType());
|
||||
}
|
||||
else if ("BIG_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(BigDecimal.class, field.getType());
|
||||
assertEquals(SQLDataType.NUMERIC, field.getDataType());
|
||||
}
|
||||
|
||||
// [#746] TODO: Interestingly, HSQLDB and MySQL match REAL with DOUBLE.
|
||||
// There is no matching type for java.lang.Float...
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.HSQLDB
|
||||
&& getDialect() != SQLDialect.MYSQL
|
||||
&& getDialect() != SQLDialect.SYBASE) {
|
||||
|
||||
assertEquals(Float.class, field.getType());
|
||||
assertEquals(SQLDataType.REAL, field.getDataType());
|
||||
}
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.MYSQL
|
||||
&& getDialect() != SQLDialect.SYBASE) {
|
||||
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.DOUBLE, field.getDataType());
|
||||
}
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.FLOAT, field.getDataType());
|
||||
}
|
||||
|
||||
// [#746] TODO: Fix this, too
|
||||
else if ("DOUBLE".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.SQLSERVER
|
||||
&& getDialect() != SQLDialect.ASE) {
|
||||
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.DOUBLE, field.getDataType());
|
||||
}
|
||||
else if ("DOUBLE".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.FLOAT, field.getDataType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchSingle() throws Exception {
|
||||
jOOQAbstractTest.reset = false;
|
||||
|
||||
456
jOOQ-test/src/org/jooq/test/_/testcases/MetaDataTests.java
Normal file
456
jOOQ-test/src/org/jooq/test/_/testcases/MetaDataTests.java
Normal file
@ -0,0 +1,456 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.test._.testcases;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.jooq.SQLDialect.ASE;
|
||||
import static org.jooq.SQLDialect.CUBRID;
|
||||
import static org.jooq.SQLDialect.DB2;
|
||||
import static org.jooq.SQLDialect.H2;
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.MYSQL;
|
||||
import static org.jooq.SQLDialect.ORACLE;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.SQLDialect.SQLITE;
|
||||
import static org.jooq.SQLDialect.SYBASE;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Date;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Meta;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
import org.jooq.Record3;
|
||||
import org.jooq.Record6;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Sequence;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UDT;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.UpdatableTable;
|
||||
import org.jooq.impl.SQLDataType;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class MetaDataTests<
|
||||
A extends UpdatableRecord<A> & Record6<Integer, String, String, Date, Integer, ?>,
|
||||
AP,
|
||||
B extends UpdatableRecord<B>,
|
||||
S extends UpdatableRecord<S> & Record1<String>,
|
||||
B2S extends UpdatableRecord<B2S> & Record3<String, Integer, Integer>,
|
||||
BS extends UpdatableRecord<BS>,
|
||||
L extends TableRecord<L> & Record2<String, String>,
|
||||
X extends TableRecord<X>,
|
||||
DATE extends UpdatableRecord<DATE>,
|
||||
BOOL extends UpdatableRecord<BOOL>,
|
||||
D extends UpdatableRecord<D>,
|
||||
T extends UpdatableRecord<T>,
|
||||
U extends TableRecord<U>,
|
||||
I extends TableRecord<I>,
|
||||
IPK extends UpdatableRecord<IPK>,
|
||||
T725 extends UpdatableRecord<T725>,
|
||||
T639 extends UpdatableRecord<T639>,
|
||||
T785 extends TableRecord<T785>>
|
||||
extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725, T639, T785> {
|
||||
|
||||
public MetaDataTests(jOOQAbstractTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T725, T639, T785> delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaModel() throws Exception {
|
||||
|
||||
// Test correct source code generation for the meta model
|
||||
Schema schema = TAuthor().getSchema();
|
||||
if (schema != null) {
|
||||
int sequences = 0;
|
||||
|
||||
if (cSequences() != null) {
|
||||
sequences++;
|
||||
|
||||
// DB2 has an additional sequence for the T_TRIGGERS table
|
||||
if (getDialect() == DB2 ||
|
||||
getDialect() == H2) {
|
||||
|
||||
sequences++;
|
||||
}
|
||||
|
||||
// CUBRID generates sequences for AUTO_INCREMENT columns
|
||||
else if (getDialect() == CUBRID) {
|
||||
sequences += 3;
|
||||
}
|
||||
|
||||
// Oracle has additional sequences for [#961]
|
||||
else if (getDialect() == ORACLE) {
|
||||
sequences += 5;
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(sequences, schema.getSequences().size());
|
||||
for (Table<?> table : schema.getTables()) {
|
||||
assertEquals(table, schema.getTable(table.getName()));
|
||||
}
|
||||
for (UDT<?> udt : schema.getUDTs()) {
|
||||
assertEquals(udt, schema.getUDT(udt.getName()));
|
||||
}
|
||||
for (Sequence<?> sequence : schema.getSequences()) {
|
||||
assertEquals(sequence, schema.getSequence(sequence.getName()));
|
||||
}
|
||||
|
||||
int tables = 17;
|
||||
|
||||
// The additional T_DIRECTORY table for recursive queries
|
||||
if (supportsRecursiveQueries()) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_TRIGGERS table for INSERT .. RETURNING
|
||||
if (TTriggers() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_UNSIGNED table
|
||||
if (TUnsigned() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_IDENTITY table
|
||||
if (TIdentity() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// The additional T_IDENTITY_PK table
|
||||
if (TIdentityPK() != null) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// [#959] The T_959 table for enum collisions with Java keywords
|
||||
if (getDialect() == MYSQL ||
|
||||
getDialect() == POSTGRES) {
|
||||
tables++;
|
||||
}
|
||||
|
||||
// [#986] Some foreign key name collision checks
|
||||
if (getDialect() == ASE ||
|
||||
getDialect() == CUBRID ||
|
||||
getDialect() == DB2 ||
|
||||
getDialect() == POSTGRES ||
|
||||
getDialect() == SQLITE ||
|
||||
getDialect() == SYBASE) {
|
||||
|
||||
tables += 2;
|
||||
}
|
||||
|
||||
if (TArrays() == null) {
|
||||
assertEquals(tables, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#877] The T_877 table is only available in H2
|
||||
else if (getDialect() == H2) {
|
||||
assertEquals(tables + 2, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#624] The V_INCOMPLETE view is only available in Oracle
|
||||
else if (getDialect() == ORACLE) {
|
||||
assertEquals(tables + 3, schema.getTables().size());
|
||||
}
|
||||
|
||||
// [#610] Collision-prone entities are only available in HSQLDB
|
||||
else if (getDialect() == HSQLDB) {
|
||||
assertEquals(tables + 11, schema.getTables().size());
|
||||
}
|
||||
|
||||
else {
|
||||
assertEquals(tables + 1, schema.getTables().size());
|
||||
}
|
||||
|
||||
if (cUAddressType() == null) {
|
||||
assertEquals(0, schema.getUDTs().size());
|
||||
}
|
||||
// [#643] The U_INVALID types are only available in Oracle
|
||||
// [#799] The member procedure UDT's too
|
||||
else if (getDialect() == ORACLE) {
|
||||
assertEquals(7, schema.getUDTs().size());
|
||||
}
|
||||
else {
|
||||
assertEquals(2, schema.getUDTs().size());
|
||||
}
|
||||
}
|
||||
|
||||
// Test correct source code generation for identity columns
|
||||
assertNull(TAuthor().getIdentity());
|
||||
assertNull(TBook().getIdentity());
|
||||
|
||||
if (TIdentity() != null || TIdentityPK() != null) {
|
||||
if (TIdentity() != null) {
|
||||
assertEquals(TIdentity(), TIdentity().getIdentity().getTable());
|
||||
assertEquals(TIdentity_ID(), TIdentity().getIdentity().getField());
|
||||
}
|
||||
|
||||
if (TIdentityPK() != null) {
|
||||
assertEquals(TIdentityPK(), TIdentityPK().getIdentity().getTable());
|
||||
assertEquals(TIdentityPK_ID(), TIdentityPK().getIdentity().getField());
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("SKIPPING", "Identity tests");
|
||||
}
|
||||
|
||||
// Test correct source code generation for relations
|
||||
assertNotNull(TAuthor().getMainKey());
|
||||
assertNotNull(TAuthor().getKeys());
|
||||
assertTrue(TAuthor().getKeys().contains(TAuthor().getMainKey()));
|
||||
assertEquals(1, TAuthor().getKeys().size());
|
||||
assertEquals(1, TAuthor().getMainKey().getFields().size());
|
||||
assertEquals(TAuthor_ID(), TAuthor().getMainKey().getFields().get(0));
|
||||
assertEquals(Record1.class, TAuthor().getRecordType().getMethod("key").getReturnType());
|
||||
assertTrue(TAuthor().getRecordType().getMethod("key").toGenericString().contains("org.jooq.Record1<java.lang.Integer>"));
|
||||
assertEquals(Record2.class, TBookToBookStore().getRecordType().getMethod("key").getReturnType());
|
||||
assertTrue(TBookToBookStore().getRecordType().getMethod("key").toGenericString().contains("org.jooq.Record2<java.lang.String, java.lang.Integer>"));
|
||||
|
||||
if (supportsReferences()) {
|
||||
|
||||
// Without aliasing
|
||||
assertEquals(0, TAuthor().getReferences().size());
|
||||
assertEquals(2, TAuthor().getMainKey().getReferences().size());
|
||||
assertEquals(TBook(), TAuthor().getMainKey().getReferences().get(0).getTable());
|
||||
assertEquals(TBook(), TAuthor().getMainKey().getReferences().get(1).getTable());
|
||||
assertEquals(Arrays.asList(), TAuthor().getReferencesTo(TBook()));
|
||||
assertTrue(TBook().getReferences().containsAll(TAuthor().getReferencesFrom(TBook())));
|
||||
assertTrue(TBook().getReferences().containsAll(TBook().getReferencesFrom(TAuthor())));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), TAuthor().getReferencesFrom(TBook()));
|
||||
|
||||
// [#1460] With aliasing
|
||||
Table<A> a = TAuthor().as("a");
|
||||
Table<B> b = TBook().as("b");
|
||||
|
||||
assertEquals(0, a.getReferences().size());
|
||||
assertEquals(Arrays.asList(), a.getReferencesTo(b));
|
||||
|
||||
// This should work with both types of meta-models (static, non-static)
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), TBook().getReferencesTo(a));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), b.getReferencesTo(a));
|
||||
assertEquals(TBook().getReferencesTo(TAuthor()), b.getReferencesTo(TAuthor()));
|
||||
|
||||
// Only with a non-static meta model
|
||||
if (a instanceof UpdatableTable && b instanceof UpdatableTable) {
|
||||
UpdatableTable<A> ua = (UpdatableTable<A>) a;
|
||||
UpdatableTable<B> ub = (UpdatableTable<B>) b;
|
||||
|
||||
assertEquals(2, ua.getMainKey().getReferences().size());
|
||||
assertEquals(TBook(), ua.getMainKey().getReferences().get(0).getTable());
|
||||
assertEquals(TBook(), ua.getMainKey().getReferences().get(1).getTable());
|
||||
assertTrue(b.getReferences().containsAll(ua.getReferencesFrom(b)));
|
||||
assertTrue(b.getReferences().containsAll(ub.getReferencesFrom(a)));
|
||||
assertEquals(b.getReferencesTo(a), ua.getReferencesFrom(b));
|
||||
assertEquals(TBook().getReferencesTo(a), ua.getReferencesFrom(b));
|
||||
assertEquals(b.getReferencesTo(a), TAuthor().getReferencesFrom(b));
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.info("SKIPPING", "References tests");
|
||||
}
|
||||
|
||||
for (Field<?> field : T639().getFields()) {
|
||||
if ("BYTE".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Byte.class, field.getType());
|
||||
assertEquals(SQLDataType.TINYINT, field.getDataType());
|
||||
}
|
||||
else if ("SHORT".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Short.class, field.getType());
|
||||
assertEquals(SQLDataType.SMALLINT, field.getDataType());
|
||||
}
|
||||
else if ("INTEGER".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Integer.class, field.getType());
|
||||
assertEquals(SQLDataType.INTEGER, field.getDataType());
|
||||
}
|
||||
else if ("LONG".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Long.class, field.getType());
|
||||
assertEquals(SQLDataType.BIGINT, field.getDataType());
|
||||
}
|
||||
else if ("BYTE_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Byte.class, field.getType());
|
||||
assertEquals(SQLDataType.TINYINT, field.getDataType());
|
||||
}
|
||||
else if ("SHORT_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Short.class, field.getType());
|
||||
assertEquals(SQLDataType.SMALLINT, field.getDataType());
|
||||
}
|
||||
else if ("INTEGER_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Integer.class, field.getType());
|
||||
assertEquals(SQLDataType.INTEGER, field.getDataType());
|
||||
}
|
||||
else if ("LONG_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Long.class, field.getType());
|
||||
assertEquals(SQLDataType.BIGINT, field.getDataType());
|
||||
}
|
||||
else if ("BIG_INTEGER".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(BigInteger.class, field.getType());
|
||||
assertEquals(SQLDataType.DECIMAL_INTEGER, field.getDataType());
|
||||
}
|
||||
|
||||
// [#745] TODO: Unify distinction between NUMERIC and DECIMAL
|
||||
else if ("BIG_DECIMAL".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.ORACLE
|
||||
&& getDialect() != SQLDialect.POSTGRES
|
||||
&& getDialect() != SQLDialect.SQLITE
|
||||
&& getDialect() != SQLDialect.SQLSERVER) {
|
||||
|
||||
assertEquals(BigDecimal.class, field.getType());
|
||||
assertEquals(SQLDataType.DECIMAL, field.getDataType());
|
||||
}
|
||||
else if ("BIG_DECIMAL".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(BigDecimal.class, field.getType());
|
||||
assertEquals(SQLDataType.NUMERIC, field.getDataType());
|
||||
}
|
||||
|
||||
// [#746] TODO: Interestingly, HSQLDB and MySQL match REAL with DOUBLE.
|
||||
// There is no matching type for java.lang.Float...
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.HSQLDB
|
||||
&& getDialect() != SQLDialect.MYSQL
|
||||
&& getDialect() != SQLDialect.SYBASE) {
|
||||
|
||||
assertEquals(Float.class, field.getType());
|
||||
assertEquals(SQLDataType.REAL, field.getDataType());
|
||||
}
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.MYSQL
|
||||
&& getDialect() != SQLDialect.SYBASE) {
|
||||
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.DOUBLE, field.getDataType());
|
||||
}
|
||||
else if ("FLOAT".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.FLOAT, field.getDataType());
|
||||
}
|
||||
|
||||
// [#746] TODO: Fix this, too
|
||||
else if ("DOUBLE".equalsIgnoreCase(field.getName())
|
||||
&& getDialect() != SQLDialect.SQLSERVER
|
||||
&& getDialect() != SQLDialect.ASE) {
|
||||
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.DOUBLE, field.getDataType());
|
||||
}
|
||||
else if ("DOUBLE".equalsIgnoreCase(field.getName())) {
|
||||
assertEquals(Double.class, field.getType());
|
||||
assertEquals(SQLDataType.FLOAT, field.getDataType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaData() throws Exception {
|
||||
Meta meta = create().meta();
|
||||
|
||||
if (schema() != null) {
|
||||
|
||||
// The schema returned from meta should be equal to the
|
||||
// generated test schema
|
||||
List<Schema> metaSchemas = meta.getSchemas();
|
||||
assertTrue(metaSchemas.contains(schema()));
|
||||
|
||||
Schema metaSchema = metaSchemas.get(metaSchemas.indexOf(schema()));
|
||||
assertEquals(schema(), metaSchema);
|
||||
|
||||
// The schema returned from meta should contain at least all the
|
||||
// generated test tables
|
||||
List<Table<?>> metaTables = metaSchema.getTables();
|
||||
assertTrue(metaTables.containsAll(schema().getTables()));
|
||||
assertTrue(metaTables.size() >= schema().getTables().size());
|
||||
|
||||
metaTableChecks(metaTables);
|
||||
}
|
||||
|
||||
// Some sample checks about tables returned from meta
|
||||
List<Table<?>> metaTables = meta.getTables();
|
||||
assertTrue(metaTables.contains(TAuthor()));
|
||||
assertTrue(metaTables.contains(TBook()));
|
||||
assertTrue(metaTables.contains(TBookStore()));
|
||||
assertTrue(metaTables.contains(TBookToBookStore()));
|
||||
assertTrue(metaTables.contains(VAuthor()));
|
||||
assertTrue(metaTables.contains(VBook()));
|
||||
assertTrue(metaTables.contains(VLibrary()));
|
||||
|
||||
metaTableChecks(metaTables);
|
||||
}
|
||||
|
||||
private void metaTableChecks(Collection<? extends Table<?>> metaTables) {
|
||||
for (Table<?> metaTable : metaTables) {
|
||||
Table<?> generatedTable = schema().getTable(metaTable.getName());
|
||||
|
||||
// Every table returned from meta should have a corresponding
|
||||
// table by name in the generated test tables
|
||||
if (generatedTable != null) {
|
||||
assertNotNull(generatedTable);
|
||||
assertEquals(metaTable, generatedTable);
|
||||
|
||||
// Check if fields match, as well
|
||||
List<Field<?>> metaFields = metaTable.getFields();
|
||||
assertTrue(metaFields.containsAll(generatedTable.getFields()));
|
||||
|
||||
// Check if relations are correctly loaded (and typed) as well
|
||||
// [#1977] Fix this, once the "main key" concept has been removed
|
||||
if (generatedTable instanceof UpdatableTable && metaTable instanceof UpdatableTable) {
|
||||
UpdatableTable<?> generatedUTable = (UpdatableTable<?>) generatedTable;
|
||||
UpdatableTable<?> metaUTable = (UpdatableTable<?>) metaTable;
|
||||
|
||||
// [#1977] TODO: Add key checks
|
||||
}
|
||||
|
||||
// Only truly updatable tables should be "Updatable"
|
||||
else {
|
||||
assertFalse(metaTable instanceof UpdatableTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,6 +110,7 @@ import org.jooq.test._.testcases.GroupByTests;
|
||||
import org.jooq.test._.testcases.InsertUpdateTests;
|
||||
import org.jooq.test._.testcases.JoinTests;
|
||||
import org.jooq.test._.testcases.LoaderTests;
|
||||
import org.jooq.test._.testcases.MetaDataTests;
|
||||
import org.jooq.test._.testcases.OrderByTests;
|
||||
import org.jooq.test._.testcases.PlainSQLTests;
|
||||
import org.jooq.test._.testcases.PredicateTests;
|
||||
@ -869,7 +870,12 @@ public abstract class jOOQAbstractTest<
|
||||
|
||||
@Test
|
||||
public void testMetaModel() throws Exception {
|
||||
new GeneralTests(this).testMetaModel();
|
||||
new MetaDataTests(this).testMetaModel();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetaData() throws Exception {
|
||||
new MetaDataTests(this).testMetaData();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
74
jOOQ/src/main/java/org/jooq/Meta.java
Normal file
74
jOOQ/src/main/java/org/jooq/Meta.java
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.Executor;
|
||||
|
||||
/**
|
||||
* A wrapping object for {@link DatabaseMetaData}
|
||||
* <p>
|
||||
* This object can be obtained through {@link Executor#meta()} in order to
|
||||
* provide convenient access to your database meta data. This abstraction has
|
||||
* two purposes:
|
||||
* <p>
|
||||
* <ol>
|
||||
* <li>To increase API convenience, as no checked {@link SQLException} is
|
||||
* thrown, only the unchecked {@link DataAccessException}</li>
|
||||
* <li>To increase API convenience, as the returned objects are always jOOQ
|
||||
* objects, not JDBC {@link ResultSet} objects with hard-to-remember API
|
||||
* constraints</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public interface Meta {
|
||||
|
||||
/**
|
||||
* Get all schema objects from the underlying {@link DatabaseMetaData}
|
||||
*/
|
||||
List<Schema> getSchemas();
|
||||
|
||||
/**
|
||||
* Get all table objects from the underlying {@link DatabaseMetaData}
|
||||
*/
|
||||
List<Table<?>> getTables();
|
||||
}
|
||||
213
jOOQ/src/main/java/org/jooq/impl/MetaImpl.java
Normal file
213
jOOQ/src/main/java/org/jooq/impl/MetaImpl.java
Normal file
@ -0,0 +1,213 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2012, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* . Neither the name "jOOQ" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.Meta;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Schema;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableField;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.UpdatableTable;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
class MetaImpl implements Meta {
|
||||
|
||||
private final Executor executor;
|
||||
private transient DatabaseMetaData meta;
|
||||
|
||||
MetaImpl(Executor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
private final DatabaseMetaData meta() {
|
||||
if (meta == null) {
|
||||
try {
|
||||
meta = executor.getConnection().getMetaData();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new DataAccessException("Error while accessing DatabaseMetaData", e);
|
||||
}
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Schema> getSchemas() {
|
||||
try {
|
||||
List<Schema> result = new ArrayList<Schema>();
|
||||
Result<Record> schemas = executor.fetch(meta().getSchemas());
|
||||
|
||||
for (String name : schemas.getValues(0, String.class)) {
|
||||
result.add(new MetaSchema(name));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new DataAccessException("Error while accessing DatabaseMetaData", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Table<?>> getTables() {
|
||||
List<Table<?>> result = new ArrayList<Table<?>>();
|
||||
|
||||
for (Schema schema : getSchemas()) {
|
||||
result.addAll(schema.getTables());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class MetaSchema extends SchemaImpl {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -2621899850912554198L;
|
||||
|
||||
MetaSchema(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Table<?>> getTables() {
|
||||
try {
|
||||
List<Table<?>> result = new ArrayList<Table<?>>();
|
||||
Result<Record> tables = executor.fetch(meta().getTables(null, getName(), "%", null));
|
||||
|
||||
for (Record table : tables) {
|
||||
String catalog = table.getValue(0, String.class);
|
||||
String schema = table.getValue(1, String.class);
|
||||
String name = table.getValue(2, String.class);
|
||||
|
||||
Result<Record> pkColumns = executor.fetch(meta().getPrimaryKeys(catalog, schema, name))
|
||||
.sortAsc("KEY_SEQ");
|
||||
|
||||
if (pkColumns.size() == 0) {
|
||||
result.add(new MetaTable(name, this));
|
||||
}
|
||||
else {
|
||||
result.add(new MetaUpdatableTable(name, this));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new DataAccessException("Error while accessing DatabaseMetaData", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MetaTable extends TableImpl<Record> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 4843841667753000233L;
|
||||
|
||||
MetaTable(String name, Schema schema) {
|
||||
super(name, schema);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
private final void init() {
|
||||
try {
|
||||
Result<Record> columns = executor.fetch(meta().getColumns(null, getSchema().getName(), getName(), "%"));
|
||||
|
||||
for (Record column : columns) {
|
||||
createField(column.getValue("COLUMN_NAME", String.class), SQLDataType.OTHER, this);
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new DataAccessException("Error while accessing DatabaseMetaData", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MetaUpdatableTable extends MetaTable implements UpdatableTable<Record> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = -4555457095396846609L;
|
||||
|
||||
MetaUpdatableTable(String name, Schema schema) {
|
||||
super(name, schema);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final UniqueKey<Record> getMainKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<UniqueKey<Record>> getKeys() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <O extends Record> List<ForeignKey<O, Record>> getReferencesFrom(Table<O> other) {
|
||||
return other.getReferencesTo(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TableField<Record, ? extends Number> getRecordVersion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TableField<Record, ? extends Date> getRecordTimestamp() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user