[#3560] Slow discovery of primary keys in very large MySQL databases
This commit is contained in:
parent
8dbff7fc0b
commit
57650f08e3
@ -41,12 +41,13 @@
|
||||
|
||||
package org.jooq.util.mysql;
|
||||
|
||||
import static org.jooq.impl.DSL.inline;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.COLUMNS;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.KEY_COLUMN_USAGE;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.REFERENTIAL_CONSTRAINTS;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.SCHEMATA;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.STATISTICS;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.TABLES;
|
||||
import static org.jooq.util.mysql.information_schema.Tables.TABLE_CONSTRAINTS;
|
||||
import static org.jooq.util.mysql.mysql.tables.Proc.DB;
|
||||
import static org.jooq.util.mysql.mysql.tables.Proc.PROC;
|
||||
|
||||
@ -85,7 +86,7 @@ import org.jooq.util.mysql.information_schema.tables.Columns;
|
||||
import org.jooq.util.mysql.information_schema.tables.KeyColumnUsage;
|
||||
import org.jooq.util.mysql.information_schema.tables.ReferentialConstraints;
|
||||
import org.jooq.util.mysql.information_schema.tables.Schemata;
|
||||
import org.jooq.util.mysql.information_schema.tables.TableConstraints;
|
||||
import org.jooq.util.mysql.information_schema.tables.Statistics;
|
||||
import org.jooq.util.mysql.information_schema.tables.Tables;
|
||||
import org.jooq.util.mysql.mysql.enums.ProcType;
|
||||
import org.jooq.util.mysql.mysql.tables.Proc;
|
||||
@ -99,11 +100,11 @@ public class MySQLDatabase extends AbstractDatabase {
|
||||
|
||||
@Override
|
||||
protected void loadPrimaryKeys(DefaultRelations relations) throws SQLException {
|
||||
for (Record record : fetchKeys("PRIMARY KEY")) {
|
||||
SchemaDefinition schema = getSchema(record.getValue(KeyColumnUsage.TABLE_SCHEMA));
|
||||
String constraintName = record.getValue(KeyColumnUsage.CONSTRAINT_NAME);
|
||||
String tableName = record.getValue(KeyColumnUsage.TABLE_NAME);
|
||||
String columnName = record.getValue(KeyColumnUsage.COLUMN_NAME);
|
||||
for (Record record : fetchKeys(true)) {
|
||||
SchemaDefinition schema = getSchema(record.getValue(Statistics.TABLE_SCHEMA));
|
||||
String constraintName = record.getValue(Statistics.INDEX_NAME);
|
||||
String tableName = record.getValue(Statistics.TABLE_NAME);
|
||||
String columnName = record.getValue(Statistics.COLUMN_NAME);
|
||||
|
||||
String key = getKeyName(tableName, constraintName);
|
||||
TableDefinition table = getTable(schema, tableName);
|
||||
@ -116,11 +117,11 @@ public class MySQLDatabase extends AbstractDatabase {
|
||||
|
||||
@Override
|
||||
protected void loadUniqueKeys(DefaultRelations relations) throws SQLException {
|
||||
for (Record record : fetchKeys("UNIQUE")) {
|
||||
SchemaDefinition schema = getSchema(record.getValue(KeyColumnUsage.TABLE_SCHEMA));
|
||||
String constraintName = record.getValue(KeyColumnUsage.CONSTRAINT_NAME);
|
||||
String tableName = record.getValue(KeyColumnUsage.TABLE_NAME);
|
||||
String columnName = record.getValue(KeyColumnUsage.COLUMN_NAME);
|
||||
for (Record record : fetchKeys(false)) {
|
||||
SchemaDefinition schema = getSchema(record.getValue(Statistics.TABLE_SCHEMA));
|
||||
String constraintName = record.getValue(Statistics.INDEX_NAME);
|
||||
String tableName = record.getValue(Statistics.TABLE_NAME);
|
||||
String columnName = record.getValue(Statistics.COLUMN_NAME);
|
||||
|
||||
String key = getKeyName(tableName, constraintName);
|
||||
TableDefinition table = getTable(schema, tableName);
|
||||
@ -135,24 +136,26 @@ public class MySQLDatabase extends AbstractDatabase {
|
||||
return "KEY_" + tableName + "_" + keyName;
|
||||
}
|
||||
|
||||
private Result<Record4<String, String, String, String>> fetchKeys(String constraintType) {
|
||||
private Result<Record4<String, String, String, String>> fetchKeys(boolean primary) {
|
||||
|
||||
// [#3560] It has been shown that querying the STATISTICS table is much faster on
|
||||
// very large databases than going through TABLE_CONSTRAINTS and KEY_COLUMN_USAGE
|
||||
return create().select(
|
||||
KeyColumnUsage.TABLE_SCHEMA,
|
||||
KeyColumnUsage.CONSTRAINT_NAME,
|
||||
KeyColumnUsage.TABLE_NAME,
|
||||
KeyColumnUsage.COLUMN_NAME)
|
||||
.from(KEY_COLUMN_USAGE)
|
||||
.join(TABLE_CONSTRAINTS)
|
||||
.on(KeyColumnUsage.TABLE_SCHEMA.equal(TableConstraints.TABLE_SCHEMA))
|
||||
.and(KeyColumnUsage.TABLE_NAME.equal(TableConstraints.TABLE_NAME))
|
||||
.and(KeyColumnUsage.CONSTRAINT_NAME.equal(TableConstraints.CONSTRAINT_NAME))
|
||||
.where(TableConstraints.CONSTRAINT_TYPE.equal(constraintType))
|
||||
.and(KeyColumnUsage.TABLE_SCHEMA.in(getInputSchemata()))
|
||||
.orderBy(
|
||||
KeyColumnUsage.TABLE_SCHEMA.asc(),
|
||||
KeyColumnUsage.TABLE_NAME.asc(),
|
||||
KeyColumnUsage.ORDINAL_POSITION.asc())
|
||||
.fetch();
|
||||
Statistics.TABLE_SCHEMA,
|
||||
Statistics.TABLE_NAME,
|
||||
Statistics.COLUMN_NAME,
|
||||
Statistics.INDEX_NAME)
|
||||
.from(STATISTICS)
|
||||
.where(Statistics.TABLE_SCHEMA.in(getInputSchemata()))
|
||||
.and(primary
|
||||
? Statistics.INDEX_NAME.eq(inline("PRIMARY"))
|
||||
: Statistics.INDEX_NAME.ne(inline("PRIMARY")).and(Statistics.NON_UNIQUE.eq(inline(0L))))
|
||||
.orderBy(
|
||||
Statistics.TABLE_SCHEMA,
|
||||
Statistics.TABLE_NAME,
|
||||
Statistics.INDEX_NAME,
|
||||
Statistics.SEQ_IN_INDEX)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class InformationSchema extends org.jooq.impl.SchemaImpl {
|
||||
|
||||
private static final long serialVersionUID = -611052785;
|
||||
private static final long serialVersionUID = -679998315;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema</code>
|
||||
@ -39,6 +39,7 @@ public class InformationSchema extends org.jooq.impl.SchemaImpl {
|
||||
org.jooq.util.mysql.information_schema.tables.Parameters.PARAMETERS,
|
||||
org.jooq.util.mysql.information_schema.tables.ReferentialConstraints.REFERENTIAL_CONSTRAINTS,
|
||||
org.jooq.util.mysql.information_schema.tables.Schemata.SCHEMATA,
|
||||
org.jooq.util.mysql.information_schema.tables.Statistics.STATISTICS,
|
||||
org.jooq.util.mysql.information_schema.tables.Tables.TABLES,
|
||||
org.jooq.util.mysql.information_schema.tables.TableConstraints.TABLE_CONSTRAINTS);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ package org.jooq.util.mysql.information_schema;
|
||||
*
|
||||
* Convenience access to all tables in information_schema
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Tables {
|
||||
@ -38,6 +38,11 @@ public class Tables {
|
||||
*/
|
||||
public static final org.jooq.util.mysql.information_schema.tables.Schemata SCHEMATA = org.jooq.util.mysql.information_schema.tables.Schemata.SCHEMATA;
|
||||
|
||||
/**
|
||||
* The table information_schema.STATISTICS
|
||||
*/
|
||||
public static final org.jooq.util.mysql.information_schema.tables.Statistics STATISTICS = org.jooq.util.mysql.information_schema.tables.Statistics.STATISTICS;
|
||||
|
||||
/**
|
||||
* The table information_schema.TABLES
|
||||
*/
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Columns extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = -840872510;
|
||||
private static final long serialVersionUID = -1192516157;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.COLUMNS</code>
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class KeyColumnUsage extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = -1303145965;
|
||||
private static final long serialVersionUID = -669574892;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.KEY_COLUMN_USAGE</code>
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Parameters extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = -564000748;
|
||||
private static final long serialVersionUID = 1665633877;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.PARAMETERS</code>
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class ReferentialConstraints extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = -514911080;
|
||||
private static final long serialVersionUID = 1234359031;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.REFERENTIAL_CONSTRAINTS</code>
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Schemata extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = 1266409808;
|
||||
private static final long serialVersionUID = -2145867409;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.SCHEMATA</code>
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* This class is generated by jOOQ
|
||||
*/
|
||||
package org.jooq.util.mysql.information_schema.tables;
|
||||
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Statistics extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = 357430055;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.STATISTICS</code>
|
||||
*/
|
||||
public static final org.jooq.util.mysql.information_schema.tables.Statistics STATISTICS = new org.jooq.util.mysql.information_schema.tables.Statistics();
|
||||
|
||||
/**
|
||||
* The class holding records for this type
|
||||
*/
|
||||
@Override
|
||||
public java.lang.Class<org.jooq.Record> getRecordType() {
|
||||
return org.jooq.Record.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.TABLE_CATALOG</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_CATALOG = createField("TABLE_CATALOG", org.jooq.impl.SQLDataType.VARCHAR.length(512).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.TABLE_SCHEMA</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_SCHEMA = createField("TABLE_SCHEMA", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.TABLE_NAME</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> TABLE_NAME = createField("TABLE_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.NON_UNIQUE</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> NON_UNIQUE = createField("NON_UNIQUE", org.jooq.impl.SQLDataType.BIGINT.nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.INDEX_SCHEMA</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_SCHEMA = createField("INDEX_SCHEMA", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.INDEX_NAME</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_NAME = createField("INDEX_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.SEQ_IN_INDEX</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> SEQ_IN_INDEX = createField("SEQ_IN_INDEX", org.jooq.impl.SQLDataType.BIGINT.nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.COLUMN_NAME</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COLUMN_NAME = createField("COLUMN_NAME", org.jooq.impl.SQLDataType.VARCHAR.length(64).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.COLLATION</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COLLATION = createField("COLLATION", org.jooq.impl.SQLDataType.VARCHAR.length(1), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.CARDINALITY</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> CARDINALITY = createField("CARDINALITY", org.jooq.impl.SQLDataType.BIGINT, STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.SUB_PART</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.Long> SUB_PART = createField("SUB_PART", org.jooq.impl.SQLDataType.BIGINT, STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.PACKED</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> PACKED = createField("PACKED", org.jooq.impl.SQLDataType.VARCHAR.length(10), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.NULLABLE</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> NULLABLE = createField("NULLABLE", org.jooq.impl.SQLDataType.VARCHAR.length(3).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.INDEX_TYPE</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_TYPE = createField("INDEX_TYPE", org.jooq.impl.SQLDataType.VARCHAR.length(16).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.COMMENT</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> COMMENT = createField("COMMENT", org.jooq.impl.SQLDataType.VARCHAR.length(16), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* The column <code>information_schema.STATISTICS.INDEX_COMMENT</code>.
|
||||
*/
|
||||
public static final org.jooq.TableField<org.jooq.Record, java.lang.String> INDEX_COMMENT = createField("INDEX_COMMENT", org.jooq.impl.SQLDataType.VARCHAR.length(1024).nullable(false).defaulted(true), STATISTICS, "");
|
||||
|
||||
/**
|
||||
* No further instances allowed
|
||||
*/
|
||||
private Statistics() {
|
||||
this("STATISTICS", null);
|
||||
}
|
||||
|
||||
private Statistics(java.lang.String alias, org.jooq.Table<org.jooq.Record> aliased) {
|
||||
this(alias, aliased, null);
|
||||
}
|
||||
|
||||
private Statistics(java.lang.String alias, org.jooq.Table<org.jooq.Record> aliased, org.jooq.Field<?>[] parameters) {
|
||||
super(alias, org.jooq.util.mysql.information_schema.InformationSchema.INFORMATION_SCHEMA, aliased, parameters, "");
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class TableConstraints extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = 2008733278;
|
||||
private static final long serialVersionUID = -1909788577;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.TABLE_CONSTRAINTS</code>
|
||||
|
||||
@ -6,12 +6,12 @@ package org.jooq.util.mysql.information_schema.tables;
|
||||
/**
|
||||
* This class is generated by jOOQ.
|
||||
*/
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.4.0" },
|
||||
@javax.annotation.Generated(value = { "http://www.jooq.org", "3.5.0" },
|
||||
comments = "This class is generated by jOOQ")
|
||||
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
|
||||
public class Tables extends org.jooq.impl.TableImpl<org.jooq.Record> {
|
||||
|
||||
private static final long serialVersionUID = 1927949993;
|
||||
private static final long serialVersionUID = 1728740650;
|
||||
|
||||
/**
|
||||
* The singleton instance of <code>information_schema.TABLES</code>
|
||||
|
||||
@ -2468,7 +2468,7 @@
|
||||
<name>org.jooq.util.DefaultGenerator</name>
|
||||
<database>
|
||||
<name>org.jooq.util.mysql.MySQLDatabase</name>
|
||||
<includes>COLUMNS|KEY_COLUMN_USAGE|PARAMETERS|REFERENTIAL_CONSTRAINTS|SCHEMATA|TABLE_CONSTRAINTS|TABLES</includes>
|
||||
<includes>COLUMNS|KEY_COLUMN_USAGE|PARAMETERS|REFERENTIAL_CONSTRAINTS|SCHEMATA|STATISTICS|TABLE_CONSTRAINTS|TABLES</includes>
|
||||
<excludes></excludes>
|
||||
<recordVersionFields></recordVersionFields>
|
||||
<recordTimestampFields></recordTimestampFields>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user