[jOOQ/jOOQ#6489] Code generator should support SQL-generated "dynamic regular expressions"

This commit is contained in:
Lukas Eder 2022-06-15 18:11:56 +02:00
parent 439e60c558
commit 29890da22c
6 changed files with 264 additions and 12 deletions

View File

@ -553,8 +553,14 @@ public class GenerationTool {
database.setConnection(connection);
database.setConfiguredCatalogs(catalogs);
database.setConfiguredSchemata(schemata);
database.setIncludes(new String[] { defaultString(d.getIncludes()) });
database.setExcludes(new String[] { defaultString(d.getExcludes()) });
if (!isBlank(d.getIncludes()))
database.setIncludes(new String[] { d.getIncludes() });
if (!isBlank(d.getExcludes()))
database.setExcludes(new String[] { d.getExcludes() });
database.setIncludeSql(d.getIncludeSql());
database.setExcludeSql(d.getExcludeSql());
// [#10763] Currently, the javaTimeTypes flag needs to be set before
// the forcedTypesForBuiltinDataTypeExtensions flag.

View File

@ -162,7 +162,11 @@ public abstract class AbstractDatabase implements Database {
private OnError onError = OnError.FAIL;
private List<Filter> filters;
private String[] excludes;
private String[] includes = { ".*" };
private String[] excludesResult;
private String excludeSql;
private String[] includes;
private String[] includesResult;
private String includeSql;
private boolean includeExcludeColumns = false;
private boolean includeExcludePackageRoutines = false;
private boolean includeInvisibleColumns = true;
@ -1009,7 +1013,20 @@ public abstract class AbstractDatabase implements Database {
if (excludes == null)
excludes = new String[0];
return excludes;
if (excludesResult == null)
excludesResult = includeExcludeResult(excludes, excludeSql);
return excludesResult;
}
@Override
public final void setExcludeSql(String sql) {
this.excludeSql = sql;
}
@Override
public final String getExcludeSql() {
return excludeSql;
}
@Override
@ -1022,7 +1039,29 @@ public abstract class AbstractDatabase implements Database {
if (includes == null)
includes = new String[0];
return includes;
if (includesResult == null)
includesResult = includeExcludeResult(includes, includeSql);
return includesResult;
}
@Override
public final void setIncludeSql(String sql) {
this.includeSql = sql;
}
@Override
public final String getIncludeSql() {
return includeSql;
}
private final String[] includeExcludeResult(String[] a, String sql) {
List<String> list = new ArrayList<>(Arrays.asList(a));
if (!StringUtils.isBlank(sql))
list.addAll(statements.fetchSet(sql, String.class));
return list.toArray(new String[0]);
}
@Override
@ -2959,7 +2998,7 @@ public abstract class AbstractDatabase implements Database {
@Override
public final <T extends Definition> List<T> filterExcludeInclude(List<T> definitions) {
List<T> result = filterExcludeInclude(definitions, excludes, includes, filters);
List<T> result = filterExcludeInclude(definitions, getExcludes(), getIncludes(), filters);
this.all.addAll(definitions);
this.included.addAll(result);
@ -3012,6 +3051,10 @@ public abstract class AbstractDatabase implements Database {
protected final <T extends Definition> List<T> filterExcludeInclude(List<T> definitions, String[] e, String[] i, List<Filter> f) {
List<T> result = new ArrayList<>();
// [#6489] By default, exclude nothing and include everything
if (i == null || i.length == 0)
i = new String[] { ".*" };
definitionsLoop: for (T definition : definitions) {
if (e != null) {
for (String exclude : e) {

View File

@ -457,24 +457,52 @@ public interface Database extends AutoCloseable {
*/
void setExcludes(String[] excludes);
/**
* Database objects matching any of the regular expressions produced by this
* SQL query will not be generated, in addition to the ones specified by
* {@link #getExcludes()}.
*/
void setExcludeSql(String sql);
/**
* Database objects matching any of these regular expressions will not be
* generated.
*/
String[] getExcludes();
/**
* Database objects matching any of the regular expressions produced by this
* SQL query will not be generated, in addition to the ones specified by
* {@link #getExcludes()}.
*/
String getExcludeSql();
/**
* Only database objects matching any of these regular expressions will be
* generated.
*/
void setIncludes(String[] includes);
/**
* Only database objects matching any of the regular expressions produced by
* this SQL query will be generated, in addition to the ones specified by
* {@link #getIncludes()}.
*/
void setIncludeSql(String sql);
/**
* Only database objects matching any of these regular expressions will be
* generated.
*/
String[] getIncludes();
/**
* Only database objects matching any of the regular expressions produced by
* this SQL query will be generated, in addition to the ones specified by
* {@link #getIncludes()}.
*/
String getIncludeSql();
/**
* Indicate whether include / exclude regular expression shall also match
* database columns.

View File

@ -72,4 +72,9 @@ final class Statements {
final Set<?> fetchSet(String sql) {
return sqlCacheSingleColumnSet.computeIfAbsent(sql, s -> fetch(s).intoSet(0));
}
@SuppressWarnings("unchecked")
final <T> Set<T> fetchSet(String sql, Class<T> type) {
return (Set<T>) sqlCacheSingleColumnSet.computeIfAbsent(sql, s -> fetch(s).intoSet(0, type));
}
}

View File

@ -43,12 +43,14 @@ public class Database implements Serializable, XMLAppendable
protected Boolean regexMatchesPartialQualification = true;
@XmlElement(defaultValue = "true")
protected Boolean sqlMatchesPartialQualification = true;
@XmlElement(defaultValue = ".*")
@XmlJavaTypeAdapter(StringAdapter.class)
protected String includes = ".*";
@XmlElement(defaultValue = "")
protected String includes;
@XmlJavaTypeAdapter(StringAdapter.class)
protected String excludes = "";
protected String includeSql;
@XmlJavaTypeAdapter(StringAdapter.class)
protected String excludes;
@XmlJavaTypeAdapter(StringAdapter.class)
protected String excludeSql;
@XmlElement(defaultValue = "false")
protected Boolean includeExcludeColumns = false;
@XmlElement(defaultValue = "false")
@ -409,6 +411,44 @@ public class Database implements Serializable, XMLAppendable
this.includes = value;
}
/**
* All elements that are generated from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by includes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public String getIncludeSql() {
return includeSql;
}
/**
* All elements that are generated from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by includes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public void setIncludeSql(String value) {
this.includeSql = value;
}
/**
* All elements that are excluded from your schema.
* <p>
@ -431,6 +471,44 @@ public class Database implements Serializable, XMLAppendable
this.excludes = value;
}
/**
* All elements that are excluded from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by excludes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public String getExcludeSql() {
return excludeSql;
}
/**
* All elements that are excluded from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by excludes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public void setExcludeSql(String value) {
this.excludeSql = value;
}
/**
* This flag indicates whether include / exclude patterns should also match columns within tables.
*
@ -2061,6 +2139,26 @@ public class Database implements Serializable, XMLAppendable
return this;
}
/**
* All elements that are generated from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by includes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public Database withIncludeSql(String value) {
setIncludeSql(value);
return this;
}
/**
* All elements that are excluded from your schema.
* <p>
@ -2073,6 +2171,26 @@ public class Database implements Serializable, XMLAppendable
return this;
}
/**
* All elements that are excluded from your schema.
* <p>
* This is a query that produces Java regular expressions, which are appended to the ones produced by excludes.
* Watch out for case-sensitivity. Depending on your database, this might be
* important!
* <p>
* You can create case-insensitive regular expressions
* using this syntax: <code>(?i:expr)</code>
* <p>
* Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
* <p>
* Excludes match before includes, i.e. excludes have a higher priority.
*
*/
public Database withExcludeSql(String value) {
setExcludeSql(value);
return this;
}
public Database withIncludeExcludeColumns(Boolean value) {
setIncludeExcludeColumns(value);
return this;
@ -2689,7 +2807,9 @@ public class Database implements Serializable, XMLAppendable
builder.append("regexMatchesPartialQualification", regexMatchesPartialQualification);
builder.append("sqlMatchesPartialQualification", sqlMatchesPartialQualification);
builder.append("includes", includes);
builder.append("includeSql", includeSql);
builder.append("excludes", excludes);
builder.append("excludeSql", excludeSql);
builder.append("includeExcludeColumns", includeExcludeColumns);
builder.append("includeExcludePackageRoutines", includeExcludePackageRoutines);
builder.append("includeTables", includeTables);
@ -2820,6 +2940,15 @@ public class Database implements Serializable, XMLAppendable
return false;
}
}
if (includeSql == null) {
if (other.includeSql!= null) {
return false;
}
} else {
if (!includeSql.equals(other.includeSql)) {
return false;
}
}
if (excludes == null) {
if (other.excludes!= null) {
return false;
@ -2829,6 +2958,15 @@ public class Database implements Serializable, XMLAppendable
return false;
}
}
if (excludeSql == null) {
if (other.excludeSql!= null) {
return false;
}
} else {
if (!excludeSql.equals(other.excludeSql)) {
return false;
}
}
if (includeExcludeColumns == null) {
if (other.includeExcludeColumns!= null) {
return false;
@ -3417,7 +3555,9 @@ public class Database implements Serializable, XMLAppendable
result = ((prime*result)+((regexMatchesPartialQualification == null)? 0 :regexMatchesPartialQualification.hashCode()));
result = ((prime*result)+((sqlMatchesPartialQualification == null)? 0 :sqlMatchesPartialQualification.hashCode()));
result = ((prime*result)+((includes == null)? 0 :includes.hashCode()));
result = ((prime*result)+((includeSql == null)? 0 :includeSql.hashCode()));
result = ((prime*result)+((excludes == null)? 0 :excludes.hashCode()));
result = ((prime*result)+((excludeSql == null)? 0 :excludeSql.hashCode()));
result = ((prime*result)+((includeExcludeColumns == null)? 0 :includeExcludeColumns.hashCode()));
result = ((prime*result)+((includeExcludePackageRoutines == null)? 0 :includeExcludePackageRoutines.hashCode()));
result = ((prime*result)+((includeTables == null)? 0 :includeTables.hashCode()));

View File

@ -574,7 +574,7 @@ The default value is "COMMENTS CASE_INSENSITIVE"]]></jxb:javadoc></jxb:property>
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether SQL queries that match qualified object names also match partial qualifications (e.g. `table\.column` matches `schema.table.column`) or only full and/or no qualifications (e.g. `schema\.table\.column` and `column` match `schema.table.column`)]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="includes" type="string" default=".*" minOccurs="0" maxOccurs="1">
<element name="includes" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All elements that are generated from your schema.
<p>
This is a Java regular expression. Use the pipe to separate several expressions.
@ -587,13 +587,43 @@ using this syntax: <code>(?i:expr)</code>
Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="excludes" type="string" default="" minOccurs="0" maxOccurs="1">
<element name="includeSql" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All elements that are generated from your schema.
<p>
This is a query that produces Java regular expressions, which are appended to the ones produced by includes.
Watch out for case-sensitivity. Depending on your database, this might be
important!
<p>
You can create case-insensitive regular expressions
using this syntax: <code>(?i:expr)</code>
<p>
Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
<p>
Excludes match before includes, i.e. excludes have a higher priority.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="excludes" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All elements that are excluded from your schema.
<p>
This is a Java regular expression. Use the pipe to separate several expressions.
Excludes match before includes, i.e. excludes have a higher priority.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="excludeSql" type="string" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All elements that are excluded from your schema.
<p>
This is a query that produces Java regular expressions, which are appended to the ones produced by excludes.
Watch out for case-sensitivity. Depending on your database, this might be
important!
<p>
You can create case-insensitive regular expressions
using this syntax: <code>(?i:expr)</code>
<p>
Whitespace is ignored and comments are possible unless overridden in {@link #getRegexFlags()}.
<p>
Excludes match before includes, i.e. excludes have a higher priority.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="includeExcludeColumns" type="boolean" default="false" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[This flag indicates whether include / exclude patterns should also match columns within tables.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>