[#1801] Add Table.as(String, String...) to allow for creating a
table alias with aliased fields - Added API and tests that work for Postgres
This commit is contained in:
parent
ae7aad93d5
commit
48b25650b4
171
jOOQ-test/src/org/jooq/test/_/testcases/AliasTests.java
Normal file
171
jOOQ-test/src/org/jooq/test/_/testcases/AliasTests.java
Normal file
@ -0,0 +1,171 @@
|
||||
/**
|
||||
* 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.assertNull;
|
||||
import static org.jooq.impl.Factory.select;
|
||||
import static org.jooq.impl.Factory.selectOne;
|
||||
import static org.jooq.impl.Factory.table;
|
||||
import static org.jooq.impl.Factory.two;
|
||||
import static org.jooq.impl.Factory.zero;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
import org.jooq.Record3;
|
||||
import org.jooq.Record6;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class AliasTests<
|
||||
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 AliasTests(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 testAliasingSimple() throws Exception {
|
||||
Table<B> b = TBook().as("b");
|
||||
Field<Integer> b_ID = b.getField(TBook_ID());
|
||||
|
||||
List<Integer> ids = create().select(b_ID).from(b).orderBy(b_ID).fetch(b_ID);
|
||||
assertEquals(4, ids.size());
|
||||
assertEquals(BOOK_IDS, ids);
|
||||
|
||||
Result<Record> books = create().select().from(b).orderBy(b_ID).fetch();
|
||||
assertEquals(4, books.size());
|
||||
assertEquals(BOOK_IDS, books.getValues(b_ID));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testAliasingTablesAndFields() throws Exception {
|
||||
Table<B2S> b2s = TBookToBookStore().as("b2s", "b2s_1", "b2s_2", "b2s_3");
|
||||
Field<String> b2s1 = (Field<String>) b2s.getField(0);
|
||||
Field<Integer> b2s2 = (Field<Integer>) b2s.getField(1);
|
||||
Field<Integer> b2s3 = (Field<Integer>) b2s.getField(2);
|
||||
|
||||
assertEquals("b2s", b2s.getName());
|
||||
assertEquals("b2s_1", b2s1.getName());
|
||||
assertEquals("b2s_2", b2s2.getName());
|
||||
assertEquals("b2s_3", b2s3.getName());
|
||||
|
||||
assertEquals("b2s_1", b2s.getField("b2s_1").getName());
|
||||
assertEquals("b2s_2", b2s.getField("b2s_2").getName());
|
||||
assertEquals("b2s_3", b2s.getField("b2s_3").getName());
|
||||
|
||||
// TODO: What happens with typed records?
|
||||
// B2S record1 = create().selectFrom(b2s).where(b2s3.eq(2)).fetchOne();
|
||||
// Record record1 = create().select().from(b2s).where(b2s3.eq(2)).fetchOne();
|
||||
Record record1 = create()
|
||||
.select(b2s1, b2s2, b2s3)
|
||||
.from(b2s)
|
||||
.where(b2s3.eq(2))
|
||||
.fetchOne();
|
||||
|
||||
assertEquals("Ex Libris", record1.getValue("b2s_1"));
|
||||
assertEquals("Ex Libris", record1.getValue(b2s1));
|
||||
assertEquals(3, record1.getValue("b2s_2"));
|
||||
assertEquals(3, (int) record1.getValue(b2s2));
|
||||
assertEquals(2, record1.getValue("b2s_3"));
|
||||
assertEquals(2, (int) record1.getValue(b2s3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAliasingSelectAndFields() throws Exception {
|
||||
Record r1 = create().select().from(table(selectOne()).as("t", "v")).fetchOne();
|
||||
assertEquals("v", r1.getField(0).getName());
|
||||
assertEquals("v", r1.getField("v").getName());
|
||||
assertEquals(1, r1.getValue(0));
|
||||
assertEquals(1, r1.getValue("v"));
|
||||
assertEquals(1, r1.getValue(r1.getField(0)));
|
||||
|
||||
Record r2 = create()
|
||||
.select()
|
||||
.from(table(selectOne()).as("t1", "v1"))
|
||||
.crossJoin(table(select(two(), zero())).as("t2", "v2a", "v2b"))
|
||||
.leftOuterJoin(table(selectOne()).as("t3", "v3"))
|
||||
.on("1 = 0")
|
||||
.fetchOne();
|
||||
assertEquals("v1", r2.getField(0).getName());
|
||||
assertEquals("v2a", r2.getField(1).getName());
|
||||
assertEquals("v2b", r2.getField(2).getName());
|
||||
assertEquals("v3", r2.getField(3).getName());
|
||||
assertEquals("v1", r2.getField("v1").getName());
|
||||
assertEquals("v2a", r2.getField("v2a").getName());
|
||||
assertEquals("v2b", r2.getField("v2b").getName());
|
||||
assertEquals("v3", r2.getField("v3").getName());
|
||||
|
||||
assertEquals(1, r2.getValue(0));
|
||||
assertEquals(1, r2.getValue("v1"));
|
||||
assertEquals(2, r2.getValue(1));
|
||||
assertEquals(2, r2.getValue("v2a"));
|
||||
assertEquals(0, r2.getValue(2));
|
||||
assertEquals(0, r2.getValue("v2b"));
|
||||
assertNull(r2.getValue(3));
|
||||
assertNull(r2.getValue("v3"));
|
||||
}
|
||||
}
|
||||
@ -36,7 +36,6 @@
|
||||
package org.jooq.test;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static org.jooq.SQLDialect.CUBRID;
|
||||
import static org.jooq.SQLDialect.FIREBIRD;
|
||||
import static org.jooq.tools.reflect.Reflect.on;
|
||||
@ -97,6 +96,7 @@ import org.jooq.test._.converters.Boolean_YES_NO_UC;
|
||||
import org.jooq.test._.converters.Boolean_YN_LC;
|
||||
import org.jooq.test._.converters.Boolean_YN_UC;
|
||||
import org.jooq.test._.testcases.AggregateWindowFunctionTests;
|
||||
import org.jooq.test._.testcases.AliasTests;
|
||||
import org.jooq.test._.testcases.BatchTests;
|
||||
import org.jooq.test._.testcases.BenchmarkTests;
|
||||
import org.jooq.test._.testcases.CRUDTests;
|
||||
@ -1540,17 +1540,18 @@ public abstract class jOOQAbstractTest<
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAliasing() throws Exception {
|
||||
Table<B> b = TBook().as("b");
|
||||
Field<Integer> b_ID = b.getField(TBook_ID());
|
||||
public void testAliasingSimple() throws Exception {
|
||||
new AliasTests(this).testAliasingSimple();
|
||||
}
|
||||
|
||||
List<Integer> ids = create().select(b_ID).from(b).orderBy(b_ID).fetch(b_ID);
|
||||
assertEquals(4, ids.size());
|
||||
assertEquals(BOOK_IDS, ids);
|
||||
@Test
|
||||
public void testAliasingTablesAndFields() throws Exception {
|
||||
new AliasTests(this).testAliasingTablesAndFields();
|
||||
}
|
||||
|
||||
Result<Record> books = create().select().from(b).orderBy(b_ID).fetch();
|
||||
assertEquals(4, books.size());
|
||||
assertEquals(BOOK_IDS, books.getValues(b_ID));
|
||||
@Test
|
||||
public void testAliasingSelectAndFields() throws Exception {
|
||||
new AliasTests(this).testAliasingSelectAndFields();
|
||||
}
|
||||
|
||||
// @Test // TODO [#579] re-enable this test when fixing this bug
|
||||
|
||||
@ -92,6 +92,22 @@ public interface Table<R extends Record> extends FieldProvider, TableLike<R> {
|
||||
@Support
|
||||
Table<R> as(String alias);
|
||||
|
||||
/**
|
||||
* Create an alias for this table and its fields
|
||||
* <p>
|
||||
* Note that the case-sensitivity of the returned table depends on
|
||||
* {@link Settings#getRenderNameStyle()}. By default, table aliases are
|
||||
* quoted, and thus case-sensitive!
|
||||
*
|
||||
* @param alias The alias name
|
||||
* @param fieldAliases The field aliases. Excess aliases are ignored,
|
||||
* missing aliases will be substituted by this table's field
|
||||
* names.
|
||||
* @return The table alias
|
||||
*/
|
||||
@Support
|
||||
Table<R> as(String alias, String... fieldAliases);
|
||||
|
||||
/**
|
||||
* Retrieve the table's <code>IDENTITY</code> information, if available.
|
||||
* <p>
|
||||
|
||||
@ -64,4 +64,21 @@ public interface TableLike<R extends Record> extends QueryPart {
|
||||
* quoted, and thus case-sensitive!
|
||||
*/
|
||||
Table<R> asTable(String alias);
|
||||
|
||||
/**
|
||||
* The underlying aliased table representation of this object
|
||||
* <p>
|
||||
* This method is useful for things like
|
||||
* <code><pre>
|
||||
* SELECT alias.fieldAlias1, alias.fieldAlias2
|
||||
* FROM (
|
||||
* SELECT * FROM x WHERE x.a = '1'
|
||||
* ) AS alias(fieldAlias1, fieldAlias2)
|
||||
* WHERE ... </code>
|
||||
* <p>
|
||||
* Note that the case-sensitivity of the returned table depends on
|
||||
* {@link Settings#getRenderNameStyle()}. By default, table aliases are
|
||||
* quoted, and thus case-sensitive!
|
||||
*/
|
||||
Table<R> asTable(String alias, String... fieldAliases);
|
||||
}
|
||||
|
||||
@ -136,6 +136,11 @@ abstract class AbstractSelect<R extends Record> extends AbstractResultQuery<R> i
|
||||
return new SelectQueryAsTable<R>(this).as(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> asTable(String alias, String... fieldAliases) {
|
||||
return new SelectQueryAsTable<R>(this).as(alias, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final List<Field<?>> getFields(ResultSetMetaData meta) {
|
||||
|
||||
|
||||
@ -97,6 +97,11 @@ abstract class AbstractTable<R extends Record> extends AbstractFieldProviderQuer
|
||||
return as(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> asTable(String alias, String... fieldAliases) {
|
||||
return as(alias, fieldAliases);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// XXX: Table API
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@ -55,15 +55,25 @@ class Alias<Q extends QueryPart> extends AbstractQueryPart {
|
||||
private static final long serialVersionUID = -2456848365524191614L;
|
||||
private final Q wrapped;
|
||||
private final String alias;
|
||||
private final String[] fieldAliases;
|
||||
private final boolean wrapInParentheses;
|
||||
|
||||
Alias(Q aliasProvider, String alias) {
|
||||
this(aliasProvider, alias, false);
|
||||
Alias(Q wrapped, String alias) {
|
||||
this(wrapped, alias, null, false);
|
||||
}
|
||||
|
||||
Alias(Q wrapped, String alias, boolean wrapInParentheses) {
|
||||
this(wrapped, alias, null, wrapInParentheses);
|
||||
}
|
||||
|
||||
Alias(Q wrapped, String alias, String[] fieldAliases) {
|
||||
this(wrapped, alias, fieldAliases, false);
|
||||
}
|
||||
|
||||
Alias(Q wrapped, String alias, String[] fieldAliases, boolean wrapInParentheses) {
|
||||
this.wrapped = wrapped;
|
||||
this.alias = alias;
|
||||
this.fieldAliases = fieldAliases;
|
||||
this.wrapInParentheses = wrapInParentheses;
|
||||
}
|
||||
|
||||
@ -92,29 +102,47 @@ class Alias<Q extends QueryPart> extends AbstractQueryPart {
|
||||
context.sql(" ");
|
||||
context.literal(alias);
|
||||
|
||||
// [#756] If the aliased object is an anonymous table (usually an
|
||||
// unnested array), then field names must be part of the alias
|
||||
// declaration. For example:
|
||||
//
|
||||
// SELECT t.column_value FROM UNNEST(ARRAY[1, 2]) AS t(column_value)
|
||||
// [#1801] Add field aliases to the table alias, if applicable
|
||||
if (fieldAliases != null) {
|
||||
String separator = "";
|
||||
|
||||
// TODO: Is this still needed?
|
||||
context.sql("(");
|
||||
|
||||
switch (context.getDialect()) {
|
||||
case HSQLDB:
|
||||
case POSTGRES: {
|
||||
// The javac compiler doesn't like casting of generics
|
||||
Object o = wrapped;
|
||||
for (int i = 0; i < fieldAliases.length; i++) {
|
||||
context.sql(separator);
|
||||
context.literal(fieldAliases[i]);
|
||||
|
||||
if (context.declareTables() && o instanceof ArrayTable) {
|
||||
ArrayTable table = (ArrayTable) o;
|
||||
separator = ", ";
|
||||
}
|
||||
|
||||
context.sql("(");
|
||||
Utils.fieldNames(context, table.getFields());
|
||||
context.sql(")");
|
||||
context.sql(")");
|
||||
}
|
||||
|
||||
else {
|
||||
// [#756] If the aliased object is an anonymous table (usually an
|
||||
// unnested array), then field names must be part of the alias
|
||||
// declaration. For example:
|
||||
//
|
||||
// SELECT t.column_value FROM UNNEST(ARRAY[1, 2]) AS t(column_value)
|
||||
|
||||
// TODO: Is this still needed?
|
||||
|
||||
switch (context.getDialect()) {
|
||||
case HSQLDB:
|
||||
case POSTGRES: {
|
||||
// The javac compiler doesn't like casting of generics
|
||||
Object o = wrapped;
|
||||
|
||||
if (context.declareTables() && o instanceof ArrayTable) {
|
||||
ArrayTable table = (ArrayTable) o;
|
||||
|
||||
context.sql("(");
|
||||
Utils.fieldNames(context, table.getFields());
|
||||
context.sql(")");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,6 +123,12 @@ class ArrayTable extends AbstractTable<Record> {
|
||||
}
|
||||
}
|
||||
|
||||
ArrayTable(Field<?> array, String alias, String[] fieldAliases) {
|
||||
super(alias);
|
||||
|
||||
throw new UnsupportedOperationException("This constructor is not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<? extends Record> getRecordType() {
|
||||
return RecordImpl.class;
|
||||
@ -133,6 +139,11 @@ class ArrayTable extends AbstractTable<Record> {
|
||||
return new ArrayTable(array, as);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String as, String... fieldAliases) {
|
||||
return new ArrayTable(array, as, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean declaresTables() {
|
||||
|
||||
@ -254,22 +265,27 @@ class ArrayTable extends AbstractTable<Record> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Record> getRecordType() {
|
||||
public final Class<? extends Record> getRecordType() {
|
||||
return RecordImpl.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Table<Record> as(String as) {
|
||||
public final Table<Record> as(String as) {
|
||||
return new TableAlias<Record>(this, as);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(BindContext context) throws DataAccessException {
|
||||
public final Table<Record> as(String as, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, as, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bind(BindContext context) throws DataAccessException {
|
||||
context.bind(array);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FieldList getFieldList() {
|
||||
protected final FieldList getFieldList() {
|
||||
return ArrayTable.this.getFieldList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,20 +64,26 @@ class ArrayTableSimulation extends AbstractTable<Record> {
|
||||
private final Object[] array;
|
||||
private final FieldList field;
|
||||
private final String alias;
|
||||
private final String fieldAlias;
|
||||
|
||||
private transient Table<Record> table;
|
||||
|
||||
ArrayTableSimulation(Object[] array) {
|
||||
this(array, "array_table");
|
||||
this(array, "array_table", null);
|
||||
}
|
||||
|
||||
ArrayTableSimulation(Object[] array, String alias) {
|
||||
this(array, alias, null);
|
||||
}
|
||||
|
||||
ArrayTableSimulation(Object[] array, String alias, String fieldAlias) {
|
||||
super(alias);
|
||||
|
||||
this.array = array;
|
||||
this.field = new FieldList();
|
||||
this.alias = alias;
|
||||
this.field.add(fieldByName(Factory.getDataType(array.getClass().getComponentType()), alias, "COLUMN_VALUE"));
|
||||
this.fieldAlias = fieldAlias == null ? "COLUMN_VALUE" : fieldAlias;
|
||||
this.field.add(fieldByName(Factory.getDataType(array.getClass().getComponentType()), alias, this.fieldAlias));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,6 +96,18 @@ class ArrayTableSimulation extends AbstractTable<Record> {
|
||||
return new ArrayTableSimulation(array, as);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String as, String... fieldAliases) {
|
||||
if (fieldAliases == null) {
|
||||
return new ArrayTableSimulation(array, as);
|
||||
}
|
||||
else if (fieldAliases.length == 1) {
|
||||
return new ArrayTableSimulation(array, as, fieldAliases[0]);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Array table simulations can only have a single field alias");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean declaresTables() {
|
||||
|
||||
|
||||
@ -178,6 +178,11 @@ implements
|
||||
return new TableAlias<Record>(this, alias, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final FieldList getFieldList() {
|
||||
return new FieldList();
|
||||
|
||||
@ -63,6 +63,11 @@ class Dual extends AbstractTable<Record> {
|
||||
return new TableAlias<Record>(this, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
switch (context.getDialect()) {
|
||||
|
||||
@ -71,6 +71,11 @@ class FunctionTable<R extends Record> extends AbstractTable<R> {
|
||||
return new TableAlias<R>(new FunctionTable<R>(function), as);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> as(String as, String... fieldAliases) {
|
||||
return new TableAlias<R>(new FunctionTable<R>(function), as, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
switch (context.getDialect()) {
|
||||
|
||||
@ -278,6 +278,11 @@ class JoinTable extends AbstractTable<Record> implements TableOptionalOnStep, Ta
|
||||
return new TableAlias<Record>(this, alias, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<? extends Record> getRecordType() {
|
||||
return RecordImpl.class;
|
||||
|
||||
@ -51,6 +51,7 @@ import org.jooq.QueryPart;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.RenderContext;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.Support;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
|
||||
@ -266,15 +267,21 @@ implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Record> getRecordType() {
|
||||
public final Class<? extends Record> getRecordType() {
|
||||
return RecordImpl.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Table<Record> as(String as) {
|
||||
public final Table<Record> as(String as) {
|
||||
return new TableAlias<Record>(this, as);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Support
|
||||
public final Table<Record> as(String as, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, as, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FieldList getFieldList() {
|
||||
return Pivot.this.getFieldList();
|
||||
@ -304,6 +311,11 @@ implements
|
||||
return new TableAlias<Record>(this, alias, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final FieldList getFieldList() {
|
||||
return new FieldList();
|
||||
|
||||
@ -89,6 +89,11 @@ class QualifiedTable extends AbstractTable<Record> {
|
||||
return new TableAlias<Record>(this, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final FieldList getFieldList() {
|
||||
return new FieldList();
|
||||
|
||||
@ -74,6 +74,11 @@ class SQLTable extends AbstractTable<Record> {
|
||||
return new TableAlias<Record>(this, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<Record> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<Record>(this, alias, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
Utils.renderAndBind(context, null, sql, substitutes);
|
||||
|
||||
@ -1217,6 +1217,11 @@ class SelectImpl<R extends Record> extends AbstractDelegatingQuery<Select<R>> im
|
||||
return getDelegate().asTable(alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> asTable(String alias, String... fieldAliases) {
|
||||
return getDelegate().asTable(alias, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> Field<T> asField() {
|
||||
return getDelegate().asField();
|
||||
|
||||
@ -62,6 +62,11 @@ class SelectQueryAsTable<R extends Record> extends AbstractTable<R> {
|
||||
return new TableAlias<R>(this, alias, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<R>(this, alias, fieldAliases, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final FieldList getFieldList() {
|
||||
return new FieldList(query.getSelect());
|
||||
|
||||
@ -53,16 +53,53 @@ class TableAlias<R extends Record> extends AbstractTable<R> {
|
||||
private static final long serialVersionUID = -8417114874567698325L;
|
||||
|
||||
private final Alias<Table<R>> alias;
|
||||
private FieldList aliasedFields;
|
||||
private final FieldList aliasedFields;
|
||||
|
||||
TableAlias(Table<R> table, String alias) {
|
||||
this(table, alias, false);
|
||||
this(table, alias, null, false);
|
||||
}
|
||||
|
||||
TableAlias(Table<R> table, String alias, boolean wrapInParentheses) {
|
||||
this(table, alias, null, wrapInParentheses);
|
||||
}
|
||||
|
||||
TableAlias(Table<R> table, String alias, String[] fieldAliases) {
|
||||
this(table, alias, fieldAliases, false);
|
||||
}
|
||||
|
||||
TableAlias(Table<R> table, String alias, String[] fieldAliases, boolean wrapInParentheses) {
|
||||
super(alias, table.getSchema());
|
||||
|
||||
this.alias = new Alias<Table<R>>(table, alias, wrapInParentheses);
|
||||
this.alias = new Alias<Table<R>>(table, alias, fieldAliases, wrapInParentheses);
|
||||
this.aliasedFields = new FieldList();
|
||||
|
||||
registerFields(fieldAliases);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register fields for this table alias
|
||||
*/
|
||||
private final void registerFields(String[] fieldAliases) {
|
||||
List<Field<?>> fields = this.alias.wrapped().getFields();
|
||||
int size = fields.size();
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
Field<?> field = fields.get(i);
|
||||
String name = field.getName();
|
||||
|
||||
if (fieldAliases != null && fieldAliases.length > i) {
|
||||
name = fieldAliases[i];
|
||||
}
|
||||
|
||||
registerTableField(field, name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a field for this table alias
|
||||
*/
|
||||
private final <T> void registerTableField(Field<T> field, String name) {
|
||||
aliasedFields.add(new TableFieldImpl<R, T>(name, field.getDataType(), this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,31 +133,21 @@ class TableAlias<R extends Record> extends AbstractTable<R> {
|
||||
return alias.wrapped().as(as);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> as(String as, String... fieldAliases) {
|
||||
return alias.wrapped().as(as, fieldAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean declaresTables() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FieldList getFieldList() {
|
||||
if (aliasedFields == null) {
|
||||
aliasedFields = new FieldList();
|
||||
|
||||
for (Field<?> field : alias.wrapped().getFields()) {
|
||||
registerTableField(field);
|
||||
}
|
||||
}
|
||||
|
||||
protected final FieldList getFieldList() {
|
||||
return aliasedFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a field for this table alias
|
||||
*/
|
||||
private <T> void registerTableField(Field<T> field) {
|
||||
aliasedFields.add(new TableFieldImpl<R, T>(field.getName(), field.getDataType(), this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends R> getRecordType() {
|
||||
return alias.wrapped().getRecordType();
|
||||
|
||||
@ -57,24 +57,32 @@ public class TableImpl<R extends Record> extends AbstractTable<R> {
|
||||
private final Alias<Table<R>> alias;
|
||||
|
||||
public TableImpl(String name) {
|
||||
this(name, null, null);
|
||||
this(name, null, null, null);
|
||||
}
|
||||
|
||||
public TableImpl(String name, Table<R> aliased) {
|
||||
this(name, null, aliased);
|
||||
this(name, null, null, aliased);
|
||||
}
|
||||
|
||||
public TableImpl(String name, String[] fieldAliases, Table<R> aliased) {
|
||||
this(name, fieldAliases, null, aliased);
|
||||
}
|
||||
|
||||
public TableImpl(String name, Schema schema) {
|
||||
this(name, schema, null);
|
||||
this(name, null, schema, null);
|
||||
}
|
||||
|
||||
public TableImpl(String name, Schema schema, Table<R> aliased) {
|
||||
this(name, null, schema, aliased);
|
||||
}
|
||||
|
||||
public TableImpl(String name, String[] fieldAliases, Schema schema, Table<R> aliased) {
|
||||
super(name, schema);
|
||||
|
||||
this.fields = new FieldList();
|
||||
|
||||
if (aliased != null) {
|
||||
alias = new Alias<Table<R>>(aliased, name);
|
||||
alias = new Alias<Table<R>>(aliased, name, fieldAliases);
|
||||
}
|
||||
else {
|
||||
alias = null;
|
||||
@ -139,6 +147,22 @@ public class TableImpl<R extends Record> extends AbstractTable<R> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide custom aliasing
|
||||
* implementations
|
||||
* <p>
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Table<R> as(String as, String... fieldAliases) {
|
||||
if (alias != null) {
|
||||
return alias.wrapped().as(as, fieldAliases);
|
||||
}
|
||||
else {
|
||||
return new TableAlias<R>(this, as, fieldAliases);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must override this method if they use the generic type
|
||||
* parameter <R> for other types than {@link Record}
|
||||
|
||||
@ -61,15 +61,23 @@ public class UpdatableTableImpl<R extends Record> extends TableImpl<R> implement
|
||||
private static final long serialVersionUID = 8214807990871116060L;
|
||||
|
||||
public UpdatableTableImpl(String name) {
|
||||
this(name, null);
|
||||
super(name, null, null, null);
|
||||
}
|
||||
|
||||
public UpdatableTableImpl(String name, Schema schema) {
|
||||
super(name, schema);
|
||||
super(name, null, schema, null);
|
||||
}
|
||||
|
||||
public UpdatableTableImpl(String name, Schema schema, Table<R> aliased) {
|
||||
super(name, schema, aliased);
|
||||
super(name, null, schema, aliased);
|
||||
}
|
||||
|
||||
public UpdatableTableImpl(String name, String[] aliasedFields, Schema schema) {
|
||||
super(name, aliasedFields, schema, null);
|
||||
}
|
||||
|
||||
public UpdatableTableImpl(String name, String[] aliasedFields, Schema schema, Table<R> aliased) {
|
||||
super(name, aliasedFields, schema, aliased);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -75,6 +75,11 @@ class Values<R extends Record> extends AbstractTable<R> {
|
||||
return new TableAlias<R>(this, alias, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> as(String alias, String... fieldAliases) {
|
||||
return new TableAlias<R>(this, alias, fieldAliases, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toSQL(RenderContext context) {
|
||||
context.keyword("values");
|
||||
|
||||
@ -89,6 +89,11 @@ class WithTable<R extends Record> extends AbstractTable<R> {
|
||||
return new WithTable<R>(new TableAlias<R>(delegate, alias), hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Table<R> as(String alias, String... fieldAliases) {
|
||||
return new WithTable<R>(new TableAlias<R>(delegate, alias, fieldAliases), hint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final FieldList getFieldList() {
|
||||
return delegate.getFieldList();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user