[jOOQ/jOOQ#7406] Add code generation support for SETOF UDT returning
functions in PostgreSQL
This commit is contained in:
parent
4ffd806253
commit
1200fa0fa5
@ -1643,7 +1643,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
|
||||
for (TableDefinition table : database.getTables(schema)) {
|
||||
try {
|
||||
if (table.isTableValuedFunction() && table.getReferencedTable() != table)
|
||||
if (table.isTableValuedFunction() && table.getReferencedTableOrUDT() != table)
|
||||
continue;
|
||||
|
||||
generateRecord(table);
|
||||
@ -7204,7 +7204,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
final String tableId = scala
|
||||
? out.ref(getStrategy().getFullJavaIdentifier(table), 2)
|
||||
: getStrategy().getJavaIdentifier(table);
|
||||
final String recordType = out.ref(getStrategy().getFullJavaClassName(table.getReferencedTable(), Mode.RECORD));
|
||||
final String recordType = out.ref(getStrategy().getFullJavaClassName(table.getReferencedTableOrUDT(), Mode.RECORD));
|
||||
final String classExtends = out.ref(getStrategy().getJavaClassExtends(table, Mode.DEFAULT));
|
||||
final List<String> interfaces = out.ref(getStrategy().getJavaClassImplements(table, Mode.DEFAULT));
|
||||
final String schemaId = generateDefaultSchema(schema)
|
||||
@ -8578,7 +8578,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
// [#10481] Use the types from replaced embeddables if applicable
|
||||
List<Definition> replacingEmbeddablesAndUnreplacedColumns = replacingEmbeddablesAndUnreplacedColumns(table);
|
||||
int degree = replacingEmbeddablesAndUnreplacedColumns.size();
|
||||
int referencedDegree = replacingEmbeddablesAndUnreplacedColumns(table.getReferencedTable()).size();
|
||||
int referencedDegree = replacingEmbeddablesAndUnreplacedColumns(table.getReferencedTableOrUDT()).size();
|
||||
|
||||
String rowType = refRowType(out, replacingEmbeddablesAndUnreplacedColumns);
|
||||
String rowTypeContravariantJava = refRowType(out, replacingEmbeddablesAndUnreplacedColumns, s -> "? super " + s);
|
||||
@ -11013,7 +11013,7 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
final String recordClassName = out.ref(getStrategy().getFullJavaClassName(function.getReferencedTable(), Mode.RECORD));
|
||||
final String recordClassName = out.ref(getStrategy().getFullJavaClassName(function.getReferencedTableOrUDT(), Mode.RECORD));
|
||||
|
||||
// [#3456] Local variables should not collide with actual function arguments
|
||||
final String configurationArgument = disambiguateJavaMemberName(function.getParameters(), "configuration");
|
||||
@ -11067,7 +11067,11 @@ public class JavaGenerator extends AbstractGenerator {
|
||||
}
|
||||
|
||||
protected void printRecordTypeMethod(JavaWriter out, Definition tableOrUDT) {
|
||||
final String className = out.ref(getStrategy().getFullJavaClassName(tableOrUDT instanceof TableDefinition ? ((TableDefinition) tableOrUDT).getReferencedTable() : tableOrUDT, Mode.RECORD));
|
||||
final String className = out.ref(getStrategy().getFullJavaClassName(
|
||||
tableOrUDT instanceof TableDefinition
|
||||
? ((TableDefinition) tableOrUDT).getReferencedTableOrUDT()
|
||||
: tableOrUDT, Mode.RECORD
|
||||
));
|
||||
|
||||
out.javadoc("The class holding records for this type");
|
||||
|
||||
|
||||
@ -71,6 +71,7 @@ implements
|
||||
private final SchemaDefinition referencedSchema;
|
||||
private final String referencedName;
|
||||
private TableDefinition referencedTable;
|
||||
private Definition referencedTableOrUDT;
|
||||
|
||||
public AbstractTableDefinition(SchemaDefinition schema, String name, String comment) {
|
||||
this(schema, name, comment, TableType.TABLE, null);
|
||||
@ -353,6 +354,22 @@ implements
|
||||
return referencedTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Definition getReferencedTableOrUDT() {
|
||||
if (referencedTableOrUDT == null) {
|
||||
if (referencedSchema != null)
|
||||
referencedTableOrUDT = getDatabase().getTable(referencedSchema, referencedName);
|
||||
|
||||
if (referencedTableOrUDT == null)
|
||||
referencedTableOrUDT = getDatabase().getUDT(referencedSchema, referencedName);
|
||||
|
||||
if (referencedTableOrUDT == null)
|
||||
referencedTableOrUDT = this;
|
||||
}
|
||||
|
||||
return referencedTableOrUDT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ColumnDefinition> getElements0() throws SQLException {
|
||||
return null;
|
||||
|
||||
@ -236,8 +236,31 @@ public interface TableDefinition extends Definition {
|
||||
* <code>true</code> and the table valued function references a table
|
||||
* type</li>
|
||||
* </ul>
|
||||
*
|
||||
* @deprecated - [#7406] - 3.20.0 - Use {@link #getReferencedTableOrUDT()}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
TableDefinition getReferencedTable();
|
||||
|
||||
/**
|
||||
* The referenced table or UDT type, if this
|
||||
* {@link #isTableValuedFunction()}.
|
||||
* <p>
|
||||
* This returns:
|
||||
* <ul>
|
||||
* <li><code>this</code>, if {@link #isTableValuedFunction()} ==
|
||||
* <code>false</code></li>
|
||||
* <li><code>this</code>, if {@link #isTableValuedFunction()} ==
|
||||
* <code>true</code> but the table valued function doesn't reference a table
|
||||
* type</li>
|
||||
* <li>Another {@link TableDefinition} or {@link UDTDefinition}, if
|
||||
* {@link #isTableValuedFunction()} == <code>true</code> and the table
|
||||
* valued function references a table type</li>
|
||||
* </ul>
|
||||
*/
|
||||
@NotNull
|
||||
Definition getReferencedTableOrUDT();
|
||||
|
||||
}
|
||||
|
||||
@ -48,8 +48,10 @@ import static org.jooq.impl.DSL.row;
|
||||
import static org.jooq.impl.DSL.rowNumber;
|
||||
import static org.jooq.impl.DSL.select;
|
||||
import static org.jooq.impl.DSL.substring;
|
||||
import static org.jooq.impl.DSL.val;
|
||||
import static org.jooq.impl.DSL.when;
|
||||
import static org.jooq.meta.postgres.PostgresRoutineDefinition.pNumericPrecision;
|
||||
import static org.jooq.meta.postgres.information_schema.Tables.ATTRIBUTES;
|
||||
import static org.jooq.meta.postgres.information_schema.Tables.COLUMNS;
|
||||
import static org.jooq.meta.postgres.information_schema.Tables.PARAMETERS;
|
||||
import static org.jooq.meta.postgres.information_schema.Tables.ROUTINES;
|
||||
@ -73,6 +75,7 @@ import org.jooq.meta.DefaultColumnDefinition;
|
||||
import org.jooq.meta.DefaultDataTypeDefinition;
|
||||
import org.jooq.meta.ParameterDefinition;
|
||||
import org.jooq.meta.SchemaDefinition;
|
||||
import org.jooq.meta.postgres.information_schema.tables.Attributes;
|
||||
import org.jooq.meta.postgres.information_schema.tables.Columns;
|
||||
import org.jooq.meta.postgres.information_schema.tables.Parameters;
|
||||
import org.jooq.meta.postgres.information_schema.tables.Routines;
|
||||
@ -112,6 +115,7 @@ public class PostgresTableValuedFunction extends AbstractTableDefinition {
|
||||
Routines r = ROUTINES.as("r");
|
||||
Parameters p = PARAMETERS.as("p");
|
||||
Columns c = COLUMNS.as("c");
|
||||
Attributes a = ATTRIBUTES.as("a");
|
||||
Columns x = COLUMNS.as("x");
|
||||
PgClass pg_c = PG_CLASS.as("pgc");
|
||||
PgAttribute pg_a = PG_ATTRIBUTE.as("pga");
|
||||
@ -120,6 +124,7 @@ public class PostgresTableValuedFunction extends AbstractTableDefinition {
|
||||
|
||||
Field<Integer> pPrecision = pNumericPrecision(p);
|
||||
Field<Integer> cPrecision = nvl(c.DATETIME_PRECISION, c.NUMERIC_PRECISION);
|
||||
Field<Integer> aPrecision = nvl(a.DATETIME_PRECISION, a.NUMERIC_PRECISION);
|
||||
Field<Integer> rPrecision = nvl(r.DATETIME_PRECISION, r.NUMERIC_PRECISION);
|
||||
|
||||
|
||||
@ -127,6 +132,7 @@ public class PostgresTableValuedFunction extends AbstractTableDefinition {
|
||||
|
||||
|
||||
|
||||
|
||||
for (Record record : create()
|
||||
|
||||
// [#3375] The first subselect is expected to return only those
|
||||
@ -165,16 +171,17 @@ public class PostgresTableValuedFunction extends AbstractTableDefinition {
|
||||
// table-valued functions that return a SETOF [ table type ], as that
|
||||
// table reference is reported via a TYPE_UDT that matches a table
|
||||
// from INFORMATION_SCHEMA.TABLES
|
||||
// [#7406] Exclude composite types
|
||||
select(
|
||||
coalesce(c.COLUMN_NAME, getName()).as(c.COLUMN_NAME),
|
||||
coalesce(c.ORDINAL_POSITION, inline(1)).as(c.ORDINAL_POSITION),
|
||||
coalesce(c.COLUMN_NAME, a.ATTRIBUTE_NAME, val(getName())).as(c.COLUMN_NAME),
|
||||
coalesce(c.ORDINAL_POSITION, a.ORDINAL_POSITION, inline(1)).as(c.ORDINAL_POSITION),
|
||||
db.arrayDataType(x.DATA_TYPE, x.UDT_NAME, pg_a.ATTNDIMS).as(c.DATA_TYPE),
|
||||
coalesce(c.CHARACTER_MAXIMUM_LENGTH, r.CHARACTER_MAXIMUM_LENGTH ).as(c.CHARACTER_MAXIMUM_LENGTH),
|
||||
coalesce(cPrecision, rPrecision).as(c.NUMERIC_PRECISION),
|
||||
coalesce(c.NUMERIC_SCALE, r.NUMERIC_SCALE).as(c.NUMERIC_SCALE),
|
||||
coalesce(c.IS_NULLABLE, inline("true")).as(c.IS_NULLABLE),
|
||||
coalesce(c.COLUMN_DEFAULT, inline((String) null)).as(c.COLUMN_DEFAULT),
|
||||
coalesce(c.UDT_SCHEMA, inline((String) null)).as(c.UDT_SCHEMA),
|
||||
coalesce(c.CHARACTER_MAXIMUM_LENGTH, a.CHARACTER_MAXIMUM_LENGTH, r.CHARACTER_MAXIMUM_LENGTH ).as(c.CHARACTER_MAXIMUM_LENGTH),
|
||||
coalesce(cPrecision, aPrecision, rPrecision).as(c.NUMERIC_PRECISION),
|
||||
coalesce(c.NUMERIC_SCALE, a.NUMERIC_SCALE, r.NUMERIC_SCALE).as(c.NUMERIC_SCALE),
|
||||
coalesce(c.IS_NULLABLE, a.IS_NULLABLE, inline("true")).as(c.IS_NULLABLE),
|
||||
coalesce(c.COLUMN_DEFAULT, a.ATTRIBUTE_DEFAULT, inline((String) null)).as(c.COLUMN_DEFAULT),
|
||||
coalesce(c.UDT_SCHEMA, a.ATTRIBUTE_UDT_SCHEMA, inline((String) null)).as(c.UDT_SCHEMA),
|
||||
db.arrayUdtName(x.DATA_TYPE, x.UDT_NAME).as(c.UDT_NAME)
|
||||
)
|
||||
.from(r)
|
||||
@ -185,20 +192,26 @@ public class PostgresTableValuedFunction extends AbstractTableDefinition {
|
||||
.join(pg_p)
|
||||
.on(pg_p.PRONAME.concat("_").concat(pg_p.OID).eq(r.SPECIFIC_NAME))
|
||||
.and(pg_p.pgNamespace().NSPNAME.eq(r.SPECIFIC_SCHEMA))
|
||||
|
||||
// [#7406] COLUMNS and ATTRIBUTES are mutually exclusive, hence no cross product here
|
||||
.leftJoin(c)
|
||||
.on(row(r.TYPE_UDT_CATALOG, r.TYPE_UDT_SCHEMA, r.TYPE_UDT_NAME)
|
||||
.eq(c.TABLE_CATALOG, c.TABLE_SCHEMA, c.TABLE_NAME))
|
||||
.leftJoin(a)
|
||||
.on(row(r.TYPE_UDT_CATALOG, r.TYPE_UDT_SCHEMA, r.TYPE_UDT_NAME)
|
||||
.eq(a.UDT_CATALOG, a.UDT_SCHEMA, a.UDT_NAME))
|
||||
|
||||
.leftJoin(pg_c)
|
||||
.on(c.TABLE_NAME.eq(pg_c.RELNAME))
|
||||
.on(nvl(c.TABLE_NAME, a.UDT_NAME).eq(pg_c.RELNAME))
|
||||
.and(pg_c.pgNamespace().NSPNAME.eq(r.SPECIFIC_SCHEMA))
|
||||
.leftJoin(pg_a)
|
||||
.on(pg_c.OID.eq(pg_a.ATTRELID))
|
||||
.and(c.COLUMN_NAME.eq(pg_a.ATTNAME))
|
||||
.and(nvl(c.COLUMN_NAME, a.ATTRIBUTE_NAME).eq(pg_a.ATTNAME))
|
||||
.crossApply(
|
||||
select(
|
||||
coalesce(c.DATA_TYPE, r.DATA_TYPE).as(x.DATA_TYPE),
|
||||
coalesce(c.DATA_TYPE, a.DATA_TYPE, r.DATA_TYPE).as(x.DATA_TYPE),
|
||||
coalesce(
|
||||
c.UDT_NAME, r.UDT_NAME,
|
||||
c.UDT_NAME, a.ATTRIBUTE_UDT_NAME, r.UDT_NAME,
|
||||
field(select(pg_t.TYPNAME).from(pg_t).where(pg_t.OID.eq(pg_p.PRORETTYPE)))
|
||||
).as(x.UDT_NAME)
|
||||
).asTable(x)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user