WordTable.java
/*
** Module : WordTable.java
** Abstract : Word table data
**
** Copyright (c) 2021-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
** 001 IAS 20219314 Created initial version.
** OM 20220817 WordTable must be dialect sensitive.
** 002 OM 20240718 Fixed the list of columns in foreign key when creating FK constraints.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.persist.orm;
import static com.goldencode.p2j.persist.orm.DDLGeneratorWorker.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.stream.*;
import com.goldencode.p2j.persist.dialect.*;
import com.goldencode.p2j.schema.*;
/** Word table data */
public class WordTable
{
/** The dialect used to generated DDL statements. */
public final Dialect dialect;
/** The name of the parent table. */
public final String parentTableName;
/** The field name. */
public final String fieldName;
/** Custom extent hints. */
public final List<CustomExtentField> customExtentFields;
/** The extent size. */
public final long extent;
/** Is this field a case-sensitive character? */
public final boolean caseSensitive;
/** The word table name. */
public final String tableName;
/** The word table PK name. */
public final String pkName;
/** The word table FK index name. */
public final String fkIndexName;
/** The word table FK constraint name. */
public final String fkName;
/** The name of the word table index on 'word' field. */
public final String indexName;
/** parent table trigger function name */
public final String triggerFunctionName;
/** parent table AFTER UPDATE trigger name */
public final String afterUpdateTriggerName;
/** parent table AFTER INSERT trigger name */
public final String afterInsertTriggerName;
/**
* The constructor is private. Objects of this class can be constructed only using the {@link Builder}.
*
* @param dialect
* The dialect used to generated DDL statements.
* @param parentTableName
* parent table name
* @param fieldName
* field name
* @param customExtentFields
* custom extent hints
* @param extent
* field extent
* @param caseSensitive
* field is case-sensitive flag
* @param tableName
* word table name
* @param pkName
* word table PK name
* @param fkIndexName
* word table FK index name
* @param fkName
* word table FK constraint name
* @param indexName
* name of the word table index on 'word' field
* @param triggerFunctionName
* parent table trigger function name
* @param afterUpdateTriggerName
* parent table AFTER UPDATE trigger name
* @param afterInsertTriggerName
* parent table AFTER INSERT trigger name
*/
private WordTable(
Dialect dialect,
String parentTableName, String fieldName, List<CustomExtentField> customExtentFields,
long extent, boolean caseSensitive,
String tableName, String pkName, String fkIndexName, String fkName, String indexName,
String triggerFunctionName,
String afterUpdateTriggerName, String afterInsertTriggerName)
{
this.dialect = dialect;
this.parentTableName = parentTableName;
this.fieldName = fieldName;
this.customExtentFields = customExtentFields;
this.extent = extent;
this.caseSensitive = caseSensitive;
this.tableName = tableName;
this.pkName = pkName;
this.fkIndexName = fkIndexName;
this.fkName = fkName;
this.indexName = indexName;
this.triggerFunctionName = triggerFunctionName;
this.afterUpdateTriggerName = afterUpdateTriggerName;
this.afterInsertTriggerName = afterInsertTriggerName;
}
/**
* Get drop PK DDL statement
* @param eoln
* OS-specific end of line terminator.
* @param suffix
* dialect-specific statement suffix
* @return drop PK DDL statement
*/
public String dropPK(String eoln, String suffix)
{
return "alter table " + tableName + eoln +
INDENT + "drop constraint if exists " + pkName + suffix + eoln;
}
/**
* Get create PK DDL statement
*
* @param eoln
* The OS-specific end of line terminator.
* @param suffix .
* The dialect-specific statement suffix.
*
* @return The DDL statement for dropping the PK.
*/
public String createPK(String eoln, String suffix)
{
return "alter table " + tableName + eoln +
INDENT + "add constraint " + pkName + eoln +
INDENT + "primary key (parent__id, " +
(extent == 0 ? "" : "list__index, ") +
"word)" + suffix + eoln;
}
/**
* Get drop FK DDL statement.
*
* @param eoln
* OS-specific end of line terminator.
* @param suffix
* dialect-specific statement suffix
*
* @return The DDL statement for dropping the PK.
*/
public String dropFK(String eoln, String suffix)
{
return "alter table " + tableName + eoln +
INDENT + "drop constraint if exists " + fkName + suffix + eoln;
}
/**
* Get create FK DDL statement.
*
* @param eoln
* OS-specific end of line terminator.
*
* @return The DDL statement for creating a FK constraint.
*/
public String createFK(String eoln)
{
boolean singleFkField = extent == 0 || customExtentFields != null;
return dialect.getAddForeignKeyConstraintString(
tableName, fkName,
singleFkField ? "parent__id" : "parent__id, list__index", // local fields
parentTableName,
singleFkField ? Session.PK : "parent__id, list__index", // foreign fields
INDENT, eoln) +
dialect.getDelimiter() + eoln;
}
/**
* Get drop FK index DDL statement.
*
* @param eoln
* OS-specific end of line terminator.
*
* @return The dialect specific DDL statement for dropping the FK index on a 'word' field.
*/
public String dropFkIndex(String eoln)
{
return dialect.getDropIndexString(true, fkIndexName, tableName) + dialect.getDelimiter() + eoln;
}
/**
* Get create FK index DDL statement
* @param eoln
* OS-specific end of line terminator.
* @param suffix
* dialect-specific statement suffix
* @return create FK index DDL statement
*/
public String createFkIndex(String eoln, String suffix)
{
return "create index " + fkIndexName + " on " + tableName + " (parent__id" +
(extent == 0 || (customExtentFields != null) ? "" : ", list__index" ) + ")" + suffix + eoln;
}
/**
* Get drop index on a 'word' field DDL statement.
*
* @param eoln
* OS-specific end of line terminator.
*
* @return The dialect specific DDL statement for dropping the index on a 'word' field.
*/
public String dropIndex(String eoln)
{
return dialect.getDropIndexString(true, indexName, tableName) + dialect.getDelimiter() + eoln;
}
/**
* Get create index on a 'word' field DDL statement
*
* @param eoln
* OS-specific end of line terminator.
*
* @param suffix
* The dialect-specific statement suffix
*
* @return The create-index on a 'word' field DDL statement
*/
public String createIndex(String eoln, String suffix)
{
return "create index " + indexName + " on " + tableName + " (word)" + suffix + eoln;
}
/** Word table data builder */
public static class Builder
{
/** The database objects' name builder. */
private final NameBuilder nb;
/** The original parent table name. */
private final String originalParentTableName;
/** The parent table name. */
private String parentTableName;
/** The field name. */
private final String fieldName;
/** Custom extent hints. */
private List<CustomExtentField> customExtentFields = null;
/** The extent size. */
private final long extent;
/** The field is case-sensitive flag. */
private final boolean caseSensitive;
/** The word table name. */
private String tableName;
/** The word table PK name. */
private final String pkName;
/** The word table FK index name. */
private String fkIndexName;
/** The word table FK constraint name. */
private String fkName;
/** The name of the word table index on 'word' field. */
private String indexName;
/** The parent table trigger function name. */
private String triggerFunctionName;
/** The parent table AFTER INSERT trigger name. */
private String afterInsertTriggerName;
/** The parent table AFTER UPDATE trigger name. */
private String afterUpdateTriggerName;
/**
* Constructor
*
* @param nb
* The database objects' name builder.
* @param parentTableName
* parent table name
* @param fieldName
* field name
* @param extent
* field extent
* @param caseSensitive
* field is case-sensitive flag
*/
public Builder(NameBuilder nb,
String parentTableName, String fieldName, long extent, boolean caseSensitive)
{
this.nb = nb;
this.originalParentTableName = parentTableName;
this.parentTableName = extent == 0 ? parentTableName : parentTableName + "__" + extent;
this.fieldName = fieldName;
this.extent = extent;
this.caseSensitive = caseSensitive;
this.tableName = nb.build(originalParentTableName, fieldName);
this.pkName = nb.build("pk", originalParentTableName, fieldName);
this.fkIndexName = nb.build("fkidx", originalParentTableName, fieldName);
this.fkName = nb.build("fk", originalParentTableName, fieldName);
this.indexName = nb.build("idx", originalParentTableName, fieldName);
this.triggerFunctionName = nb.build(originalParentTableName, fieldName, "trg");
this.afterInsertTriggerName = nb.build(originalParentTableName, fieldName, "ins");
this.afterUpdateTriggerName = nb.build(originalParentTableName, fieldName, "upd");
}
/**
* Set custom extent hints.
*
* @param value
* The custom extent hints.
*
* @return {@code this} Builder instance.
*/
public WordTable.Builder extentHintFields(List<ExtentHintField> value)
{
this.parentTableName = originalParentTableName;
AtomicInteger pos = new AtomicInteger(0);
this.customExtentFields = value.stream().
map(hint -> new CustomExtentField(
nb, parentTableName, hint.getName(), pos.incrementAndGet())).
collect(Collectors.toList());
return this;
}
/**
* Set word table name.
*
* @param value
* The word table name.
*
* @return {@code this} Builder instance.
*/
public WordTable.Builder tableName(String value)
{
this.tableName = value;
return this;
}
/**
* Set word table FK index name.
*
* @param value
* The word table FK index name.
*
* @return {@code this} Builder instance.
*/
public WordTable.Builder fkIndexName(String value)
{
this.fkIndexName = value;
return this;
}
/**
* Set word table FK constraint name.
*
* @param value
* word table FK constraint name.
* @return <code>this</code> Builder instance
*/
public WordTable.Builder fkName(String value)
{
this.fkName = value;
return this;
}
/**
* Set word table index name.
*
* @param value
* word table index name.
* @return <code>this</code> Builder instance
*/
public WordTable.Builder indexName(String value)
{
this.indexName = value;
return this;
}
/**
* Set word table trigger function name.
*
* @param value
* word table trigger function name,
* @return <code>this</code> Builder instance
*/
public WordTable.Builder triggerFunctionName(String value)
{
this.triggerFunctionName = value;
return this;
}
/**
* Set word table AFTER INSERT trigger name.
*
* @param value
* word table AFTER INSERT trigger name.
* @return <code>this</code> Builder instance
*/
public WordTable.Builder afterInsertTriggerName(String value)
{
this.afterInsertTriggerName = value;
return this;
}
/**
* Set word table AFTER UPDATE trigger name.
*
* @param value
* word table AFTER UPDATE trigger name.
* @return <code>this</code> Builder instance
*/
public WordTable.Builder afterUpdateTriggerName(String value)
{
this.afterUpdateTriggerName = value;
return this;
}
/**
* Build word table data.
*
* @param dialect
* The dialect used to generated DDL statements.
*
* @return An {@code WordTable} instance build based on the requested criteria.
*/
public WordTable build(Dialect dialect)
{
return new WordTable(dialect, parentTableName, fieldName, customExtentFields,
extent, caseSensitive,
tableName, pkName, fkIndexName, fkName, indexName,
triggerFunctionName, afterUpdateTriggerName, afterInsertTriggerName);
}
}
}