[#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:
Lukas Eder 2013-01-02 14:39:17 +01:00
parent ae7aad93d5
commit 48b25650b4
23 changed files with 462 additions and 64 deletions

View 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"));
}
}

View File

@ -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

View File

@ -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>

View File

@ -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);
}

View File

@ -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) {

View File

@ -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
// ------------------------------------------------------------------------

View File

@ -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;
}
}
}

View File

@ -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();
}
}

View File

@ -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() {

View File

@ -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();

View File

@ -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()) {

View File

@ -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()) {

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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());

View File

@ -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();

View File

@ -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}

View File

@ -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);
}
/**

View File

@ -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");

View File

@ -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();