blob: ccc378f1f9ee6a4081c81ab7da14a2da78e416f2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.phoenix.query;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableKey;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.SchemaUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList;
import static org.apache.phoenix.util.PhoenixRuntime.TENANT_ID_ATTRIB;
/**
* PhoenixTestBuilder is a utility class using a Builder pattern.
* Facilitates the following creation patterns
* 1. Simple tables.
* 2. Global Views on tables.
* 3. Tenant Views on tables or global views.
* 4. Indexes global or local on all of the above.
* 5. Create multiple tenants
* 6. Multiple views for a tenant.
* Typical usage pattern when using this class is -
* 1. Create schema for the test.
* 2. Provide a DataSupplier for the above schema.
* 3. Write validations for your tests.
* PhoenixTestBuilder facilitates steps 1 and 2.
*/
public class PhoenixTestBuilder {
private static final Logger LOGGER = LoggerFactory.getLogger(PhoenixTestBuilder.class);
private static final int MAX_SUFFIX_VALUE = 1000000;
private static AtomicInteger NAME_SUFFIX = new AtomicInteger(0);
private static String generateUniqueName() {
int nextName = NAME_SUFFIX.incrementAndGet();
if (nextName >= MAX_SUFFIX_VALUE) {
throw new IllegalStateException("Used up all unique names");
}
return "T" + Integer.toString(MAX_SUFFIX_VALUE + nextName).substring(1);
}
/**
* @return a formatted string with nullable info
* for e.g "COL1 VARCHAR (NOT NULL), COL2 VARCHAR (NOT NULL), COL3 VARCHAR (NOT NULL)"
*/
private static String getColumnsAsString(List<String> columns, List<String> types,
boolean isPK) {
assert (columns.size() == types.size());
Joiner columnJoiner = Joiner.on(",");
Joiner typeJoiner = Joiner.on(" ");
List<String> columnDefinitions = Lists.newArrayList();
for (int colIndex = 0; colIndex < columns.size(); colIndex++) {
String column = columns.get(colIndex);
String datatype = types.get(colIndex);
if ((column != null) && (!column.isEmpty())) {
String
columnWithType =
isPK ?
typeJoiner.join(column, datatype, "NOT NULL") :
typeJoiner.join(column, datatype);
columnDefinitions.add(columnWithType);
}
}
return columnJoiner.join(columnDefinitions);
}
/**
* @return a formatted string with sort info
* for e.g "PK_COL1, PK_COL2 , PK_COL3 DESC"
*/
private static String getPKColumnsWithSort(List<String> pkColumns, List<String> sortTypes) {
assert (sortTypes == null || sortTypes.size() == pkColumns.size());
Joiner pkColumnJoiner = Joiner.on(",");
Joiner sortTypeJoiner = Joiner.on(" ");
List<String> pkColumnDefinitions = Lists.newArrayList();
for (int colIndex = 0; colIndex < pkColumns.size(); colIndex++) {
String column = pkColumns.get(colIndex);
String sorttype = sortTypes == null ? null : sortTypes.get(colIndex);
if ((column != null) && (!column.isEmpty())) {
String
columnWithSortType =
sorttype == null || sorttype.isEmpty() ?
column :
sortTypeJoiner.join(column, sorttype);
pkColumnDefinitions.add(columnWithSortType);
}
}
return pkColumnJoiner.join(pkColumnDefinitions);
}
/**
* @return a formatted string with CFs
* for e.g "A.COL1, B.COL2, C.COl3"
*/
private static String getFQColumnsAsString(List<String> columns, List<String> families) {
Joiner columnJoiner = Joiner.on(",");
return columnJoiner.join(getFQColumnsAsList(columns, families));
}
private static List<String> getFQColumnsAsList(List<String> columns, List<String> families) {
assert (columns.size() == families.size());
Joiner familyJoiner = Joiner.on(".");
List<String> columnDefinitions = Lists.newArrayList();
int colIndex = 0;
for (String family : families) {
String column = columns.get(colIndex++);
if ((column != null) && (!column.isEmpty())) {
columnDefinitions.add(((family != null) && (!family.isEmpty())) ?
familyJoiner.join(family, column) :
column);
}
}
return columnDefinitions;
}
/**
* @return a formatted string with data types
* for e.g => A.COL1 VARCHAR, A.COL2 VARCHAR, B.COL3 VARCHAR
*/
private static String getFQColumnsAsString(List<String> columns, List<String> families,
List<String> types) {
Joiner columnJoiner = Joiner.on(",");
return columnJoiner.join(getFQColumnsAsList(columns, families, types));
}
/*
* -----------------
* Helper methods
* -----------------
*/
private static List<String> getFQColumnsAsList(List<String> columns, List<String> families,
List<String> types) {
assert (columns.size() == families.size());
Joiner familyJoiner = Joiner.on(".");
Joiner typeJoiner = Joiner.on(" ");
List<String> columnDefinitions = Lists.newArrayList();
int colIndex = 0;
for (String family : families) {
String column = columns.get(colIndex);
String datatype = types.get(colIndex);
colIndex++;
if ((column != null) && (!column.isEmpty())) {
String columnWithType = typeJoiner.join(column, datatype);
columnDefinitions.add(((family != null) && (!family.isEmpty())) ?
familyJoiner.join(family, columnWithType) :
columnWithType);
}
}
return columnDefinitions;
}
// Test Data supplier interface for test writers to provide custom data.
public interface DataSupplier {
// return the values to be used for upserting data into the underlying entity.
List<Object> getValues(int rowIndex);
}
// A Data Writer to be used in tests to upsert sample data (@see TestDataSupplier) into the sample schema.
public interface DataWriter {
// returns the columns that need to be upserted,
// should match the #columns in TestDataSupplier::getValues().
List<String> getUpsertColumns();
void setUpsertColumns(List<String> upsertColumns);
// returns the partial/overridden set of columns to be used for upserts.
List<Integer> getColumnPositionsToUpdate();
void setColumnPositionsToUpdate(List<Integer> columnPositionsToUpdate);
// returns the connection to be used for upserting rows.
Connection getConnection();
void setConnection(Connection connection);
// returns the target entity - whether to use the table, global-view or the tenant-view.
String getTargetEntity();
void setTargetEntity(String targetEntity);
// return the data provider for this writer
DataSupplier getTestDataSupplier();
// template method to upsert rows using the above info.
void upsertRow(int rowIndex) throws SQLException;
void setDataSupplier(DataSupplier dataSupplier);
}
/**
* Test SchemaBuilder defaults.
*/
public static class DDLDefaults {
public static final int MAX_ROWS = 10000;
public static List<String> TABLE_PK_TYPES = asList("CHAR(15)", "CHAR(3)");
public static List<String> GLOBAL_VIEW_PK_TYPES = asList("CHAR(15)");
public static List<String> TENANT_VIEW_PK_TYPES = asList("CHAR(15)");
public static List<String> COLUMN_TYPES = asList("VARCHAR", "VARCHAR", "VARCHAR");
public static List<String> TABLE_COLUMNS = asList("COL1", "COL2", "COL3");
public static List<String> GLOBAL_VIEW_COLUMNS = asList("COL4", "COL5", "COL6");
public static List<String> TENANT_VIEW_COLUMNS = asList("COL7", "COL8", "COL9");
public static List<String> TABLE_COLUMN_FAMILIES = asList(null, null, null);
public static List<String> GLOBAL_VIEW_COLUMN_FAMILIES = asList(null, null, null);
public static List<String> TENANT_VIEW_COLUMN_FAMILIES = asList(null, null, null);
public static List<String> TABLE_PK_COLUMNS = asList("OID", "KP");
public static List<String> GLOBAL_VIEW_PK_COLUMNS = asList("ID");
public static List<String> TENANT_VIEW_PK_COLUMNS = asList("ZID");
public static List<String> TABLE_INDEX_COLUMNS = asList("COL1");
public static List<String> TABLE_INCLUDE_COLUMNS = asList("COL3");
public static List<String> GLOBAL_VIEW_INDEX_COLUMNS = asList("COL4");
public static List<String> GLOBAL_VIEW_INCLUDE_COLUMNS = asList("COL6");
public static List<String> TENANT_VIEW_INDEX_COLUMNS = asList("COL9");
public static List<String> TENANT_VIEW_INCLUDE_COLUMNS = asList("COL7");
public static String
DEFAULT_TABLE_PROPS =
"COLUMN_ENCODED_BYTES=0, MULTI_TENANT=true,DEFAULT_COLUMN_FAMILY='Z'";
public static String DEFAULT_TABLE_INDEX_PROPS = "";
public static String DEFAULT_GLOBAL_VIEW_PROPS = "";
public static String DEFAULT_GLOBAL_VIEW_INDEX_PROPS = "";
public static String DEFAULT_TENANT_VIEW_PROPS = "";
public static String DEFAULT_TENANT_VIEW_INDEX_PROPS = "";
public static String DEFAULT_KP = "0EC";
public static String DEFAULT_SCHEMA_NAME = "TEST_ENTITY";
public static String DEFAULT_TENANT_ID_FMT = "00D0t%03d%s";
public static String DEFAULT_CONNECT_URL = "jdbc:phoenix:localhost";
}
// Provides template method for upserting rows
public static abstract class AbstractDataWriter implements DataWriter {
public void upsertRow(int rowIndex) throws SQLException {
List<String> upsertColumns = Lists.newArrayList();
List<Object> upsertValues = Lists.newArrayList();
if (getColumnPositionsToUpdate().isEmpty()) {
upsertColumns.addAll(getUpsertColumns());
upsertValues.addAll(getTestDataSupplier().getValues(rowIndex));
} else {
List<String> tmpColumns = getUpsertColumns();
List<Object> tmpValues = getTestDataSupplier().getValues(rowIndex);
for (int i : getColumnPositionsToUpdate()) {
upsertColumns.add(tmpColumns.get(i));
upsertValues.add(tmpValues.get(i));
}
}
StringBuilder buf = new StringBuilder("UPSERT INTO ");
buf.append(getTargetEntity());
buf.append(" (").append(Joiner.on(",").join(upsertColumns)).append(") VALUES(");
for (int i = 0; i < upsertValues.size(); i++) {
buf.append("?,");
}
buf.setCharAt(buf.length() - 1, ')');
LOGGER.info(buf.toString());
Connection connection = getConnection();
try (PreparedStatement stmt = connection.prepareStatement(buf.toString())) {
for (int i = 0; i < upsertValues.size(); i++) {
stmt.setObject(i + 1, upsertValues.get(i));
}
stmt.execute();
connection.commit();
}
}
}
// An implementation of the TestDataWriter.
public static class BasicDataWriter extends AbstractDataWriter {
List<String> upsertColumns = Lists.newArrayList();
List<Integer> columnPositionsToUpdate = Lists.newArrayList();
DataSupplier dataSupplier;
Connection connection;
String targetEntity;
@Override public List<String> getUpsertColumns() {
return upsertColumns;
}
@Override public void setUpsertColumns(List<String> upsertColumns) {
this.upsertColumns = upsertColumns;
}
@Override public List<Integer> getColumnPositionsToUpdate() {
return columnPositionsToUpdate;
}
@Override public void setColumnPositionsToUpdate(List<Integer> columnPositionsToUpdate) {
this.columnPositionsToUpdate = columnPositionsToUpdate;
}
@Override public Connection getConnection() {
return connection;
}
@Override public void setConnection(Connection connection) {
this.connection = connection;
}
@Override public String getTargetEntity() {
return targetEntity;
}
@Override public void setTargetEntity(String targetEntity) {
this.targetEntity = targetEntity;
}
@Override public DataSupplier getTestDataSupplier() {
return dataSupplier;
}
@Override public void setDataSupplier(DataSupplier dataSupplier) {
this.dataSupplier = dataSupplier;
}
}
/**
* Schema builder for test writers to prepare various test scenarios.
* It can be used to define the following type of schemas -
* 1. Simple Table.
* 2. Table with Global and Tenant Views.
* 3. Table with Tenant Views
* The above entities can be supplemented with indexes (global or local)
* The builder also provides some reasonable defaults, but can be customized/overridden
* for specific test requirements.
*/
public static class SchemaBuilder {
private static final AtomicInteger TENANT_COUNTER = new AtomicInteger(0);
// variables holding the various options.
boolean tableEnabled = false;
boolean globalViewEnabled = false;
boolean tenantViewEnabled = false;
boolean tableIndexEnabled = false;
boolean globalViewIndexEnabled = false;
boolean tenantViewIndexEnabled = false;
boolean tableCreated = false;
boolean globalViewCreated = false;
boolean tenantViewCreated = false;
boolean tableIndexCreated = false;
boolean globalViewIndexCreated = false;
boolean tenantViewIndexCreated = false;
String url;
String entityKeyPrefix;
String entityTableName;
String entityGlobalViewName;
String entityTenantViewName;
PTable baseTable;
ConnectOptions connectOptions;
TableOptions tableOptions;
GlobalViewOptions globalViewOptions;
TenantViewOptions tenantViewOptions;
TableIndexOptions tableIndexOptions;
GlobalViewIndexOptions globalViewIndexOptions;
TenantViewIndexOptions tenantViewIndexOptions;
OtherOptions otherOptions;
DataOptions dataOptions;
public SchemaBuilder(String url) {
this.url = url;
}
public PTable getBaseTable() {
return baseTable;
}
void setBaseTable(PTable baseTable) {
this.baseTable = baseTable;
}
public String getUrl() {
return this.url;
}
public boolean isTableEnabled() {
return tableEnabled;
}
public boolean isGlobalViewEnabled() {
return globalViewEnabled;
}
public boolean isTenantViewEnabled() {
return tenantViewEnabled;
}
public boolean isTableIndexEnabled() {
return tableIndexEnabled;
}
public boolean isGlobalViewIndexEnabled() {
return globalViewIndexEnabled;
}
public boolean isTenantViewIndexEnabled() {
return tenantViewIndexEnabled;
}
/*
*****************************
* Setters and Getters
*****************************
*/
public boolean isTableCreated() {
return tableCreated;
}
public boolean isGlobalViewCreated() {
return globalViewCreated;
}
public boolean isTenantViewCreated() {
return tenantViewCreated;
}
public boolean isTableIndexCreated() {
return tableIndexCreated;
}
public boolean isGlobalViewIndexCreated() {
return globalViewIndexCreated;
}
public boolean isTenantViewIndexCreated() {
return tenantViewIndexCreated;
}
public String getEntityKeyPrefix() {
return entityKeyPrefix;
}
public String getEntityTableName() {
return entityTableName;
}
public String getEntityGlobalViewName() {
return entityGlobalViewName;
}
public String getEntityTenantViewName() {
return entityTenantViewName;
}
public ConnectOptions getConnectOptions() {
return connectOptions;
}
public TableOptions getTableOptions() {
return tableOptions;
}
public GlobalViewOptions getGlobalViewOptions() {
return globalViewOptions;
}
public TenantViewOptions getTenantViewOptions() {
return tenantViewOptions;
}
public TableIndexOptions getTableIndexOptions() {
return tableIndexOptions;
}
public GlobalViewIndexOptions getGlobalViewIndexOptions() {
return globalViewIndexOptions;
}
public TenantViewIndexOptions getTenantViewIndexOptions() {
return tenantViewIndexOptions;
}
public OtherOptions getOtherOptions() {
return otherOptions;
}
public DataOptions getDataOptions() {
return dataOptions;
}
// "CREATE TABLE IF NOT EXISTS " +
// tableName +
// "(" +
// dataColumns +
// " CONSTRAINT pk PRIMARY KEY (" + pk + ")
// ) " +
// (dataProps.isEmpty() ? "" : dataProps;
public SchemaBuilder withTableDefaults() {
tableEnabled = true;
tableCreated = false;
tableOptions = TableOptions.withDefaults();
return this;
}
// "CREATE TABLE IF NOT EXISTS " +
// tableName +
// "(" +
// dataColumns + " CONSTRAINT pk PRIMARY KEY (" + pk + ")
// ) " +
// (dataProps.isEmpty() ? "" : dataProps;
public SchemaBuilder withTableOptions(TableOptions options) {
tableEnabled = true;
tableCreated = false;
tableOptions = options;
return this;
}
// "CREATE VIEW IF NOT EXISTS " +
// globalViewName +
// AS SELECT * FROM " + tableName + " WHERE " + globalViewCondition;
public SchemaBuilder withSimpleGlobalView() {
globalViewEnabled = true;
globalViewCreated = false;
globalViewOptions = new GlobalViewOptions();
return this;
}
// "CREATE VIEW IF NOT EXISTS " +
// globalViewName +
// "(" +
// globalViewColumns + " CONSTRAINT pk PRIMARY KEY (" + globalViewPK + ")
// ) AS SELECT * FROM " + tableName + " WHERE " + globalViewCondition;
public SchemaBuilder withGlobalViewDefaults() {
globalViewEnabled = true;
globalViewCreated = false;
globalViewOptions = GlobalViewOptions.withDefaults();
return this;
}
// "CREATE VIEW IF NOT EXISTS " +
// globalViewName +
// "(" +
// globalViewColumns + " CONSTRAINT pk PRIMARY KEY (" + globalViewPK + ")
// ) AS SELECT * FROM " + tableName + " WHERE " + globalViewCondition;
public SchemaBuilder withGlobalViewOptions(GlobalViewOptions options) {
globalViewEnabled = true;
globalViewCreated = false;
globalViewOptions = options;
return this;
}
// "CREATE VIEW IF NOT EXISTS " + tenantViewName + AS SELECT * FROM " + globalViewName;
public SchemaBuilder withSimpleTenantView() {
tenantViewEnabled = true;
tenantViewCreated = false;
tenantViewOptions = new TenantViewOptions();
return this;
}
// "CREATE VIEW IF NOT EXISTS " +
// tenantViewName +
// "(" +
// tenantViewColumns + " CONSTRAINT pk PRIMARY KEY (" + tenantViewPK + ")
// ) AS SELECT * FROM " + globalViewName;
public SchemaBuilder withTenantViewDefaults() {
tenantViewEnabled = true;
tenantViewCreated = false;
tenantViewOptions = TenantViewOptions.withDefaults();
return this;
}
// "CREATE VIEW IF NOT EXISTS " +
// tenantViewName +
// "(" +
// tenantViewColumns + " CONSTRAINT pk PRIMARY KEY (" + tenantViewPK + ")
// ) AS SELECT * FROM " + globalViewName;
public SchemaBuilder withTenantViewOptions(TenantViewOptions options) {
tenantViewEnabled = true;
tenantViewCreated = false;
tenantViewOptions = options;
return this;
}
// "CREATE INDEX IF NOT EXISTS
// "IDX_T_T000001"
// ON "TEST_ENTITY"."T_T000001"(COL1) INCLUDE (COL3)"
public SchemaBuilder withTableIndexDefaults() {
tableIndexEnabled = true;
tableIndexCreated = false;
tableIndexOptions = TableIndexOptions.withDefaults();
return this;
}
public SchemaBuilder withTableIndexOptions(TableIndexOptions options) {
tableIndexEnabled = true;
tableIndexCreated = false;
tableIndexOptions = options;
return this;
}
public SchemaBuilder withGlobalViewIndexDefaults() {
globalViewIndexEnabled = true;
globalViewIndexCreated = false;
globalViewIndexOptions = GlobalViewIndexOptions.withDefaults();
return this;
}
public SchemaBuilder withGlobalViewIndexOptions(GlobalViewIndexOptions options) {
globalViewIndexEnabled = true;
globalViewIndexCreated = false;
globalViewIndexOptions = options;
return this;
}
public SchemaBuilder withTenantViewIndexDefaults() {
tenantViewIndexEnabled = true;
tenantViewIndexCreated = false;
tenantViewIndexOptions = TenantViewIndexOptions.withDefaults();
return this;
}
public SchemaBuilder withTenantViewIndexOptions(TenantViewIndexOptions options) {
tenantViewIndexEnabled = true;
tenantViewIndexCreated = false;
tenantViewIndexOptions = options;
return this;
}
public SchemaBuilder withOtherDefaults() {
this.otherOptions = OtherOptions.withDefaults();
return this;
}
public SchemaBuilder withOtherOptions(OtherOptions otherOptions) {
this.otherOptions = otherOptions;
return this;
}
public SchemaBuilder withDataOptionsDefaults() {
this.dataOptions = DataOptions.withDefaults();
return this;
}
public SchemaBuilder withDataOptions(DataOptions dataOptions) {
this.dataOptions = dataOptions;
return this;
}
public SchemaBuilder withConnectOptions(ConnectOptions connectOptions) {
this.connectOptions = connectOptions;
return this;
}
public SchemaBuilder withConnectDefaults() {
this.connectOptions = new ConnectOptions();
return this;
}
// Build method for creating new tenants with existing table,
// global and tenant view definitions.
// If the tenant view definition is not changed then
// the same view is created with different names for different tenants.
public void buildWithNewTenant() throws Exception {
tenantViewCreated = false;
tenantViewIndexCreated = false;
if (this.dataOptions == null) {
this.dataOptions = DataOptions.withDefaults();
}
this.dataOptions.tenantId =
String.format(dataOptions.tenantIdFormat, TENANT_COUNTER.incrementAndGet(),
dataOptions.uniqueName);
build();
}
// Build method for creating new tenant views with existing table,
// global and tenant view definitions.
// If the tenant view definition is not changed then
// the same view is created with different names.
public void buildNewView() throws Exception {
tenantViewCreated = false;
tenantViewIndexCreated = false;
if (this.dataOptions == null) {
this.dataOptions = DataOptions.withDefaults();
}
dataOptions.viewNumber = this.getDataOptions().getNextViewNumber();
build();
}
// The main build method for the builder.
public void build() throws Exception {
// Set defaults if not specified
if (this.otherOptions == null) {
this.otherOptions = OtherOptions.withDefaults();
}
if (this.dataOptions == null) {
this.dataOptions = DataOptions.withDefaults();
}
if (this.connectOptions == null) {
this.connectOptions = new ConnectOptions();
}
if (connectOptions.useGlobalConnectionOnly
&& connectOptions.useTenantConnectionForGlobalView) {
throw new IllegalArgumentException(
"useTenantConnectionForGlobalView and useGlobalConnectionOnly both cannot be true");
}
String tableName = SchemaUtil.getEscapedArgument("T_" + dataOptions.uniqueName);
String globalViewName = SchemaUtil.getEscapedArgument("V_" + dataOptions.uniqueName);
String
tableSchemaName =
tableEnabled ? SchemaUtil.getEscapedArgument(tableOptions.schemaName) : "";
String
globalViewSchemaName =
globalViewEnabled ?
SchemaUtil.getEscapedArgument(globalViewOptions.schemaName) :
"";
String
tenantViewSchemaName =
tenantViewEnabled ?
SchemaUtil.getEscapedArgument(tenantViewOptions.schemaName) :
"";
entityTableName = SchemaUtil.getTableName(tableSchemaName, tableName);
entityGlobalViewName = SchemaUtil.getTableName(globalViewSchemaName, globalViewName);
// Derive the keyPrefix to use.
entityKeyPrefix =
connectOptions.useGlobalConnectionOnly ?
(String.format("Z%02d", dataOptions.getViewNumber())) :
(tenantViewEnabled && !globalViewEnabled ?
(String.format("Z%02d", dataOptions.getViewNumber())) :
DDLDefaults.DEFAULT_KP);
String tenantViewName = SchemaUtil.getEscapedArgument(entityKeyPrefix);
entityTenantViewName = SchemaUtil.getTableName(tenantViewSchemaName, tenantViewName);
String globalViewCondition = String.format("KP = '%s'", entityKeyPrefix);
// Table and Table Index creation.
try (Connection globalConnection = getGlobalConnection()) {
if (tableEnabled && !tableCreated) {
globalConnection.createStatement()
.execute(buildCreateTableStmt(entityTableName));
tableCreated = true;
PTableKey
tableKey =
new PTableKey(null, SchemaUtil.normalizeFullTableName(entityTableName));
setBaseTable(
globalConnection.unwrap(PhoenixConnection.class).getTable(tableKey));
}
// Index on Table
if (tableIndexEnabled && !tableIndexCreated) {
String
indexOnTableName =
SchemaUtil.getEscapedArgument(String.format("IDX_%s",
SchemaUtil.normalizeIdentifier(tableName)));
globalConnection.createStatement().execute(
buildCreateIndexStmt(indexOnTableName, entityTableName,
tableIndexOptions.isLocal, tableIndexOptions.tableIndexColumns,
tableIndexOptions.tableIncludeColumns,
tableIndexOptions.indexProps));
tableIndexCreated = true;
}
}
// Global View and View Index creation.
try (Connection globalViewConnection = getGlobalViewConnection()) {
if (globalViewEnabled && !globalViewCreated) {
globalViewConnection.createStatement().execute(
buildCreateGlobalViewStmt(entityGlobalViewName, entityTableName,
globalViewCondition));
globalViewCreated = true;
}
// Index on GlobalView
if (globalViewIndexEnabled && !globalViewIndexCreated) {
String
indexOnGlobalViewName =
String.format("IDX_%s", SchemaUtil.normalizeIdentifier(globalViewName));
globalViewConnection.createStatement().execute(
buildCreateIndexStmt(indexOnGlobalViewName, entityGlobalViewName,
globalViewIndexOptions.isLocal,
globalViewIndexOptions.globalViewIndexColumns,
globalViewIndexOptions.globalViewIncludeColumns,
globalViewIndexOptions.indexProps));
globalViewIndexCreated = true;
}
}
// Tenant View and View Index creation.
try (Connection tenantConnection = getTenantConnection()) {
// Build tenant related views if any
if (tenantViewEnabled && !tenantViewCreated) {
String tenantViewCondition;
if (globalViewEnabled) {
tenantViewCondition =
String.format("SELECT * FROM %s", entityGlobalViewName);
} else if (tableEnabled) {
tenantViewCondition =
String.format("SELECT * FROM %s WHERE KP = '%s'", entityTableName,
entityKeyPrefix);
} else {
throw new IllegalStateException(
"Tenant View must be based on tables or global view");
}
tenantConnection.createStatement().execute(
buildCreateTenantViewStmt(entityTenantViewName, tenantViewCondition));
tenantViewCreated = true;
}
// Index on TenantView
if (tenantViewIndexEnabled && !tenantViewIndexCreated) {
String indexOnTenantViewName = String.format("IDX_%s", entityKeyPrefix);
tenantConnection.createStatement().execute(
buildCreateIndexStmt(indexOnTenantViewName, entityTenantViewName,
tenantViewIndexOptions.isLocal,
tenantViewIndexOptions.tenantViewIndexColumns,
tenantViewIndexOptions.tenantViewIncludeColumns,
tenantViewIndexOptions.indexProps));
tenantViewIndexCreated = true;
}
}
}
// Helper method for CREATE INDEX stmt builder.
private String buildCreateIndexStmt(String indexName, String onEntityName, boolean isLocal,
List<String> indexColumns, List<String> includeColumns, String indexProps) {
StringBuilder statement = new StringBuilder();
statement.append(isLocal ?
"CREATE LOCAL INDEX IF NOT EXISTS " :
"CREATE INDEX IF NOT EXISTS ")
.append(indexName)
.append(" ON ")
.append(onEntityName)
.append("(")
.append(Joiner.on(",").join(indexColumns))
.append(") ")
.append(includeColumns.isEmpty() ?
"" :
"INCLUDE (" + Joiner.on(",").join(includeColumns) + ") ")
.append((indexProps.isEmpty() ? "" : indexProps));
LOGGER.info(statement.toString());
return statement.toString();
}
// Helper method for CREATE TABLE stmt builder.
private String buildCreateTableStmt(String fullTableName) {
StringBuilder statement = new StringBuilder();
StringBuilder tableDefinition = new StringBuilder();
if (!tableOptions.tablePKColumns.isEmpty() || !tableOptions.tableColumns.isEmpty()) {
tableDefinition.append(("("));
if (!tableOptions.tablePKColumns.isEmpty()) {
tableDefinition.append(getColumnsAsString(tableOptions.tablePKColumns,
tableOptions.tablePKColumnTypes, true));
}
if (!tableOptions.tableColumns.isEmpty()) {
tableDefinition.append(tableOptions.tablePKColumns.isEmpty() ? "" : ",")
.append(getFQColumnsAsString(tableOptions.tableColumns,
otherOptions.tableCFs, tableOptions.tableColumnTypes));
}
if (!tableOptions.tablePKColumns.isEmpty()) {
tableDefinition.append(" CONSTRAINT pk PRIMARY KEY ").append("(")
.append(getPKColumnsWithSort(tableOptions.tablePKColumns,
tableOptions.tablePKColumnSort)).append(")");
}
tableDefinition.append((")"));
}
statement.append("CREATE TABLE IF NOT EXISTS ").append(fullTableName)
.append(tableDefinition.toString()).append(" ")
.append((tableOptions.tableProps.isEmpty() ? "" : tableOptions.tableProps));
LOGGER.info(statement.toString());
return statement.toString();
}
// Helper method for CREATE VIEW (GLOBAL) stmt builder.
private String buildCreateGlobalViewStmt(String fullGlobalViewName, String fullTableName,
String globalViewCondition) {
StringBuilder statement = new StringBuilder();
StringBuilder viewDefinition = new StringBuilder();
if (!globalViewOptions.globalViewPKColumns.isEmpty()
|| !globalViewOptions.globalViewColumns.isEmpty()) {
viewDefinition.append(("("));
if (!globalViewOptions.globalViewPKColumns.isEmpty()) {
viewDefinition.append(getColumnsAsString(globalViewOptions.globalViewPKColumns,
globalViewOptions.globalViewPKColumnTypes, true));
}
if (!globalViewOptions.globalViewColumns.isEmpty()) {
viewDefinition
.append(globalViewOptions.globalViewPKColumns.isEmpty() ? "" : ",")
.append(getFQColumnsAsString(globalViewOptions.globalViewColumns,
otherOptions.globalViewCFs,
globalViewOptions.globalViewColumnTypes));
}
if (!globalViewOptions.globalViewPKColumns.isEmpty()) {
viewDefinition.append(" CONSTRAINT pk PRIMARY KEY ").append("(")
.append(getPKColumnsWithSort(globalViewOptions.globalViewPKColumns,
globalViewOptions.globalViewPKColumnSort)).append(")");
}
viewDefinition.append((")"));
}
statement.append("CREATE VIEW IF NOT EXISTS ").append(fullGlobalViewName)
.append(viewDefinition.toString()).append(" AS SELECT * FROM ")
.append(fullTableName).append(" WHERE ").append(globalViewCondition).append(" ")
.append((globalViewOptions.tableProps.isEmpty() ?
"" :
globalViewOptions.tableProps));
LOGGER.info(statement.toString());
return statement.toString();
}
// Helper method for CREATE VIEW (TENANT) stmt builder.
private String buildCreateTenantViewStmt(String fullTenantViewName,
String tenantViewCondition) {
StringBuilder statement = new StringBuilder();
StringBuilder viewDefinition = new StringBuilder();
if (!tenantViewOptions.tenantViewPKColumns.isEmpty()
|| !tenantViewOptions.tenantViewColumns.isEmpty()) {
viewDefinition.append(("("));
if (!tenantViewOptions.tenantViewPKColumns.isEmpty()) {
viewDefinition.append(getColumnsAsString(tenantViewOptions.tenantViewPKColumns,
tenantViewOptions.tenantViewPKColumnTypes, true));
}
if (!tenantViewOptions.tenantViewColumns.isEmpty()) {
viewDefinition
.append(tenantViewOptions.tenantViewPKColumns.isEmpty() ? "" : ",")
.append(getFQColumnsAsString(tenantViewOptions.tenantViewColumns,
otherOptions.tenantViewCFs,
tenantViewOptions.tenantViewColumnTypes));
}
if (!tenantViewOptions.tenantViewPKColumns.isEmpty()) {
viewDefinition.append(" CONSTRAINT pk PRIMARY KEY ").append("(")
.append(getPKColumnsWithSort(tenantViewOptions.tenantViewPKColumns,
tenantViewOptions.tenantViewPKColumnSort)).append(")");
}
viewDefinition.append((")"));
}
statement.append("CREATE VIEW IF NOT EXISTS ").append(fullTenantViewName)
.append(viewDefinition.toString()).append(" AS ").append(tenantViewCondition)
.append(" ").append((tenantViewOptions.tableProps.isEmpty() ?
"" :
tenantViewOptions.tableProps));
LOGGER.info(statement.toString());
return statement.toString();
}
Connection getGlobalConnection() throws SQLException {
return getPhoenixConnection(getUrl());
}
Connection getGlobalViewConnection() throws SQLException {
return getPhoenixConnection(connectOptions.useTenantConnectionForGlobalView ?
getUrl() + ';' + TENANT_ID_ATTRIB + '=' + dataOptions.tenantId :
getUrl());
}
Connection getTenantConnection() throws SQLException {
return getPhoenixConnection(connectOptions.useGlobalConnectionOnly ?
getUrl() :
getUrl() + ';' + TENANT_ID_ATTRIB + '=' + dataOptions.tenantId);
}
Connection getPhoenixConnection(String url) throws SQLException {
return getPhoenixConnection(url, connectOptions.connectProps);
}
Connection getPhoenixConnection(String url, Properties props) throws SQLException {
Connection phoenixConnection;
if (props == null) {
Properties connProps = PropertiesUtil.deepCopy(connectOptions.connectProps);
phoenixConnection = DriverManager.getConnection(url, connProps);
} else {
phoenixConnection = DriverManager.getConnection(url, props);
}
phoenixConnection.setAutoCommit(true);
return phoenixConnection;
}
/**
* Option holders for various statement generation.
*/
// Connect options.
public static class ConnectOptions {
Properties connectProps = new Properties();
boolean useGlobalConnectionOnly = false;
boolean useTenantConnectionForGlobalView = false;
/*
*****************************
* Setters and Getters
*****************************
*/
public Properties getConnectProps() {
return connectProps;
}
public void setConnectProps(Properties connectProps) {
this.connectProps = connectProps;
}
public boolean isUseGlobalConnectionOnly() {
return useGlobalConnectionOnly;
}
public void setUseGlobalConnectionOnly(boolean useGlobalConnectionOnly) {
this.useGlobalConnectionOnly = useGlobalConnectionOnly;
}
public boolean isUseTenantConnectionForGlobalView() {
return useTenantConnectionForGlobalView;
}
public void setUseTenantConnectionForGlobalView(
boolean useTenantConnectionForGlobalView) {
this.useTenantConnectionForGlobalView = useTenantConnectionForGlobalView;
}
}
// Table statement generation.
public static class TableOptions {
String schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
List<String> tableColumns = Lists.newArrayList();
List<String> tableColumnTypes = Lists.newArrayList();
List<String> tablePKColumns = Lists.newArrayList();
List<String> tablePKColumnTypes = Lists.newArrayList();
List<String> tablePKColumnSort;
String tableProps = DDLDefaults.DEFAULT_TABLE_PROPS;
/*
*****************************
* Setters and Getters
*****************************
*/
public static TableOptions withDefaults() {
TableOptions options = new TableOptions();
options.schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
options.tableColumns = Lists.newArrayList(DDLDefaults.TABLE_COLUMNS);
options.tableColumnTypes = Lists.newArrayList(DDLDefaults.COLUMN_TYPES);
options.tablePKColumns = Lists.newArrayList(DDLDefaults.TABLE_PK_COLUMNS);
options.tablePKColumnTypes = Lists.newArrayList(DDLDefaults.TABLE_PK_TYPES);
options.tableProps = DDLDefaults.DEFAULT_TABLE_PROPS;
return options;
}
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public List<String> getTableColumns() {
return tableColumns;
}
public void setTableColumns(List<String> tableColumns) {
this.tableColumns = tableColumns;
}
public List<String> getTableColumnTypes() {
return tableColumnTypes;
}
public void setTableColumnTypes(List<String> tableColumnTypes) {
this.tableColumnTypes = tableColumnTypes;
}
public List<String> getTablePKColumns() {
return tablePKColumns;
}
public void setTablePKColumns(List<String> tablePKColumns) {
this.tablePKColumns = tablePKColumns;
}
public List<String> getTablePKColumnTypes() {
return tablePKColumnTypes;
}
public void setTablePKColumnTypes(List<String> tablePKColumnTypes) {
this.tablePKColumnTypes = tablePKColumnTypes;
}
public List<String> getTablePKColumnSort() {
return tablePKColumnSort;
}
public void setTablePKColumnSort(List<String> tablePKColumnSort) {
this.tablePKColumnSort = tablePKColumnSort;
}
public String getTableProps() {
return tableProps;
}
public void setTableProps(String tableProps) {
this.tableProps = tableProps;
}
}
// Global View statement generation.
public static class GlobalViewOptions {
String schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
List<String> globalViewColumns = Lists.newArrayList();
List<String> globalViewColumnTypes = Lists.newArrayList();
List<String> globalViewPKColumns = Lists.newArrayList();
List<String> globalViewPKColumnTypes = Lists.newArrayList();
List<String> globalViewPKColumnSort;
String tableProps = DDLDefaults.DEFAULT_TENANT_VIEW_PROPS;
String globalViewCondition;
/*
*****************************
* Setters and Getters
*****************************
*/
public static GlobalViewOptions withDefaults() {
GlobalViewOptions options = new GlobalViewOptions();
options.schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
options.globalViewColumns = Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_COLUMNS);
options.globalViewColumnTypes = Lists.newArrayList(DDLDefaults.COLUMN_TYPES);
options.globalViewPKColumns =
Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_PK_COLUMNS);
options.globalViewPKColumnTypes =
Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_PK_TYPES);
options.tableProps = DDLDefaults.DEFAULT_GLOBAL_VIEW_PROPS;
options.globalViewCondition = "";
return options;
}
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public List<String> getGlobalViewColumns() {
return globalViewColumns;
}
public void setGlobalViewColumns(List<String> globalViewColumns) {
this.globalViewColumns = globalViewColumns;
}
public List<String> getGlobalViewColumnTypes() {
return globalViewColumnTypes;
}
public void setGlobalViewColumnTypes(List<String> globalViewColumnTypes) {
this.globalViewColumnTypes = globalViewColumnTypes;
}
public List<String> getGlobalViewPKColumns() {
return globalViewPKColumns;
}
public void setGlobalViewPKColumns(List<String> globalViewPKColumns) {
this.globalViewPKColumns = globalViewPKColumns;
}
public List<String> getGlobalViewPKColumnTypes() {
return globalViewPKColumnTypes;
}
public void setGlobalViewPKColumnTypes(List<String> globalViewPKColumnTypes) {
this.globalViewPKColumnTypes = globalViewPKColumnTypes;
}
public List<String> getGlobalViewPKColumnSort() {
return globalViewPKColumnSort;
}
public void setGlobalViewPKColumnSort(List<String> globalViewPKColumnSort) {
this.globalViewPKColumnSort = globalViewPKColumnSort;
}
public String getTableProps() {
return tableProps;
}
public void setTableProps(String tableProps) {
this.tableProps = tableProps;
}
public String getGlobalViewCondition() {
return globalViewCondition;
}
public void setGlobalViewCondition(String globalViewCondition) {
this.globalViewCondition = globalViewCondition;
}
}
// Tenant View statement generation.
public static class TenantViewOptions {
String schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
List<String> tenantViewColumns = Lists.newArrayList();
List<String> tenantViewColumnTypes = Lists.newArrayList();
List<String> tenantViewPKColumns = Lists.newArrayList();
List<String> tenantViewPKColumnTypes = Lists.newArrayList();
List<String> tenantViewPKColumnSort;
String tableProps = DDLDefaults.DEFAULT_TENANT_VIEW_PROPS;
/*
*****************************
* Setters and Getters
*****************************
*/
public static TenantViewOptions withDefaults() {
TenantViewOptions options = new TenantViewOptions();
options.schemaName = DDLDefaults.DEFAULT_SCHEMA_NAME;
options.tenantViewColumns = Lists.newArrayList(DDLDefaults.TENANT_VIEW_COLUMNS);
options.tenantViewColumnTypes = Lists.newArrayList(DDLDefaults.COLUMN_TYPES);
options.tenantViewPKColumns =
Lists.newArrayList(DDLDefaults.TENANT_VIEW_PK_COLUMNS);
options.tenantViewPKColumnTypes =
Lists.newArrayList(DDLDefaults.TENANT_VIEW_PK_TYPES);
options.tableProps = DDLDefaults.DEFAULT_TENANT_VIEW_PROPS;
return options;
}
public String getSchemaName() {
return schemaName;
}
public void setSchemaName(String schemaName) {
this.schemaName = schemaName;
}
public List<String> getTenantViewColumns() {
return tenantViewColumns;
}
public void setTenantViewColumns(List<String> tenantViewColumns) {
this.tenantViewColumns = tenantViewColumns;
}
public List<String> getTenantViewColumnTypes() {
return tenantViewColumnTypes;
}
public void setTenantViewColumnTypes(List<String> tenantViewColumnTypes) {
this.tenantViewColumnTypes = tenantViewColumnTypes;
}
public List<String> getTenantViewPKColumns() {
return tenantViewPKColumns;
}
public void setTenantViewPKColumns(List<String> tenantViewPKColumns) {
this.tenantViewPKColumns = tenantViewPKColumns;
}
public List<String> getTenantViewPKColumnTypes() {
return tenantViewPKColumnTypes;
}
public void setTenantViewPKColumnTypes(List<String> tenantViewPKColumnTypes) {
this.tenantViewPKColumnTypes = tenantViewPKColumnTypes;
}
public List<String> getTenantViewPKColumnSort() {
return tenantViewPKColumnSort;
}
public void setTenantViewPKColumnSort(List<String> tenantViewPKColumnSort) {
this.tenantViewPKColumnSort = tenantViewPKColumnSort;
}
public String getTableProps() {
return tableProps;
}
public void setTableProps(String tableProps) {
this.tableProps = tableProps;
}
}
// Table Index statement generation.
public static class TableIndexOptions {
List<String> tableIndexColumns = Lists.newArrayList();
List<String> tableIncludeColumns = Lists.newArrayList();
boolean isLocal = false;
String indexProps = "";
/*
*****************************
* Setters and Getters
*****************************
*/
public static TableIndexOptions withDefaults() {
TableIndexOptions options = new TableIndexOptions();
options.tableIndexColumns = Lists.newArrayList(DDLDefaults.TABLE_INDEX_COLUMNS);
options.tableIncludeColumns = Lists.newArrayList(DDLDefaults.TABLE_INCLUDE_COLUMNS);
options.indexProps = DDLDefaults.DEFAULT_TABLE_INDEX_PROPS;
return options;
}
public List<String> getTableIndexColumns() {
return tableIndexColumns;
}
public void setTableIndexColumns(List<String> tableIndexColumns) {
this.tableIndexColumns = tableIndexColumns;
}
public List<String> getTableIncludeColumns() {
return tableIncludeColumns;
}
public void setTableIncludeColumns(List<String> tableIncludeColumns) {
this.tableIncludeColumns = tableIncludeColumns;
}
public boolean isLocal() {
return isLocal;
}
public void setLocal(boolean local) {
isLocal = local;
}
public String getIndexProps() {
return indexProps;
}
public void setIndexProps(String indexProps) {
this.indexProps = indexProps;
}
}
// Global View Index statement generation.
public static class GlobalViewIndexOptions {
List<String> globalViewIndexColumns = Lists.newArrayList();
List<String> globalViewIncludeColumns = Lists.newArrayList();
boolean isLocal = false;
String indexProps = "";
/*
*****************************
* Setters and Getters
*****************************
*/
public static GlobalViewIndexOptions withDefaults() {
GlobalViewIndexOptions options = new GlobalViewIndexOptions();
options.globalViewIndexColumns =
Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_INDEX_COLUMNS);
options.globalViewIncludeColumns =
Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_INCLUDE_COLUMNS);
options.indexProps = DDLDefaults.DEFAULT_GLOBAL_VIEW_INDEX_PROPS;
return options;
}
public List<String> getGlobalViewIndexColumns() {
return globalViewIndexColumns;
}
public void setGlobalViewIndexColumns(List<String> globalViewIndexColumns) {
this.globalViewIndexColumns = globalViewIndexColumns;
}
public List<String> getGlobalViewIncludeColumns() {
return globalViewIncludeColumns;
}
public void setGlobalViewIncludeColumns(List<String> globalViewIncludeColumns) {
this.globalViewIncludeColumns = globalViewIncludeColumns;
}
public boolean isLocal() {
return isLocal;
}
public void setLocal(boolean local) {
isLocal = local;
}
public String getIndexProps() {
return indexProps;
}
public void setIndexProps(String indexProps) {
this.indexProps = indexProps;
}
}
// Tenant View Index statement generation.
public static class TenantViewIndexOptions {
List<String> tenantViewIndexColumns = Lists.newArrayList();
List<String> tenantViewIncludeColumns = Lists.newArrayList();
boolean isLocal = false;
String indexProps = "";
/*
*****************************
* Setters and Getters
*****************************
*/
public static TenantViewIndexOptions withDefaults() {
TenantViewIndexOptions options = new TenantViewIndexOptions();
options.tenantViewIndexColumns =
Lists.newArrayList(DDLDefaults.TENANT_VIEW_INDEX_COLUMNS);
options.tenantViewIncludeColumns =
Lists.newArrayList(DDLDefaults.TENANT_VIEW_INCLUDE_COLUMNS);
options.indexProps = DDLDefaults.DEFAULT_TENANT_VIEW_INDEX_PROPS;
return options;
}
public List<String> getTenantViewIndexColumns() {
return tenantViewIndexColumns;
}
public void setTenantViewIndexColumns(List<String> tenantViewIndexColumns) {
this.tenantViewIndexColumns = tenantViewIndexColumns;
}
public List<String> getTenantViewIncludeColumns() {
return tenantViewIncludeColumns;
}
public void setTenantViewIncludeColumns(List<String> tenantViewIncludeColumns) {
this.tenantViewIncludeColumns = tenantViewIncludeColumns;
}
public boolean isLocal() {
return isLocal;
}
public void setLocal(boolean local) {
isLocal = local;
}
public String getIndexProps() {
return indexProps;
}
public void setIndexProps(String indexProps) {
this.indexProps = indexProps;
}
}
public static class OtherOptions {
String testName;
List<String> tableCFs = Lists.newArrayList();
List<String> globalViewCFs = Lists.newArrayList();
List<String> tenantViewCFs = Lists.newArrayList();
/*
*****************************
* Setters and Getters
*****************************
*/
public static OtherOptions withDefaults() {
OtherOptions options = new OtherOptions();
options.tableCFs = Lists.newArrayList(DDLDefaults.TABLE_COLUMN_FAMILIES);
options.globalViewCFs = Lists.newArrayList(DDLDefaults.GLOBAL_VIEW_COLUMN_FAMILIES);
options.tenantViewCFs = Lists.newArrayList(DDLDefaults.TENANT_VIEW_COLUMN_FAMILIES);
return options;
}
public String getTestName() {
return testName;
}
public void setTestName(String testName) {
this.testName = testName;
}
public List<String> getTableCFs() {
return tableCFs;
}
public void setTableCFs(List<String> tableCFs) {
this.tableCFs = tableCFs;
}
public List<String> getGlobalViewCFs() {
return globalViewCFs;
}
public void setGlobalViewCFs(List<String> globalViewCFs) {
this.globalViewCFs = globalViewCFs;
}
public List<String> getTenantViewCFs() {
return tenantViewCFs;
}
public void setTenantViewCFs(List<String> tenantViewCFs) {
this.tenantViewCFs = tenantViewCFs;
}
}
public static class DataOptions {
String uniqueName = "";
String tenantIdFormat = DDLDefaults.DEFAULT_TENANT_ID_FMT;
int viewNumber = 0;
AtomicInteger viewCounter = new AtomicInteger(0);
String tenantId = "";
/*
*****************************
* Setters and Getters
*****************************
*/
public static DataOptions withDefaults() {
DataOptions options = new DataOptions();
options.uniqueName = generateUniqueName();
options.viewCounter = new AtomicInteger(0);
options.tenantId =
String.format(options.tenantIdFormat, TENANT_COUNTER.get(),
options.uniqueName);
return options;
}
public int getNextViewNumber() {
return viewNumber = viewCounter.incrementAndGet();
}
public int getViewNumber() {
return viewNumber;
}
public String getTenantIdFormat() {
return tenantIdFormat;
}
public void setTenantIdFormat(String tenantIdFormat) {
this.tenantIdFormat = tenantIdFormat;
}
public String getUniqueName() {
return uniqueName;
}
public void setUniqueName(String uniqueName) {
this.uniqueName = uniqueName;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
}
}
}