You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2017/09/29 01:24:35 UTC
[01/25] phoenix git commit: PHOENIX-4096 Disallow DML operations on
connections with CURRENT_SCN set
Repository: phoenix
Updated Branches:
refs/heads/master 45079c4ea -> dd3b7b6c0
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.java b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.java
index 79c316a..730f754 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/jdbc/PhoenixConnection.java
@@ -124,16 +124,12 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Lists;
-
/**
*
- * JDBC Connection implementation of Phoenix.
- * Currently the following are supported:
- * - Statement
- * - PreparedStatement
- * The connection may only be used with the following options:
- * - ResultSet.TYPE_FORWARD_ONLY
- * - Connection.TRANSACTION_READ_COMMITTED
+ * JDBC Connection implementation of Phoenix. Currently the following are
+ * supported: - Statement - PreparedStatement The connection may only be used
+ * with the following options: - ResultSet.TYPE_FORWARD_ONLY -
+ * Connection.TRANSACTION_READ_COMMITTED
*
*
* @since 0.1
@@ -147,14 +143,14 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
private final int mutateBatchSize;
private final long mutateBatchSizeBytes;
private final Long scn;
- private final boolean replayMutations;
+ private final boolean buildingIndex;
private MutationState mutationState;
private List<PhoenixStatement> statements = new ArrayList<>();
private boolean isAutoFlush = false;
private boolean isAutoCommit = false;
private PMetaData metaData;
private final PName tenantId;
- private final String datePattern;
+ private final String datePattern;
private final String timePattern;
private final String timestampPattern;
private int statementExecutionCounter;
@@ -170,7 +166,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
private final LinkedBlockingQueue<WeakReference<TableResultIterator>> scannerQueue;
private TableResultIteratorFactory tableResultIteratorFactory;
private boolean isRunningUpgrade;
-
+
static {
Tracing.addTraceMetricsSource();
}
@@ -181,8 +177,13 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
return props;
}
- public PhoenixConnection(PhoenixConnection connection, boolean isDescRowKeyOrderUpgrade, boolean isRunningUpgrade) throws SQLException {
- this(connection.getQueryServices(), connection.getURL(), connection.getClientInfo(), connection.metaData, connection.getMutationState(), isDescRowKeyOrderUpgrade, isRunningUpgrade, connection.replayMutations);
+ public PhoenixConnection(PhoenixConnection connection,
+ boolean isDescRowKeyOrderUpgrade, boolean isRunningUpgrade)
+ throws SQLException {
+ this(connection.getQueryServices(), connection.getURL(), connection
+ .getClientInfo(), connection.metaData, connection
+ .getMutationState(), isDescRowKeyOrderUpgrade,
+ isRunningUpgrade, connection.buildingIndex);
this.isAutoCommit = connection.isAutoCommit;
this.isAutoFlush = connection.isAutoFlush;
this.sampler = connection.sampler;
@@ -190,93 +191,140 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
public PhoenixConnection(PhoenixConnection connection) throws SQLException {
- this(connection, connection.isDescVarLengthRowKeyUpgrade(), connection.isRunningUpgrade());
+ this(connection, connection.isDescVarLengthRowKeyUpgrade(), connection
+ .isRunningUpgrade());
}
-
- public PhoenixConnection(PhoenixConnection connection, MutationState mutationState) throws SQLException {
- this(connection.getQueryServices(), connection.getURL(), connection.getClientInfo(), connection.getMetaDataCache(), mutationState, connection.isDescVarLengthRowKeyUpgrade(), connection.isRunningUpgrade(), connection.replayMutations);
+
+ public PhoenixConnection(PhoenixConnection connection,
+ MutationState mutationState) throws SQLException {
+ this(connection.getQueryServices(), connection.getURL(), connection
+ .getClientInfo(), connection.getMetaDataCache(), mutationState,
+ connection.isDescVarLengthRowKeyUpgrade(), connection
+ .isRunningUpgrade(), connection.buildingIndex);
}
-
- public PhoenixConnection(PhoenixConnection connection, long scn) throws SQLException {
+
+ public PhoenixConnection(PhoenixConnection connection, long scn)
+ throws SQLException {
this(connection.getQueryServices(), connection, scn);
}
-
- public PhoenixConnection(ConnectionQueryServices services, PhoenixConnection connection, long scn) throws SQLException {
- this(services, connection.getURL(), newPropsWithSCN(scn,connection.getClientInfo()), connection.metaData, connection.getMutationState(), connection.isDescVarLengthRowKeyUpgrade(), connection.isRunningUpgrade(), connection.replayMutations);
+
+ public PhoenixConnection(ConnectionQueryServices services,
+ PhoenixConnection connection, long scn) throws SQLException {
+ this(services, connection.getURL(), newPropsWithSCN(scn,
+ connection.getClientInfo()), connection.metaData, connection
+ .getMutationState(), connection.isDescVarLengthRowKeyUpgrade(),
+ connection.isRunningUpgrade(), connection.buildingIndex);
this.isAutoCommit = connection.isAutoCommit;
this.isAutoFlush = connection.isAutoFlush;
this.sampler = connection.sampler;
this.statementExecutionCounter = connection.statementExecutionCounter;
}
-
- public PhoenixConnection(ConnectionQueryServices services, String url, Properties info, PMetaData metaData) throws SQLException {
+
+ public PhoenixConnection(ConnectionQueryServices services, String url,
+ Properties info, PMetaData metaData) throws SQLException {
this(services, url, info, metaData, null, false, false, false);
}
-
- public PhoenixConnection(PhoenixConnection connection, ConnectionQueryServices services, Properties info) throws SQLException {
- this(services, connection.url, info, connection.metaData, null, connection.isDescVarLengthRowKeyUpgrade(), connection.isRunningUpgrade(), connection.replayMutations);
+
+ public PhoenixConnection(PhoenixConnection connection,
+ ConnectionQueryServices services, Properties info)
+ throws SQLException {
+ this(services, connection.url, info, connection.metaData, null,
+ connection.isDescVarLengthRowKeyUpgrade(), connection
+ .isRunningUpgrade(), connection.buildingIndex);
}
-
- private PhoenixConnection(ConnectionQueryServices services, String url, Properties info, PMetaData metaData, MutationState mutationState, boolean isDescVarLengthRowKeyUpgrade, boolean isRunningUpgrade, boolean replayMutations) throws SQLException {
+
+ private PhoenixConnection(ConnectionQueryServices services, String url,
+ Properties info, PMetaData metaData, MutationState mutationState,
+ boolean isDescVarLengthRowKeyUpgrade, boolean isRunningUpgrade,
+ boolean buildingIndex) throws SQLException {
GLOBAL_PHOENIX_CONNECTIONS_ATTEMPTED_COUNTER.increment();
this.url = url;
this.isDescVarLengthRowKeyUpgrade = isDescVarLengthRowKeyUpgrade;
- // Filter user provided properties based on property policy, if provided.
+ // Filter user provided properties based on property policy, if
+ // provided.
PropertyPolicyProvider.getPropertyPolicy().evaluate(info);
// Copy so client cannot change
- this.info = info == null ? new Properties() : PropertiesUtil.deepCopy(info);
+ this.info = info == null ? new Properties() : PropertiesUtil
+ .deepCopy(info);
final PName tenantId = JDBCUtil.getTenantId(url, info);
if (this.info.isEmpty() && tenantId == null) {
this.services = services;
} else {
- // Create child services keyed by tenantId to track resource usage for
+ // Create child services keyed by tenantId to track resource usage
+ // for
// a tenantId for all connections on this JVM.
if (tenantId != null) {
- services = services.getChildQueryServices(tenantId.getBytesPtr());
+ services = services.getChildQueryServices(tenantId
+ .getBytesPtr());
}
ReadOnlyProps currentProps = services.getProps();
- final ReadOnlyProps augmentedProps = currentProps.addAll(filterKnownNonProperties(this.info));
- this.services = augmentedProps == currentProps ? services : new DelegateConnectionQueryServices(services) {
+ final ReadOnlyProps augmentedProps = currentProps
+ .addAll(filterKnownNonProperties(this.info));
+ this.services = augmentedProps == currentProps ? services
+ : new DelegateConnectionQueryServices(services) {
@Override
public ReadOnlyProps getProps() {
return augmentedProps;
}
};
}
-
+
Long scnParam = JDBCUtil.getCurrentSCN(url, this.info);
checkScn(scnParam);
- Long replayAtParam = JDBCUtil.getReplayAt(url, this.info);
- checkReplayAt(replayAtParam);
- checkScnAndReplayAtEquality(scnParam,replayAtParam);
-
- this.scn = scnParam != null ? scnParam : replayAtParam;
- this.replayMutations = replayMutations || replayAtParam != null;
- this.isAutoFlush = this.services.getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED, QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)
- && this.services.getProps().getBoolean(QueryServices.AUTO_FLUSH_ATTRIB, QueryServicesOptions.DEFAULT_AUTO_FLUSH) ;
+ Long buildIndexAtParam = JDBCUtil.getBuildIndexSCN(url, this.info);
+ checkBuildIndexAt(buildIndexAtParam);
+ checkScnAndBuildIndexAtEquality(scnParam, buildIndexAtParam);
+
+ this.scn = scnParam != null ? scnParam : buildIndexAtParam;
+ this.buildingIndex = buildingIndex || buildIndexAtParam != null;
+ this.isAutoFlush = this.services.getProps().getBoolean(
+ QueryServices.TRANSACTIONS_ENABLED,
+ QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)
+ && this.services.getProps().getBoolean(
+ QueryServices.AUTO_FLUSH_ATTRIB,
+ QueryServicesOptions.DEFAULT_AUTO_FLUSH);
this.isAutoCommit = JDBCUtil.getAutoCommit(
- url, this.info,
+ url,
+ this.info,
this.services.getProps().getBoolean(
QueryServices.AUTO_COMMIT_ATTRIB,
QueryServicesOptions.DEFAULT_AUTO_COMMIT));
- this.consistency = JDBCUtil.getConsistencyLevel(url, this.info, this.services.getProps()
- .get(QueryServices.CONSISTENCY_ATTRIB,
- QueryServicesOptions.DEFAULT_CONSISTENCY_LEVEL));
- // currently we are not resolving schema set through property, so if schema doesn't exists ,connection will not fail
+ this.consistency = JDBCUtil.getConsistencyLevel(
+ url,
+ this.info,
+ this.services.getProps().get(QueryServices.CONSISTENCY_ATTRIB,
+ QueryServicesOptions.DEFAULT_CONSISTENCY_LEVEL));
+ // currently we are not resolving schema set through property, so if
+ // schema doesn't exists ,connection will not fail
// but queries may fail
- this.schema = JDBCUtil.getSchema(url, this.info,
- this.services.getProps().get(QueryServices.SCHEMA_ATTRIB, QueryServicesOptions.DEFAULT_SCHEMA));
+ this.schema = JDBCUtil.getSchema(
+ url,
+ this.info,
+ this.services.getProps().get(QueryServices.SCHEMA_ATTRIB,
+ QueryServicesOptions.DEFAULT_SCHEMA));
this.tenantId = tenantId;
- this.mutateBatchSize = JDBCUtil.getMutateBatchSize(url, this.info, this.services.getProps());
- this.mutateBatchSizeBytes = JDBCUtil.getMutateBatchSizeBytes(url, this.info, this.services.getProps());
- datePattern = this.services.getProps().get(QueryServices.DATE_FORMAT_ATTRIB, DateUtil.DEFAULT_DATE_FORMAT);
- timePattern = this.services.getProps().get(QueryServices.TIME_FORMAT_ATTRIB, DateUtil.DEFAULT_TIME_FORMAT);
- timestampPattern = this.services.getProps().get(QueryServices.TIMESTAMP_FORMAT_ATTRIB, DateUtil.DEFAULT_TIMESTAMP_FORMAT);
- String numberPattern = this.services.getProps().get(QueryServices.NUMBER_FORMAT_ATTRIB, NumberUtil.DEFAULT_NUMBER_FORMAT);
- int maxSize = this.services.getProps().getInt(QueryServices.MAX_MUTATION_SIZE_ATTRIB,QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE);
- int maxSizeBytes = this.services.getProps().getInt(QueryServices.MAX_MUTATION_SIZE_BYTES_ATTRIB,QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE_BYTES);
+ this.mutateBatchSize = JDBCUtil.getMutateBatchSize(url, this.info,
+ this.services.getProps());
+ this.mutateBatchSizeBytes = JDBCUtil.getMutateBatchSizeBytes(url,
+ this.info, this.services.getProps());
+ datePattern = this.services.getProps().get(
+ QueryServices.DATE_FORMAT_ATTRIB, DateUtil.DEFAULT_DATE_FORMAT);
+ timePattern = this.services.getProps().get(
+ QueryServices.TIME_FORMAT_ATTRIB, DateUtil.DEFAULT_TIME_FORMAT);
+ timestampPattern = this.services.getProps().get(
+ QueryServices.TIMESTAMP_FORMAT_ATTRIB,
+ DateUtil.DEFAULT_TIMESTAMP_FORMAT);
+ String numberPattern = this.services.getProps().get(
+ QueryServices.NUMBER_FORMAT_ATTRIB,
+ NumberUtil.DEFAULT_NUMBER_FORMAT);
+ int maxSize = this.services.getProps().getInt(
+ QueryServices.MAX_MUTATION_SIZE_ATTRIB,
+ QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE);
+ int maxSizeBytes = this.services.getProps().getInt(
+ QueryServices.MAX_MUTATION_SIZE_BYTES_ATTRIB,
+ QueryServicesOptions.DEFAULT_MAX_MUTATION_SIZE_BYTES);
Format dateFormat = DateUtil.getDateFormatter(datePattern);
Format timeFormat = DateUtil.getDateFormatter(timePattern);
Format timestampFormat = DateUtil.getDateFormatter(timestampPattern);
@@ -286,28 +334,36 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
formatters.put(PUnsignedDate.INSTANCE, dateFormat);
formatters.put(PUnsignedTime.INSTANCE, timeFormat);
formatters.put(PUnsignedTimestamp.INSTANCE, timestampFormat);
- formatters.put(PDecimal.INSTANCE, FunctionArgumentType.NUMERIC.getFormatter(numberPattern));
- // We do not limit the metaData on a connection less than the global one,
+ formatters.put(PDecimal.INSTANCE,
+ FunctionArgumentType.NUMERIC.getFormatter(numberPattern));
+ // We do not limit the metaData on a connection less than the global
+ // one,
// as there's not much that will be cached here.
Pruner pruner = new Pruner() {
@Override
public boolean prune(PTable table) {
- long maxTimestamp = scn == null ? HConstants.LATEST_TIMESTAMP : scn;
- return (table.getType() != PTableType.SYSTEM &&
- ( table.getTimeStamp() >= maxTimestamp ||
- (table.getTenantId()!=null && ! Objects.equal(tenantId, table.getTenantId()))));
+ long maxTimestamp = scn == null ? HConstants.LATEST_TIMESTAMP
+ : scn;
+ return (table.getType() != PTableType.SYSTEM && (table
+ .getTimeStamp() >= maxTimestamp || (table.getTenantId() != null && !Objects
+ .equal(tenantId, table.getTenantId()))));
}
-
+
@Override
public boolean prune(PFunction function) {
- long maxTimestamp = scn == null ? HConstants.LATEST_TIMESTAMP : scn;
- return ( function.getTimeStamp() >= maxTimestamp ||
- (function.getTenantId()!=null && ! Objects.equal(tenantId, function.getTenantId())));
+ long maxTimestamp = scn == null ? HConstants.LATEST_TIMESTAMP
+ : scn;
+ return (function.getTimeStamp() >= maxTimestamp || (function
+ .getTenantId() != null && !Objects.equal(tenantId,
+ function.getTenantId())));
}
};
- this.isRequestLevelMetricsEnabled = JDBCUtil.isCollectingRequestLevelMetricsEnabled(url, info, this.services.getProps());
- this.mutationState = mutationState == null ? newMutationState(maxSize, maxSizeBytes) : new MutationState(mutationState);
+ this.isRequestLevelMetricsEnabled = JDBCUtil
+ .isCollectingRequestLevelMetricsEnabled(url, info,
+ this.services.getProps());
+ this.mutationState = mutationState == null ? newMutationState(maxSize,
+ maxSizeBytes) : new MutationState(mutationState);
this.metaData = metaData;
this.metaData.pruneTables(pruner);
this.metaData.pruneFunctions(pruner);
@@ -321,22 +377,28 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
this.isRunningUpgrade = isRunningUpgrade;
GLOBAL_OPEN_PHOENIX_CONNECTIONS.increment();
}
-
+
private static void checkScn(Long scnParam) throws SQLException {
if (scnParam != null && scnParam < 0) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_SCN).build().buildException();
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_SCN)
+ .build().buildException();
}
}
- private static void checkReplayAt(Long replayAtParam) throws SQLException {
+ private static void checkBuildIndexAt(Long replayAtParam) throws SQLException {
if (replayAtParam != null && replayAtParam < 0) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.INVALID_REPLAY_AT).build().buildException();
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.INVALID_REPLAY_AT).build()
+ .buildException();
}
}
- private static void checkScnAndReplayAtEquality(Long scnParam, Long replayAt) throws SQLException {
+ private static void checkScnAndBuildIndexAtEquality(Long scnParam, Long replayAt)
+ throws SQLException {
if (scnParam != null && replayAt != null && !scnParam.equals(replayAt)) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.UNEQUAL_SCN_AND_REPLAY_AT).build().buildException();
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.UNEQUAL_SCN_AND_BUILD_INDEX_AT).build()
+ .buildException();
}
}
@@ -354,21 +416,22 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
private ImmutableMap<String, String> getImmutableCustomTracingAnnotations() {
- Builder<String, String> result = ImmutableMap.builder();
- result.putAll(JDBCUtil.getAnnotations(url, info));
- if (getSCN() != null) {
- result.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, getSCN().toString());
- }
- if (getTenantId() != null) {
- result.put(PhoenixRuntime.TENANT_ID_ATTRIB, getTenantId().getString());
- }
- return result.build();
+ Builder<String, String> result = ImmutableMap.builder();
+ result.putAll(JDBCUtil.getAnnotations(url, info));
+ if (getSCN() != null) {
+ result.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, getSCN().toString());
+ }
+ if (getTenantId() != null) {
+ result.put(PhoenixRuntime.TENANT_ID_ATTRIB, getTenantId()
+ .getString());
+ }
+ return result.build();
}
public Sampler<?> getSampler() {
return this.sampler;
}
-
+
public void setSampler(Sampler<?> sampler) throws SQLException {
this.sampler = sampler;
}
@@ -377,7 +440,8 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
return customTracingAnnotations;
}
- public int executeStatements(Reader reader, List<Object> binds, PrintStream out) throws IOException, SQLException {
+ public int executeStatements(Reader reader, List<Object> binds,
+ PrintStream out) throws IOException, SQLException {
int bindsOffset = 0;
int nStatements = 0;
PhoenixStatementParser parser = new PhoenixStatementParser(reader);
@@ -386,9 +450,10 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
PhoenixPreparedStatement stmt = null;
try {
stmt = new PhoenixPreparedStatement(this, parser);
- ParameterMetaData paramMetaData = stmt.getParameterMetaData();
+ ParameterMetaData paramMetaData = stmt
+ .getParameterMetaData();
for (int i = 0; i < paramMetaData.getParameterCount(); i++) {
- stmt.setObject(i+1, binds.get(bindsOffset+i));
+ stmt.setObject(i + 1, binds.get(bindsOffset + i));
}
long start = System.currentTimeMillis();
boolean isQuery = stmt.execute();
@@ -404,20 +469,30 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
ResultSetMetaData md = rs.getMetaData();
columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++) {
- int displayWidth = md.getColumnDisplaySize(i);
+ int displayWidth = md
+ .getColumnDisplaySize(i);
String label = md.getColumnLabel(i);
if (md.isSigned(i)) {
- out.print(displayWidth < label.length() ? label.substring(0,displayWidth) : Strings.padStart(label, displayWidth, ' '));
+ out.print(displayWidth < label.length() ? label
+ .substring(0, displayWidth)
+ : Strings.padStart(label,
+ displayWidth, ' '));
out.print(' ');
} else {
- out.print(displayWidth < label.length() ? label.substring(0,displayWidth) : Strings.padEnd(md.getColumnLabel(i), displayWidth, ' '));
+ out.print(displayWidth < label.length() ? label
+ .substring(0, displayWidth)
+ : Strings.padEnd(
+ md.getColumnLabel(i),
+ displayWidth, ' '));
out.print(' ');
}
}
out.println();
for (int i = 1; i <= columnCount; i++) {
- int displayWidth = md.getColumnDisplaySize(i);
- out.print(Strings.padStart("", displayWidth,'-'));
+ int displayWidth = md
+ .getColumnDisplaySize(i);
+ out.print(Strings.padStart("",
+ displayWidth, '-'));
out.print(' ');
}
out.println();
@@ -426,13 +501,19 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
if (out != null) {
ResultSetMetaData md = rs.getMetaData();
for (int i = 1; i <= columnCount; i++) {
- int displayWidth = md.getColumnDisplaySize(i);
+ int displayWidth = md
+ .getColumnDisplaySize(i);
String value = rs.getString(i);
- String valueString = value == null ? QueryConstants.NULL_DISPLAY_TEXT : value;
+ String valueString = value == null ? QueryConstants.NULL_DISPLAY_TEXT
+ : value;
if (md.isSigned(i)) {
- out.print(Strings.padStart(valueString, displayWidth, ' '));
+ out.print(Strings.padStart(
+ valueString, displayWidth,
+ ' '));
} else {
- out.print(Strings.padEnd(valueString, displayWidth, ' '));
+ out.print(Strings.padEnd(
+ valueString, displayWidth,
+ ' '));
}
out.print(' ');
}
@@ -440,10 +521,12 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
} while (rs.next());
}
- } else if (out != null){
+ } else if (out != null) {
int updateCount = stmt.getUpdateCount();
if (updateCount >= 0) {
- out.println((updateCount == 0 ? "no" : updateCount) + (updateCount == 1 ? " row " : " rows ") + stmt.getUpdateOperation().toString());
+ out.println((updateCount == 0 ? "no" : updateCount)
+ + (updateCount == 1 ? " row " : " rows ")
+ + stmt.getUpdateOperation().toString());
}
}
bindsOffset += paramMetaData.getParameterCount();
@@ -464,59 +547,59 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
public @Nullable PName getTenantId() {
return tenantId;
}
-
+
public Long getSCN() {
return scn;
}
-
- public boolean isReplayMutations() {
- return replayMutations;
+
+ public boolean isBuildingIndex() {
+ return buildingIndex;
}
-
+
public int getMutateBatchSize() {
return mutateBatchSize;
}
- public long getMutateBatchSizeBytes(){
+ public long getMutateBatchSizeBytes() {
return mutateBatchSizeBytes;
}
public PMetaData getMetaDataCache() {
return metaData;
}
-
+
public PTable getTable(PTableKey key) throws TableNotFoundException {
- return metaData.getTableRef(key).getTable();
+ return metaData.getTableRef(key).getTable();
}
-
+
public PTableRef getTableRef(PTableKey key) throws TableNotFoundException {
- return metaData.getTableRef(key);
+ return metaData.getTableRef(key);
}
protected MutationState newMutationState(int maxSize, int maxSizeBytes) {
return new MutationState(maxSize, maxSizeBytes, this);
}
-
+
public MutationState getMutationState() {
return mutationState;
}
-
+
public String getDatePattern() {
return datePattern;
}
-
+
public Format getFormatter(PDataType type) {
return formatters.get(type);
}
-
+
public String getURL() {
return url;
}
-
+
public ConnectionQueryServices getQueryServices() {
return services;
}
-
+
@Override
public void clearWarnings() throws SQLException {
}
@@ -538,13 +621,15 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
}
}
-
+
private void checkOpen() throws SQLException {
if (isClosed) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.CONNECTION_CLOSED).build().buildException();
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.CONNECTION_CLOSED).build()
+ .buildException();
}
}
-
+
@Override
public void close() throws SQLException {
if (isClosed) {
@@ -580,10 +665,12 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ public Array createArrayOf(String typeName, Object[] elements)
+ throws SQLException {
checkOpen();
- PDataType arrayPrimitiveType = PDataType.fromSqlTypeName(typeName);
- return PArrayDataType.instantiatePhoenixArray(arrayPrimitiveType, elements);
+ PDataType arrayPrimitiveType = PDataType.fromSqlTypeName(typeName);
+ return PArrayDataType.instantiatePhoenixArray(arrayPrimitiveType,
+ elements);
}
@Override
@@ -609,7 +696,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
public List<PhoenixStatement> getStatements() {
return statements;
}
-
+
@Override
public Statement createStatement() throws SQLException {
checkOpen();
@@ -620,28 +707,33 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
/**
* Back-door way to inject processing into walking through a result set
+ *
* @param statementFactory
* @return PhoenixStatement
* @throws SQLException
*/
- public PhoenixStatement createStatement(PhoenixStatementFactory statementFactory) throws SQLException {
+ public PhoenixStatement createStatement(
+ PhoenixStatementFactory statementFactory) throws SQLException {
PhoenixStatement statement = statementFactory.newStatement(this);
statements.add(statement);
return statement;
}
@Override
- public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ public Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException {
checkOpen();
- if (resultSetType != ResultSet.TYPE_FORWARD_ONLY || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
+ if (resultSetType != ResultSet.TYPE_FORWARD_ONLY
+ || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw new SQLFeatureNotSupportedException();
}
return createStatement();
}
@Override
- public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
- throws SQLException {
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
checkOpen();
if (resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
throw new SQLFeatureNotSupportedException();
@@ -650,7 +742,8 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ public Struct createStruct(String typeName, Object[] attributes)
+ throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@@ -664,8 +757,12 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
public void setAutoFlush(boolean autoFlush) throws SQLException {
- if (autoFlush && !this.services.getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED, QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_AUTO_FLUSH)
+ if (autoFlush
+ && !this.services.getProps().getBoolean(
+ QueryServices.TRANSACTIONS_ENABLED,
+ QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)) {
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_AUTO_FLUSH)
.build().buildException();
}
this.isAutoFlush = autoFlush;
@@ -674,20 +771,26 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
public void flush() throws SQLException {
mutationState.sendUncommitted();
}
-
- public void setTransactionContext(PhoenixTransactionContext txContext) throws SQLException {
- if (!this.services.getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED, QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_TX_CONTEXT)
+
+ public void setTransactionContext(PhoenixTransactionContext txContext)
+ throws SQLException {
+ if (!this.services.getProps().getBoolean(
+ QueryServices.TRANSACTIONS_ENABLED,
+ QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED)) {
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_TX_CONTEXT)
.build().buildException();
}
this.mutationState.rollback();
- this.mutationState = new MutationState(this.mutationState.getMaxSize(), this.mutationState.getMaxSizeBytes(), this, txContext);
-
- // Write data to HBase after each statement execution as the commit may not
+ this.mutationState = new MutationState(this.mutationState.getMaxSize(),
+ this.mutationState.getMaxSizeBytes(), this, txContext);
+
+ // Write data to HBase after each statement execution as the commit may
+ // not
// come through Phoenix APIs.
setAutoFlush(true);
}
-
+
public Consistency getConsistency() {
return this.consistency;
}
@@ -698,7 +801,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public Properties getClientInfo() throws SQLException {
+ public Properties getClientInfo() throws SQLException {
// Defensive copy so client cannot change
return new Properties(info);
}
@@ -721,10 +824,11 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
@Override
public int getTransactionIsolation() throws SQLException {
- boolean transactionsEnabled = getQueryServices().getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED,
+ boolean transactionsEnabled = getQueryServices().getProps().getBoolean(
+ QueryServices.TRANSACTIONS_ENABLED,
QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED);
- return transactionsEnabled ?
- Connection.TRANSACTION_REPEATABLE_READ : Connection.TRANSACTION_READ_COMMITTED;
+ return transactionsEnabled ? Connection.TRANSACTION_REPEATABLE_READ
+ : Connection.TRANSACTION_READ_COMMITTED;
}
@Override
@@ -744,7 +848,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
@Override
public boolean isReadOnly() throws SQLException {
- return readOnly;
+ return readOnly || (scn != null && !buildingIndex && !isRunningUpgrade);
}
@Override
@@ -764,58 +868,66 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
- public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
- int resultSetHoldability) throws SQLException {
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
throw new SQLFeatureNotSupportedException();
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
checkOpen();
- PhoenixPreparedStatement statement = new PhoenixPreparedStatement(this, sql);
+ PhoenixPreparedStatement statement = new PhoenixPreparedStatement(this,
+ sql);
statements.add(statement);
return statement;
}
@Override
- public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException {
checkOpen();
// Ignore autoGeneratedKeys, and just execute the statement.
return prepareStatement(sql);
}
@Override
- public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException {
checkOpen();
// Ignore columnIndexes, and just execute the statement.
return prepareStatement(sql);
}
@Override
- public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException {
checkOpen();
// Ignore columnNames, and just execute the statement.
return prepareStatement(sql);
}
@Override
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
- throws SQLException {
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException {
checkOpen();
- if (resultSetType != ResultSet.TYPE_FORWARD_ONLY || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
+ if (resultSetType != ResultSet.TYPE_FORWARD_ONLY
+ || resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) {
throw new SQLFeatureNotSupportedException();
}
return prepareStatement(sql);
}
@Override
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
- int resultSetHoldability) throws SQLException {
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
checkOpen();
if (resultSetHoldability != ResultSet.CLOSE_CURSORS_AT_COMMIT) {
throw new SQLFeatureNotSupportedException();
@@ -864,20 +976,22 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
throw new SQLFeatureNotSupportedException();
}
// TODO:
-// if (catalog == null) {
-// tenantId = null;
-// } else {
-// tenantId = PNameFactory.newName(catalog);
-// }
+ // if (catalog == null) {
+ // tenantId = null;
+ // } else {
+ // tenantId = PNameFactory.newName(catalog);
+ // }
}
@Override
- public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ public void setClientInfo(Properties properties)
+ throws SQLClientInfoException {
throw new UnsupportedOperationException();
}
@Override
- public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ public void setClientInfo(String name, String value)
+ throws SQLClientInfoException {
throw new UnsupportedOperationException();
}
@@ -889,7 +1003,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
checkOpen();
- this.readOnly=readOnly;
+ this.readOnly = readOnly;
}
@Override
@@ -905,13 +1019,16 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
@Override
public void setTransactionIsolation(int level) throws SQLException {
checkOpen();
- boolean transactionsEnabled = getQueryServices().getProps().getBoolean(QueryServices.TRANSACTIONS_ENABLED,
+ boolean transactionsEnabled = getQueryServices().getProps().getBoolean(
+ QueryServices.TRANSACTIONS_ENABLED,
QueryServicesOptions.DEFAULT_TRANSACTIONS_ENABLED);
if (level == Connection.TRANSACTION_SERIALIZABLE) {
throw new SQLFeatureNotSupportedException();
}
- if (!transactionsEnabled && level == Connection.TRANSACTION_REPEATABLE_READ) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_ISOLATION_LEVEL)
+ if (!transactionsEnabled
+ && level == Connection.TRANSACTION_REPEATABLE_READ) {
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.TX_MUST_BE_ENABLED_TO_SET_ISOLATION_LEVEL)
.build().buildException();
}
}
@@ -930,11 +1047,14 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
if (!iface.isInstance(this)) {
- throw new SQLExceptionInfo.Builder(SQLExceptionCode.CLASS_NOT_UNWRAPPABLE)
- .setMessage(this.getClass().getName() + " not unwrappable from " + iface.getName())
- .build().buildException();
+ throw new SQLExceptionInfo.Builder(
+ SQLExceptionCode.CLASS_NOT_UNWRAPPABLE)
+ .setMessage(
+ this.getClass().getName()
+ + " not unwrappable from "
+ + iface.getName()).build().buildException();
}
- return (T)this;
+ return (T) this;
}
@Override
@@ -958,7 +1078,8 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ public void setNetworkTimeout(Executor executor, int milliseconds)
+ throws SQLException {
checkOpen();
}
@@ -967,21 +1088,22 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
// TODO Auto-generated method stub
return 0;
}
-
+
@Override
public void addTable(PTable table, long resolvedTime) throws SQLException {
metaData.addTable(table, resolvedTime);
- //Cascade through to connectionQueryServices too
+ // Cascade through to connectionQueryServices too
getQueryServices().addTable(table, resolvedTime);
}
-
+
@Override
- public void updateResolvedTimestamp(PTable table, long resolvedTime) throws SQLException {
- metaData.updateResolvedTimestamp(table, resolvedTime);
- //Cascade through to connectionQueryServices too
+ public void updateResolvedTimestamp(PTable table, long resolvedTime)
+ throws SQLException {
+ metaData.updateResolvedTimestamp(table, resolvedTime);
+ // Cascade through to connectionQueryServices too
getQueryServices().updateResolvedTimestamp(table, resolvedTime);
}
-
+
@Override
public void addFunction(PFunction function) throws SQLException {
// TODO: since a connection is only used by one thread at a time,
@@ -989,7 +1111,7 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
if (scn == null || scn > function.getTimeStamp()) {
metaData.addFunction(function);
}
- //Cascade through to connectionQueryServices too
+ // Cascade through to connectionQueryServices too
getQueryServices().addFunction(function);
}
@@ -1001,46 +1123,57 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
@Override
- public void removeTable(PName tenantId, String tableName, String parentTableName, long tableTimeStamp) throws SQLException {
- metaData.removeTable(tenantId, tableName, parentTableName, tableTimeStamp);
- //Cascade through to connectionQueryServices too
- getQueryServices().removeTable(tenantId, tableName, parentTableName, tableTimeStamp);
+ public void removeTable(PName tenantId, String tableName,
+ String parentTableName, long tableTimeStamp) throws SQLException {
+ metaData.removeTable(tenantId, tableName, parentTableName,
+ tableTimeStamp);
+ // Cascade through to connectionQueryServices too
+ getQueryServices().removeTable(tenantId, tableName, parentTableName,
+ tableTimeStamp);
}
@Override
- public void removeFunction(PName tenantId, String functionName, long tableTimeStamp) throws SQLException {
+ public void removeFunction(PName tenantId, String functionName,
+ long tableTimeStamp) throws SQLException {
metaData.removeFunction(tenantId, functionName, tableTimeStamp);
- //Cascade through to connectionQueryServices too
- getQueryServices().removeFunction(tenantId, functionName, tableTimeStamp);
+ // Cascade through to connectionQueryServices too
+ getQueryServices().removeFunction(tenantId, functionName,
+ tableTimeStamp);
}
@Override
- public void removeColumn(PName tenantId, String tableName, List<PColumn> columnsToRemove, long tableTimeStamp,
+ public void removeColumn(PName tenantId, String tableName,
+ List<PColumn> columnsToRemove, long tableTimeStamp,
long tableSeqNum, long resolvedTime) throws SQLException {
- metaData.removeColumn(tenantId, tableName, columnsToRemove, tableTimeStamp, tableSeqNum, resolvedTime);
- //Cascade through to connectionQueryServices too
- getQueryServices().removeColumn(tenantId, tableName, columnsToRemove, tableTimeStamp, tableSeqNum, resolvedTime);
+ metaData.removeColumn(tenantId, tableName, columnsToRemove,
+ tableTimeStamp, tableSeqNum, resolvedTime);
+ // Cascade through to connectionQueryServices too
+ getQueryServices().removeColumn(tenantId, tableName, columnsToRemove,
+ tableTimeStamp, tableSeqNum, resolvedTime);
}
- protected boolean removeStatement(PhoenixStatement statement) throws SQLException {
+ protected boolean removeStatement(PhoenixStatement statement)
+ throws SQLException {
return statements.remove(statement);
- }
+ }
public KeyValueBuilder getKeyValueBuilder() {
return this.services.getKeyValueBuilder();
}
-
+
/**
- * Used to track executions of {@link Statement}s and {@link PreparedStatement}s that were created from this connection before
- * commit or rollback. 0-based. Used to associate partial save errors with SQL statements
- * invoked by users.
+ * Used to track executions of {@link Statement}s and
+ * {@link PreparedStatement}s that were created from this connection before
+ * commit or rollback. 0-based. Used to associate partial save errors with
+ * SQL statements invoked by users.
+ *
* @see CommitException
* @see #incrementStatementExecutionCounter()
*/
public int getStatementExecutionCounter() {
- return statementExecutionCounter;
- }
-
+ return statementExecutionCounter;
+ }
+
public void incrementStatementExecutionCounter() {
statementExecutionCounter++;
}
@@ -1052,19 +1185,21 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
public void setTraceScope(TraceScope traceScope) {
this.traceScope = traceScope;
}
-
+
public Map<String, Map<MetricType, Long>> getMutationMetrics() {
return mutationState.getMutationMetricQueue().aggregate();
}
-
+
public Map<String, Map<MetricType, Long>> getReadMetrics() {
- return mutationState.getReadMetricQueue() != null ? mutationState.getReadMetricQueue().aggregate() : Collections.<String, Map<MetricType, Long>>emptyMap();
+ return mutationState.getReadMetricQueue() != null ? mutationState
+ .getReadMetricQueue().aggregate() : Collections
+ .<String, Map<MetricType, Long>> emptyMap();
}
-
+
public boolean isRequestLevelMetricsEnabled() {
return isRequestLevelMetricsEnabled;
}
-
+
public void clearMetrics() {
mutationState.getMutationMetricQueue().clearMetrics();
if (mutationState.getReadMetricQueue() != null) {
@@ -1073,28 +1208,30 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
}
/**
- * Returns true if this connection is being used to upgrade the
- * data due to PHOENIX-2067 and false otherwise.
+ * Returns true if this connection is being used to upgrade the data due to
+ * PHOENIX-2067 and false otherwise.
+ *
* @return
*/
public boolean isDescVarLengthRowKeyUpgrade() {
return isDescVarLengthRowKeyUpgrade;
}
-
+
/**
* Added for tests only. Do not use this elsewhere.
*/
public ParallelIteratorFactory getIteratorFactory() {
return parallelIteratorFactory;
}
-
+
/**
* Added for testing purposes. Do not use this elsewhere.
*/
- public void setIteratorFactory(ParallelIteratorFactory parallelIteratorFactory) {
+ public void setIteratorFactory(
+ ParallelIteratorFactory parallelIteratorFactory) {
this.parallelIteratorFactory = parallelIteratorFactory;
}
-
+
public void addIteratorForLeaseRenewal(@Nonnull TableResultIterator itr) {
if (services.supportsFeature(Feature.RENEW_LEASE)) {
checkNotNull(itr);
@@ -1125,13 +1262,13 @@ public class PhoenixConnection implements Connection, MetaDataMutated, SQLClosea
getQueryServices().removeSchema(schema, schemaTimeStamp);
}
-
+
public boolean isRunningUpgrade() {
return isRunningUpgrade;
}
-
+
public void setRunningUpgrade(boolean isRunningUpgrade) {
this.isRunningUpgrade = isRunningUpgrade;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixInputFormat.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixInputFormat.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixInputFormat.java
index 25729d6..2871809 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixInputFormat.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/PhoenixInputFormat.java
@@ -30,7 +30,9 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HRegionLocation;
import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.client.*;
+import org.apache.hadoop.hbase.client.ConnectionFactory;
+import org.apache.hadoop.hbase.client.RegionLocator;
+import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.RegionSizeCalculator;
import org.apache.hadoop.io.NullWritable;
@@ -46,7 +48,6 @@ import org.apache.phoenix.iterate.MapReduceParallelScanGrouper;
import org.apache.phoenix.jdbc.PhoenixStatement;
import org.apache.phoenix.mapreduce.util.ConnectionUtil;
import org.apache.phoenix.mapreduce.util.PhoenixConfigurationUtil;
-import org.apache.phoenix.mapreduce.util.PhoenixMapReduceUtil;
import org.apache.phoenix.query.KeyRange;
import org.apache.phoenix.util.PhoenixRuntime;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportDirectMapper.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportDirectMapper.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportDirectMapper.java
index c1db27c..eb4bc0e 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportDirectMapper.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportDirectMapper.java
@@ -84,7 +84,7 @@ public class PhoenixIndexImportDirectMapper extends
String scn = configuration.get(PhoenixConfigurationUtil.CURRENT_SCN_VALUE);
String txScnValue = configuration.get(PhoenixConfigurationUtil.TX_SCN_VALUE);
if(txScnValue==null) {
- overrideProps.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, scn);
+ overrideProps.put(PhoenixRuntime.BUILD_INDEX_AT_ATTRIB, scn);
}
connection = ConnectionUtil.getOutputConnection(configuration, overrideProps);
connection.setAutoCommit(false);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
index 7551527..9e0d629 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexImportMapper.java
@@ -75,7 +75,7 @@ public class PhoenixIndexImportMapper extends Mapper<NullWritable, PhoenixIndexD
String scn = configuration.get(PhoenixConfigurationUtil.CURRENT_SCN_VALUE);
String txScnValue = configuration.get(PhoenixConfigurationUtil.TX_SCN_VALUE);
if(txScnValue==null) {
- overrideProps.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, scn);
+ overrideProps.put(PhoenixRuntime.BUILD_INDEX_AT_ATTRIB, scn);
}
connection = ConnectionUtil.getOutputConnection(configuration,overrideProps);
connection.setAutoCommit(false);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexPartialBuildMapper.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexPartialBuildMapper.java b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexPartialBuildMapper.java
index 0ead358..5b85da5 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexPartialBuildMapper.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/mapreduce/index/PhoenixIndexPartialBuildMapper.java
@@ -80,7 +80,7 @@ public class PhoenixIndexPartialBuildMapper extends TableMapper<ImmutableBytesWr
String scn = configuration.get(PhoenixConfigurationUtil.CURRENT_SCN_VALUE);
String txScnValue = configuration.get(PhoenixConfigurationUtil.TX_SCN_VALUE);
if(txScnValue==null && scn!=null) {
- overrideProps.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, scn);
+ overrideProps.put(PhoenixRuntime.BUILD_INDEX_AT_ATTRIB, scn);
}
connection = ConnectionUtil.getOutputConnection(configuration, overrideProps).unwrap(PhoenixConnection.class);
connection.setAutoCommit(false);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index 5ba134c..1a1e571 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -2412,6 +2412,7 @@ public class ConnectionQueryServicesImpl extends DelegateQueryServices implement
try (PhoenixConnection metaConnection = new PhoenixConnection(ConnectionQueryServicesImpl.this, globalUrl,
scnProps, newEmptyMetaData())) {
try {
+ metaConnection.setRunningUpgrade(true);
metaConnection.createStatement().executeUpdate(QueryConstants.CREATE_TABLE_METADATA);
} catch (NewerTableAlreadyExistsException ignore) {
// Ignore, as this will happen if the SYSTEM.CATALOG already exists at this fixed
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
index ec05b24..f15e0b1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
@@ -294,6 +294,7 @@ public class ConnectionlessQueryServicesImpl extends DelegateQueryServices imple
scnProps.remove(PhoenixRuntime.TENANT_ID_ATTRIB);
String globalUrl = JDBCUtil.removeProperty(url, PhoenixRuntime.TENANT_ID_ATTRIB);
metaConnection = new PhoenixConnection(this, globalUrl, scnProps, newEmptyMetaData());
+ metaConnection.setRunningUpgrade(true);
try {
metaConnection.createStatement().executeUpdate(QueryConstants.CREATE_TABLE_METADATA);
} catch (TableAlreadyExistsException ignore) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 557a149..ed1b3b2 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -105,7 +105,6 @@ import static org.apache.phoenix.schema.types.PDataType.FALSE_BYTES;
import static org.apache.phoenix.schema.types.PDataType.TRUE_BYTES;
import java.io.IOException;
-import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -1210,7 +1209,7 @@ public class MetaDataClient {
// If our connection is at a fixed point-in-time, we need to open a new
// connection so that our new index table is visible.
Properties props = new Properties(connection.getClientInfo());
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(connection.getSCN()+1));
+ props.setProperty(PhoenixRuntime.BUILD_INDEX_AT_ATTRIB, Long.toString(connection.getSCN()+1));
PhoenixConnection conn = new PhoenixConnection(connection, connection.getQueryServices(), props);
MetaDataClient newClientAtNextTimeStamp = new MetaDataClient(conn);
@@ -2894,13 +2893,9 @@ public class MetaDataClient {
}
private void deleteFromStatsTable(List<TableRef> tableRefs, long ts) throws SQLException {
- Properties props = new Properties(connection.getClientInfo());
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
- Connection conn = new PhoenixConnection(connection.getQueryServices(), connection, ts);
- conn.setAutoCommit(true);
- boolean success = false;
- SQLException sqlException = null;
- try {
+ boolean isAutoCommit = connection.getAutoCommit();
+ try {
+ connection.setAutoCommit(true);
StringBuilder buf = new StringBuilder("DELETE FROM SYSTEM.STATS WHERE PHYSICAL_NAME IN (");
for (TableRef ref : tableRefs) {
buf.append("'" + ref.getTable().getPhysicalName().getString() + "',");
@@ -2917,25 +2912,9 @@ public class MetaDataClient {
}
buf.setCharAt(buf.length() - 1, ')');
}
- conn.createStatement().execute(buf.toString());
- success = true;
- } catch (SQLException e) {
- sqlException = e;
+ connection.createStatement().execute(buf.toString());
} finally {
- try {
- conn.close();
- } catch (SQLException e) {
- if (sqlException == null) {
- // If we're not in the middle of throwing another exception
- // then throw the exception we got on close.
- if (success) {
- sqlException = e;
- }
- } else {
- sqlException.setNextException(e);
- }
- }
- if (sqlException != null) { throw sqlException; }
+ connection.setAutoCommit(isAutoCommit);
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/util/JDBCUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/JDBCUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/JDBCUtil.java
index 7715705..e4f490a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/JDBCUtil.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/JDBCUtil.java
@@ -133,8 +133,8 @@ public class JDBCUtil {
return (scnStr == null ? null : Long.parseLong(scnStr));
}
- public static Long getReplayAt(String url, Properties info) throws SQLException {
- String scnStr = findProperty(url, info, PhoenixRuntime.REPLAY_AT_ATTRIB);
+ public static Long getBuildIndexSCN(String url, Properties info) throws SQLException {
+ String scnStr = findProperty(url, info, PhoenixRuntime.BUILD_INDEX_AT_ATTRIB);
return (scnStr == null ? null : Long.parseLong(scnStr));
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
index 59b3bb2..16ef206 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/util/PhoenixRuntime.java
@@ -96,7 +96,6 @@ import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Maps.EntryTransformer;
/**
*
@@ -123,26 +122,18 @@ public class PhoenixRuntime {
/**
* Use this connection property to control HBase timestamps
- * by specifying your own long timestamp value at connection time. All
- * queries will use this as the upper bound of the time range for scans
- * and DDL, and DML will use this as t he timestamp for key values.
+ * by specifying your own long timestamp value at connection time.
+ * Specifying this property will force the connection to be read
+ * only - no DML or DDL will be allowed.
*/
public static final String CURRENT_SCN_ATTRIB = "CurrentSCN";
/**
- * Use this connection property to set the long time stamp value at
- * which to replay DML statements after a write failure. The time
- * stamp value must match the value returned by
- * {@link org.apache.phoenix.execute.CommitException#getServerTimestamp()}
- * when the exception occurred. Used in conjunction with the
- * {@link org.apache.phoenix.hbase.index.write.LeaveIndexActiveFailurePolicy}
- * index write failure policy to provide a means of the client replaying
- * updates to ensure that secondary indexes are correctly caught up
- * with any data updates when a write failure occurs. The updates
- * should be replayed in ascending time stamp order.
+ * Internal connection property to force an index to be built at a
+ * given time stamp.
*/
- public static final String REPLAY_AT_ATTRIB = "ReplayAt";
-
+ public static final String BUILD_INDEX_AT_ATTRIB = "BuildIndexAt";
+
/**
* Use this connection property to help with fairness of resource allocation
* for the client and server. The value of the attribute determines the
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
index 3f09a54..ca4be2f 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/compile/QueryCompilerTest.java
@@ -82,6 +82,7 @@ import org.apache.phoenix.schema.types.PDecimal;
import org.apache.phoenix.schema.types.PInteger;
import org.apache.phoenix.schema.types.PVarchar;
import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.EnvironmentEdgeManager;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.QueryUtil;
@@ -2257,18 +2258,20 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
}
@Test
- public void testQueryWithSCN() throws Exception {
+ public void testDMLOfNonIndexWithBuildIndexAt() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- props.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(1000));
- props.put(QueryServices.TRANSACTIONS_ENABLED, Boolean.TRUE.toString());
+ try (Connection conn = DriverManager.getConnection(getUrl(), props);) {
+ conn.createStatement().execute(
+ "CREATE TABLE t (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR)");
+ }
+ props.put(PhoenixRuntime.BUILD_INDEX_AT_ATTRIB, Long.toString(EnvironmentEdgeManager.currentTimeMillis()+1));
try (Connection conn = DriverManager.getConnection(getUrl(), props);) {
try {
- conn.createStatement().execute(
- "CREATE TABLE t (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR) TRANSACTIONAL=true");
+ conn.createStatement().execute("UPSERT INTO T (k,v1) SELECT k,v1 FROM T");
fail();
} catch (SQLException e) {
assertEquals("Unexpected Exception",
- SQLExceptionCode.CANNOT_START_TRANSACTION_WITH_SCN_SET
+ SQLExceptionCode.ONLY_INDEX_UPDATABLE_AT_SCN
.getErrorCode(), e.getErrorCode());
}
}
@@ -2778,21 +2781,6 @@ public class QueryCompilerTest extends BaseConnectionlessQueryTest {
}
@Test
- public void testSCNInOnDupKey() throws Exception {
- String url = getUrl() + ";" + PhoenixRuntime.CURRENT_SCN_ATTRIB + "=100";
- Connection conn = DriverManager.getConnection(url);
- conn.createStatement().execute("CREATE TABLE t1 (k1 integer not null, k2 integer not null, v bigint, constraint pk primary key (k1,k2))");
- try {
- conn.createStatement().execute("UPSERT INTO t1 VALUES(0,0) ON DUPLICATE KEY UPDATE v = v + 1");
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_SET_SCN_IN_ON_DUP_KEY.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
public void testOrderPreservingGroupBy() throws Exception {
try (Connection conn= DriverManager.getConnection(getUrl())) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
index 8b93b5c..1fe21d2 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/util/TestUtil.java
@@ -642,13 +642,7 @@ public class TestUtil {
conn.createStatement().execute(query);
}
- public static void analyzeTable(String url, long ts, String tableName) throws IOException, SQLException {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts));
- analyzeTable(url, props, tableName);
- }
-
- public static void analyzeTable(String url, Properties props, String tableName) throws IOException, SQLException {
+ public static void analyzeTable(String url, Properties props, String tableName) throws IOException, SQLException {
Connection conn = DriverManager.getConnection(url, props);
analyzeTable(conn, tableName);
conn.close();
[21/25] phoenix git commit: PHOENIX-4248 Breakup IndexExpressionIT
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
PHOENIX-4248 Breakup IndexExpressionIT into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/3d9adc6f
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/3d9adc6f
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/3d9adc6f
Branch: refs/heads/master
Commit: 3d9adc6f3f298ab5077b8fddf9d17aa4e4a11e56
Parents: 834133a
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 17:02:06 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 18:23:40 2017 -0700
----------------------------------------------------------------------
.../phoenix/end2end/index/BaseIndexIT.java | 1194 ++++++++++++++++++
.../index/GlobalImmutableNonTxIndexIT.java | 2 +-
.../end2end/index/GlobalImmutableTxIndexIT.java | 2 +-
.../index/GlobalMutableNonTxIndexIT.java | 2 +-
.../end2end/index/GlobalMutableTxIndexIT.java | 2 +-
.../end2end/index/IndexExpressionIT.java | 15 -
.../apache/phoenix/end2end/index/IndexIT.java | 1194 ------------------
.../end2end/index/IndexMaintenanceIT.java | 457 +++++++
.../phoenix/end2end/index/IndexMetadataIT.java | 67 +
.../phoenix/end2end/index/IndexUsageIT.java | 775 ++++++++++++
.../index/IndexWithTableSchemaChangeIT.java | 375 ++++++
.../index/LocalImmutableNonTxIndexIT.java | 2 +-
.../end2end/index/LocalImmutableTxIndexIT.java | 2 +-
.../end2end/index/LocalMutableNonTxIndexIT.java | 2 +-
.../end2end/index/LocalMutableTxIndexIT.java | 2 +-
15 files changed, 2876 insertions(+), 1217 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java
new file mode 100644
index 0000000..049416c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/BaseIndexIT.java
@@ -0,0 +1,1194 @@
+/*
+ * 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.end2end.index;
+
+import static org.apache.phoenix.query.QueryConstants.MILLIS_IN_DAY;
+import static org.apache.phoenix.util.TestUtil.ROW5;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import java.util.Random;
+
+import org.apache.hadoop.hbase.Cell;
+import org.apache.hadoop.hbase.CellScanner;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTableInterface;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory;
+import org.apache.phoenix.compile.ColumnResolver;
+import org.apache.phoenix.compile.FromCompiler;
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
+import org.apache.phoenix.jdbc.PhoenixResultSet;
+import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.parse.NamedTableNode;
+import org.apache.phoenix.parse.TableName;
+import org.apache.phoenix.query.BaseTest;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableImpl;
+import org.apache.phoenix.schema.PTableKey;
+import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.EnvironmentEdgeManager;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.apache.phoenix.util.TransactionUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class BaseIndexIT extends ParallelStatsDisabledIT {
+ private static final Random RAND = new Random();
+
+ private final boolean localIndex;
+ private final boolean transactional;
+ private final boolean mutable;
+ private final String tableDDLOptions;
+
+ protected BaseIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ this.localIndex = localIndex;
+ this.transactional = transactional;
+ this.mutable = mutable;
+ StringBuilder optionBuilder = new StringBuilder();
+ if (!columnEncoded) {
+ if (optionBuilder.length()!=0)
+ optionBuilder.append(",");
+ optionBuilder.append("COLUMN_ENCODED_BYTES=0");
+ }
+ if (!mutable) {
+ if (optionBuilder.length()!=0)
+ optionBuilder.append(",");
+ optionBuilder.append("IMMUTABLE_ROWS=true");
+ if (!columnEncoded) {
+ optionBuilder.append(",IMMUTABLE_STORAGE_SCHEME="+PTableImpl.ImmutableStorageScheme.ONE_CELL_PER_COLUMN);
+ }
+ }
+ if (transactional) {
+ if (optionBuilder.length()!=0)
+ optionBuilder.append(",");
+ optionBuilder.append(" TRANSACTIONAL=true ");
+ }
+ this.tableDDLOptions = optionBuilder.toString();
+ }
+
+ @Test
+ public void testIndexWithNullableFixedWithCols() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
+ + " (char_col1 ASC, int_col1 ASC)"
+ + " INCLUDE (long_col1, long_col2)";
+ stmt.execute(ddl);
+
+ String query = "SELECT d.char_col1, int_col1 from " + fullTableName + " as d";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex) {
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + tableName + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + indexName + "\n"
+ + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("chara", rs.getString(1));
+ assertEquals("chara", rs.getString("char_col1"));
+ assertEquals(2, rs.getInt(2));
+ assertTrue(rs.next());
+ assertEquals("chara", rs.getString(1));
+ assertEquals(3, rs.getInt(2));
+ assertTrue(rs.next());
+ assertEquals("chara", rs.getString(1));
+ assertEquals(4, rs.getInt(2));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
+
+ query = "SELECT char_col1, int_col1 from " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+
+ query = "SELECT char_col1, int_col1 from "+indexName;
+ try{
+ rs = conn.createStatement().executeQuery(query);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.TABLE_UNDEFINED.getErrorCode(), e.getErrorCode());
+ }
+ }
+ }
+
+ @Test
+ public void testDeleteFromAllPKColumnIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
+ + " (long_pk, varchar_pk)"
+ + " INCLUDE (long_col1, long_col2)";
+ stmt.execute(ddl);
+
+ ResultSet rs;
+
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
+ assertTrue(rs.next());
+ assertEquals(3,rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexName);
+ assertTrue(rs.next());
+ assertEquals(3,rs.getInt(1));
+
+ String dml = "DELETE from " + fullTableName + " WHERE long_col2 = 4";
+ assertEquals(1,conn.createStatement().executeUpdate(dml));
+ conn.commit();
+
+ String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertFalse(rs.next());
+
+ query = "SELECT long_pk FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
+ }
+ }
+
+ @Test
+ public void testCreateIndexAfterUpsertStarted() throws Exception {
+ testCreateIndexAfterUpsertStarted(false,
+ SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()),
+ SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()));
+ }
+
+ @Test
+ public void testCreateIndexAfterUpsertStartedTxnl() throws Exception {
+ if (transactional) {
+ testCreateIndexAfterUpsertStarted(true,
+ SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()),
+ SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()));
+ }
+ }
+
+ private void testCreateIndexAfterUpsertStarted(boolean readOwnWrites, String fullTableName, String fullIndexName) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn1 = DriverManager.getConnection(getUrl(), props)) {
+ conn1.setAutoCommit(true);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt1 = conn1.createStatement();
+ stmt1.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+
+ ResultSet rs;
+
+ rs = conn1.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
+ assertTrue(rs.next());
+ assertEquals(3,rs.getInt(1));
+
+ try (Connection conn2 = DriverManager.getConnection(getUrl(), props)) {
+
+ String upsert = "UPSERT INTO " + fullTableName
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement pstmt2 = conn2.prepareStatement(upsert);
+ pstmt2.setString(1, "varchar4");
+ pstmt2.setString(2, "char4");
+ pstmt2.setInt(3, 4);
+ pstmt2.setLong(4, 4L);
+ pstmt2.setBigDecimal(5, new BigDecimal(4.0));
+ Date date = DateUtil.parseDate("2015-01-01 00:00:00");
+ pstmt2.setDate(6, date);
+ pstmt2.setString(7, "varchar_a");
+ pstmt2.setString(8, "chara");
+ pstmt2.setInt(9, 2);
+ pstmt2.setLong(10, 2L);
+ pstmt2.setBigDecimal(11, new BigDecimal(2.0));
+ pstmt2.setDate(12, date);
+ pstmt2.setString(13, "varchar_b");
+ pstmt2.setString(14, "charb");
+ pstmt2.setInt(15, 3);
+ pstmt2.setLong(16, 3L);
+ pstmt2.setBigDecimal(17, new BigDecimal(3.0));
+ pstmt2.setDate(18, date);
+ pstmt2.executeUpdate();
+
+ if (readOwnWrites) {
+ String query = "SELECT long_pk FROM " + fullTableName + " WHERE long_pk=4";
+ rs = conn2.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertFalse(rs.next());
+ }
+
+ String indexName = SchemaUtil.getTableNameFromFullName(fullIndexName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
+ + " (long_pk, varchar_pk)"
+ + " INCLUDE (long_col1, long_col2)";
+ stmt1.execute(ddl);
+
+ /*
+ * Commit upsert after index created through different connection.
+ * This forces conn2 (which doesn't know about the index yet) to update the metadata
+ * at commit time, recognize the new index, and generate the correct metadata (or index
+ * rows for immutable indexes).
+ *
+ * For transactional data, this is problematic because the index
+ * gets a timestamp *after* the commit timestamp of conn2 and thus won't be seen during
+ * the commit. Also, when the index is being built, the data hasn't yet been committed
+ * and thus won't be part of the initial index build (fixed by PHOENIX-2446).
+ */
+ conn2.commit();
+
+ stmt1 = conn1.createStatement();
+ rs = stmt1.executeQuery("SELECT COUNT(*) FROM " + fullTableName);
+ assertTrue(rs.next());
+ assertEquals(4,rs.getInt(1));
+ assertEquals(fullIndexName, stmt1.unwrap(PhoenixStatement.class).getQueryPlan().getTableRef().getTable().getName().getString());
+
+ String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
+ rs = conn1.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(2L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(4L, rs.getLong(1));
+ assertFalse(rs.next());
+ }
+ }
+ }
+
+ @Test
+ public void testDeleteFromNonPKColumnIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
+ + " (long_col1, long_col2)"
+ + " INCLUDE (decimal_col1, decimal_col2)";
+ stmt.execute(ddl);
+ }
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ ResultSet rs;
+
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
+ assertTrue(rs.next());
+ assertEquals(3,rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexName);
+ assertTrue(rs.next());
+ assertEquals(3,rs.getInt(1));
+
+ String dml = "DELETE from " + fullTableName + " WHERE long_col2 = 4";
+ assertEquals(1,conn.createStatement().executeUpdate(dml));
+ conn.commit();
+
+ // query the data table
+ String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertFalse(rs.next());
+
+ // query the index table
+ query = "SELECT long_pk FROM " + fullTableName + " ORDER BY long_col1";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertTrue(rs.next());
+ assertEquals(3L, rs.getLong(1));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
+ }
+ }
+
+ @Test
+ public void testGroupByCount() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col2)";
+ stmt.execute(ddl);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT int_col2, COUNT(*) FROM " + fullTableName + " GROUP BY int_col2");
+ assertTrue(rs.next());
+ assertEquals(1,rs.getInt(2));
+ }
+ }
+
+ @Test
+ public void testSelectDistinctOnTableWithSecondaryImmutableIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col2)";
+ conn.createStatement().execute(ddl);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT distinct int_col2 FROM " + fullTableName + " where int_col2 > 0");
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(4, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(5, rs.getInt(1));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testInClauseWithIndexOnColumnOfUsignedIntType() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col1)";
+ stmt.execute(ddl);
+ ResultSet rs = conn.createStatement().executeQuery("SELECT int_col1 FROM " + fullTableName + " where int_col1 IN (1, 2, 3, 4)");
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(4, rs.getInt(1));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void createIndexOnTableWithSpecifiedDefaultCF() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ String ddl ="CREATE TABLE " + fullTableName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) DEFAULT_COLUMN_FAMILY='A'" + (!tableDDLOptions.isEmpty() ? "," + tableDDLOptions : "");
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+
+ query = "SELECT * FROM " + tableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ String options = localIndex ? "SALT_BUCKETS=10, MULTI_TENANT=true, IMMUTABLE_ROWS=true, DISABLE_WAL=true" : "";
+ conn.createStatement().execute(
+ "CREATE INDEX " + indexName + " ON " + fullTableName + " (v1) INCLUDE (v2) " + options);
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ //check options set correctly on index
+ TableName indexTableName = TableName.create(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ NamedTableNode indexNode = NamedTableNode.create(null, indexTableName, null);
+ ColumnResolver resolver = FromCompiler.getResolver(indexNode, conn.unwrap(PhoenixConnection.class));
+ PTable indexTable = resolver.getTables().get(0).getTable();
+ // Can't set IMMUTABLE_ROWS, MULTI_TENANT or DEFAULT_COLUMN_FAMILY_NAME on an index
+ assertNull(indexTable.getDefaultFamilyName());
+ assertFalse(indexTable.isMultiTenant());
+ assertEquals(mutable, !indexTable.isImmutableRows()); // Should match table
+ if(localIndex) {
+ assertEquals(10, indexTable.getBucketNum().intValue());
+ assertTrue(indexTable.isWALDisabled());
+ }
+ }
+ }
+
+ @Test
+ public void testIndexWithNullableDateCol() throws Exception {
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ Date date = new Date(System.currentTimeMillis());
+
+ TestUtil.createMultiCFTestTable(conn, fullTableName, tableDDLOptions);
+ populateMultiCFTestTable(fullTableName, date);
+ String ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (date_col)";
+ conn.createStatement().execute(ddl);
+
+ String query = "SELECT int_pk from " + fullTableName ;
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if (localIndex) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName +" [1]\n"
+ + " SERVER FILTER BY FIRST KEY ONLY\n"
+ + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
+ + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+
+ query = "SELECT date_col from " + fullTableName + " order by date_col" ;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if (localIndex) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1]\n"
+ + " SERVER FILTER BY FIRST KEY ONLY\n"
+ + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
+ + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(date, rs.getDate(1));
+ assertTrue(rs.next());
+ assertEquals(new Date(date.getTime() + MILLIS_IN_DAY), rs.getDate(1));
+ assertTrue(rs.next());
+ assertEquals(new Date(date.getTime() + 2 * MILLIS_IN_DAY), rs.getDate(1));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testSelectAllAndAliasWithIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ String ddl = "CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) " + tableDDLOptions;
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (v2 DESC) INCLUDE (v1)";
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
+ stmt.setString(1,"a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ stmt.setString(1,"b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertEquals("y",rs.getString(2));
+ assertEquals("2",rs.getString(3));
+ assertEquals("b",rs.getString("k"));
+ assertEquals("y",rs.getString("v1"));
+ assertEquals("2",rs.getString("v2"));
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("1",rs.getString(3));
+ assertEquals("a",rs.getString("k"));
+ assertEquals("x",rs.getString("v1"));
+ assertEquals("1",rs.getString("v2"));
+ assertFalse(rs.next());
+
+ query = "SELECT v1 as foo FROM " + fullTableName + " WHERE v2 = '1' ORDER BY foo";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +fullTableName + " [1,~'1']\n" +
+ " SERVER SORTED BY [\"V1\"]\n" +
+ "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +fullIndexName + " [~'1']\n" +
+ " SERVER SORTED BY [\"V1\"]\n" +
+ "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("x",rs.getString("foo"));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testSelectCF() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ String ddl = "CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, a.v1 VARCHAR, a.v2 VARCHAR, b.v1 VARCHAR) " + tableDDLOptions;
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (v2 DESC) INCLUDE (a.v1)";
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?,?)");
+ stmt.setString(1,"a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.setString(4, "A");
+ stmt.execute();
+ stmt.setString(1,"b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.setString(4, "B");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullTableName, QueryUtil.getExplainPlan(rs));
+
+ query = "SELECT a.* FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
+ }
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("2",rs.getString(2));
+ assertEquals("y",rs.getString("v1"));
+ assertEquals("2",rs.getString("v2"));
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("1",rs.getString(2));
+ assertEquals("x",rs.getString("v1"));
+ assertEquals("1",rs.getString("v2"));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testUpsertAfterIndexDrop() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + fullTableName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)" + tableDDLOptions);
+ query = "SELECT * FROM " + fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + " (v1, v2)");
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ PreparedStatement stmt =
+ conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ // make sure the index is working as expected
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x", rs.getString(1));
+ assertEquals("1", rs.getString(2));
+ assertEquals("a", rs.getString(3));
+ assertFalse(rs.next());
+
+ String ddl = "DROP INDEX " + indexName + " ON " + fullTableName;
+ conn.createStatement().execute(ddl);
+
+ stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + "(k, v1) VALUES(?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "y");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + fullTableName;
+
+ // check that the data table matches as expected
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("y", rs.getString(2));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testMultipleUpdatesAcrossRegions() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+
+ String testTable = fullTableName+"_MULTIPLE_UPDATES";
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + testTable
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) "
+ + (!tableDDLOptions.isEmpty() ? tableDDLOptions : "") + " SPLIT ON ('b')");
+ query = "SELECT * FROM " + testTable;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + testTable + " (v1, v2)");
+ query = "SELECT * FROM " + fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ PreparedStatement stmt =
+ conn.prepareStatement("UPSERT INTO " + testTable + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ stmt.setString(1, "b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.execute();
+ stmt.setString(1, "c");
+ stmt.setString(2, "z");
+ stmt.setString(3, "3");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT /*+ NO_INDEX */ * FROM " + testTable;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("x", rs.getString(2));
+ assertEquals("1", rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("b", rs.getString(1));
+ assertEquals("y", rs.getString(2));
+ assertEquals("2", rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("c", rs.getString(1));
+ assertEquals("z", rs.getString(2));
+ assertEquals("3", rs.getString(3));
+ assertFalse(rs.next());
+
+ // make sure the index is working as expected
+ query = "SELECT * FROM " + testTable;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if (localIndex) {
+ assertEquals("CLIENT PARALLEL 2-WAY RANGE SCAN OVER " + testTable+" [1]\n"
+ + " SERVER FILTER BY FIRST KEY ONLY\n"
+ + "CLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
+ + " SERVER FILTER BY FIRST KEY ONLY",
+ QueryUtil.getExplainPlan(rs));
+ }
+
+ // check that the data table matches as expected
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("x", rs.getString(2));
+ assertEquals("1", rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("b", rs.getString(1));
+ assertEquals("y", rs.getString(2));
+ assertEquals("2", rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("c", rs.getString(1));
+ assertEquals("z", rs.getString(2));
+ assertEquals("3", rs.getString(3));
+ assertFalse(rs.next());
+ }
+ }
+
+ @Test
+ public void testIndexWithCaseSensitiveCols() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ conn.createStatement().execute("CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, \"V1\" VARCHAR, \"v2\" VARCHAR)"+tableDDLOptions);
+ query = "SELECT * FROM "+fullTableName;
+ rs = conn.createStatement().executeQuery(query);
+ long ts = conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null,fullTableName)).getTimeStamp();
+ assertFalse(rs.next());
+ conn.createStatement().execute(
+ "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + "(\"v2\") INCLUDE (\"V1\")");
+ query = "SELECT * FROM "+fullIndexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
+ stmt.setString(1,"a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ stmt.setString(1,"b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + fullTableName + " WHERE \"v2\" = '1'";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1,'1']\n"
+ + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullIndexName + " ['1']", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("1",rs.getString(3));
+ assertEquals("a",rs.getString("k"));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("1",rs.getString("v2"));
+ assertFalse(rs.next());
+
+ query = "SELECT \"V1\", \"V1\" as foo1, \"v2\" as foo, \"v2\" as \"Foo1\", \"v2\" FROM " + fullTableName + " ORDER BY foo";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1]\nCLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER "+fullIndexName, QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("x",rs.getString(2));
+ assertEquals("x",rs.getString("foo1"));
+ assertEquals("1",rs.getString(3));
+ assertEquals("1",rs.getString("Foo"));
+ assertEquals("1",rs.getString(4));
+ assertEquals("1",rs.getString("Foo1"));
+ assertEquals("1",rs.getString(5));
+ assertEquals("1",rs.getString("v2"));
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("y",rs.getString("V1"));
+ assertEquals("y",rs.getString(2));
+ assertEquals("y",rs.getString("foo1"));
+ assertEquals("2",rs.getString(3));
+ assertEquals("2",rs.getString("Foo"));
+ assertEquals("2",rs.getString(4));
+ assertEquals("2",rs.getString("Foo1"));
+ assertEquals("2",rs.getString(5));
+ assertEquals("2",rs.getString("v2"));
+ assertFalse(rs.next());
+
+ assertNoIndexDeletes(conn, ts, fullIndexName);
+ }
+ }
+
+ private void assertNoIndexDeletes(Connection conn, long minTimestamp, String fullIndexName) throws IOException, SQLException {
+ if (!this.mutable) {
+ PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
+ PTable index = pconn.getTable(new PTableKey(null, fullIndexName));
+ byte[] physicalIndexTable = index.getPhysicalName().getBytes();
+ try (HTableInterface hIndex = pconn.getQueryServices().getTable(physicalIndexTable)) {
+ Scan scan = new Scan();
+ scan.setRaw(true);
+ if (this.transactional) {
+ minTimestamp = TransactionUtil.convertToNanoseconds(minTimestamp);
+ }
+ scan.setTimeRange(minTimestamp, HConstants.LATEST_TIMESTAMP);
+ ResultScanner scanner = hIndex.getScanner(scan);
+ Result result;
+ while ((result = scanner.next()) != null) {
+ CellScanner cellScanner = result.cellScanner();
+ while (cellScanner.advance()) {
+ Cell current = cellScanner.current();
+ assertEquals (KeyValue.Type.Put.getCode(), current.getTypeByte());
+ }
+ }
+ };
+ }
+ }
+
+ @Test
+ public void testInFilterOnIndexedTable() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ String ddl = "CREATE TABLE " + fullTableName +" (PK1 CHAR(2) NOT NULL PRIMARY KEY, CF1.COL1 BIGINT) " + tableDDLOptions;
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + "(COL1)";
+ conn.createStatement().execute(ddl);
+
+ query = "SELECT COUNT(COL1) FROM " + fullTableName +" WHERE COL1 IN (1,25,50,75,100)";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ }
+ }
+
+ @Test
+ public void testIndexWithDecimalCol() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ String query;
+ ResultSet rs;
+ Date date = new Date(System.currentTimeMillis());
+
+ TestUtil.createMultiCFTestTable(conn, fullTableName, tableDDLOptions);
+ populateMultiCFTestTable(fullTableName, date);
+ String ddl = null;
+ ddl = "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + " (decimal_pk) INCLUDE (decimal_col1, decimal_col2)";
+ conn.createStatement().execute(ddl);
+
+ query = "SELECT decimal_pk, decimal_col1, decimal_col2 from " + fullTableName ;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(new BigDecimal("1.1"), rs.getBigDecimal(1));
+ assertEquals(new BigDecimal("2.1"), rs.getBigDecimal(2));
+ assertEquals(new BigDecimal("3.1"), rs.getBigDecimal(3));
+ assertTrue(rs.next());
+ assertEquals(new BigDecimal("2.2"), rs.getBigDecimal(1));
+ assertEquals(new BigDecimal("3.2"), rs.getBigDecimal(2));
+ assertEquals(new BigDecimal("4.2"), rs.getBigDecimal(3));
+ assertTrue(rs.next());
+ assertEquals(new BigDecimal("3.3"), rs.getBigDecimal(1));
+ assertEquals(new BigDecimal("4.3"), rs.getBigDecimal(2));
+ assertEquals(new BigDecimal("5.3"), rs.getBigDecimal(3));
+ assertFalse(rs.next());
+ }
+ }
+
+ /**
+ * Ensure that HTD contains table priorities correctly.
+ */
+ @Test
+ public void testTableDescriptorPriority() throws SQLException, IOException {
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ // Check system tables priorities.
+ try (HBaseAdmin admin = driver.getConnectionQueryServices(null, null).getAdmin();
+ Connection c = DriverManager.getConnection(getUrl())) {
+ ResultSet rs = c.getMetaData().getTables("",
+ "\""+ PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA + "\"",
+ null,
+ new String[] {PTableType.SYSTEM.toString()});
+ ReadOnlyProps p = c.unwrap(PhoenixConnection.class).getQueryServices().getProps();
+ while (rs.next()) {
+ String schemaName = rs.getString(PhoenixDatabaseMetaData.TABLE_SCHEM);
+ String tName = rs.getString(PhoenixDatabaseMetaData.TABLE_NAME);
+ org.apache.hadoop.hbase.TableName hbaseTableName = SchemaUtil.getPhysicalTableName(SchemaUtil.getTableName(schemaName, tName), p);
+ HTableDescriptor htd = admin.getTableDescriptor(hbaseTableName);
+ String val = htd.getValue("PRIORITY");
+ assertNotNull("PRIORITY is not set for table:" + htd, val);
+ assertTrue(Integer.parseInt(val)
+ >= PhoenixRpcSchedulerFactory.getMetadataPriority(config));
+ }
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.setAutoCommit(false);
+ Statement stmt = conn.createStatement();
+ stmt.execute(ddl);
+ BaseTest.populateTestTable(fullTableName);
+ ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName
+ + " ON " + fullTableName + " (long_col1, long_col2)"
+ + " INCLUDE (decimal_col1, decimal_col2)";
+ stmt.execute(ddl);
+ }
+
+ HTableDescriptor dataTable = admin.getTableDescriptor(
+ org.apache.hadoop.hbase.TableName.valueOf(fullTableName));
+ String val = dataTable.getValue("PRIORITY");
+ assertTrue(val == null || Integer.parseInt(val) < HConstants.HIGH_QOS);
+
+ if (!localIndex && mutable) {
+ HTableDescriptor indexTable = admin.getTableDescriptor(
+ org.apache.hadoop.hbase.TableName.valueOf(indexName));
+ val = indexTable.getValue("PRIORITY");
+ assertNotNull("PRIORITY is not set for table:" + indexTable, val);
+ assertTrue(Integer.parseInt(val) >= PhoenixRpcSchedulerFactory.getIndexPriority(config));
+ }
+ }
+ }
+
+ @Test
+ public void testQueryBackToDataTableWithDescPKColumn() throws SQLException {
+ doTestQueryBackToDataTableWithDescPKColumn(true);
+ doTestQueryBackToDataTableWithDescPKColumn(false);
+ }
+
+ private void doTestQueryBackToDataTableWithDescPKColumn(boolean isSecondPKDesc) throws SQLException {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String tableName = "TBL_" + generateUniqueName();
+ String indexName = "IND_" + generateUniqueName();
+ String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
+ String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
+
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ // create data table and index table
+ conn.setAutoCommit(true);
+ Statement stmt = conn.createStatement();
+ String ddl = "CREATE TABLE " + fullTableName + "(p1 integer not null, p2 integer not null, " +
+ " a integer, b integer CONSTRAINT PK PRIMARY KEY ";
+ if (isSecondPKDesc) {
+ ddl += "(p1, p2 desc))";
+ } else {
+ ddl += "(p1 desc, p2))";
+ }
+ stmt.executeUpdate(ddl);
+ ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + fullIndexName + " on " + fullTableName + "(a)";
+ stmt.executeUpdate(ddl);
+
+ // upsert a single row
+ String upsert = "UPSERT INTO " + fullTableName + " VALUES(1,2,3,4)";
+ stmt.executeUpdate(upsert);
+
+ // try select with index
+ // a = 3, should hit index table, but we select column B, so it will query back to data table
+ String query = "SELECT /*+index(" + fullTableName + " " + fullIndexName + "*/ b from " + fullTableName +
+ " WHERE a = 3";
+ ResultSet rs = stmt.executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(4, rs.getInt(1));
+ assertFalse(rs.next());
+ rs.close();
+ stmt.close();
+ }
+ }
+
+ @Test
+ public void testReturnedTimestamp() throws Exception {
+ String tenantId = getOrganizationId();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ String indexName = generateUniqueName();
+ String tableName =
+ initATableValues(generateUniqueName(), tenantId, getDefaultSplits(tenantId),
+ new Date(System.currentTimeMillis()), null, getUrl(), tableDDLOptions);
+ String ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + indexName + " on " + tableName + "(A_STRING) INCLUDE (B_STRING)";
+ conn.createStatement().executeUpdate(ddl);
+ String query = "SELECT ENTITY_ID,A_STRING,B_STRING FROM " + tableName + " WHERE organization_id=? and entity_id=?";
+
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+
+ long currentTime = EnvironmentEdgeManager.currentTimeMillis();
+ String entityId = mutable ? ROW5 : Integer.toString(Math.abs(RAND.nextInt() % 1000000000));
+ PreparedStatement ddlStatement = conn.prepareStatement("UPSERT INTO " + tableName + "(ORGANIZATION_ID, ENTITY_ID,A_STRING) VALUES('" + tenantId + "',?,?)");
+ ddlStatement.setString(1, entityId);
+ ddlStatement.setString(2, Integer.toString(Math.abs(RAND.nextInt() % 1000000000)));
+ ddlStatement.executeUpdate();
+ conn.commit();
+
+ statement.setString(2, entityId);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertTrue(rs.unwrap(PhoenixResultSet.class).getCurrentRow().getValue(0).getTimestamp() >= currentTime);
+ assertEquals(rs.getString(1).trim(), entityId);
+ assertFalse(rs.next());
+
+ currentTime = EnvironmentEdgeManager.currentTimeMillis();
+ entityId = mutable ? ROW5 : Integer.toString(Math.abs(RAND.nextInt() % 1000000000));
+ ddlStatement = conn.prepareStatement("UPSERT INTO " + tableName + "(ORGANIZATION_ID, ENTITY_ID,B_STRING) VALUES('" + tenantId + "',?,?)");
+ ddlStatement.setString(1, entityId);
+ ddlStatement.setString(2, Integer.toString(Math.abs(RAND.nextInt() % 1000000000)));
+ ddlStatement.executeUpdate();
+ conn.commit();
+
+ statement.setString(2, entityId);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertTrue(rs.unwrap(PhoenixResultSet.class).getCurrentRow().getValue(0).getTimestamp() >= currentTime);
+ assertEquals(rs.getString(1).trim(), entityId);
+ assertFalse(rs.next());
+
+ } finally {
+ conn.close();
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
index 52b219d..70ad73d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class GlobalImmutableNonTxIndexIT extends IndexIT {
+public class GlobalImmutableNonTxIndexIT extends BaseIndexIT {
public GlobalImmutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
index 58eab8c..1ba498c 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class GlobalImmutableTxIndexIT extends IndexIT {
+public class GlobalImmutableTxIndexIT extends BaseIndexIT {
public GlobalImmutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
index 9fe1938..f37182d 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class GlobalMutableNonTxIndexIT extends IndexIT {
+public class GlobalMutableNonTxIndexIT extends BaseIndexIT {
public GlobalMutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
index 4536959..65ca2c5 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class GlobalMutableTxIndexIT extends IndexIT {
+public class GlobalMutableTxIndexIT extends BaseIndexIT {
public GlobalMutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
index 2395b02..2578fe4 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
@@ -199,8 +199,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
// the index table
verifyResult(rs, 3);
verifyResult(rs, 4);
-
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -279,7 +277,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertEquals("VARCHAR2_CHAR2 _A.VARCHAR2_B.CHAR2 ", rs.getString(1));
assertEquals(2, rs.getLong(2));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -362,7 +359,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -448,7 +444,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertEquals(2L, rs.getLong(3));
assertEquals("VARCHAR1", rs.getString(4));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -503,7 +498,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertTrue(rs.next());
assertEquals(1, rs.getInt(2));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -556,7 +550,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -606,7 +599,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertTrue(rs.next());
assertEquals(2, rs.getInt(1));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -660,7 +652,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -769,7 +760,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertEquals("y_2",rs.getString(5));
assertEquals("y_2",rs.getString("\"('cf1'.'V1' || '_' || 'CF2'.'v2')\""));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + dataTableName);
} finally {
conn.close();
}
@@ -824,7 +814,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
assertEquals(2, rs.getInt(1));
assertEquals(1, rs.getInt(2));
assertFalse(rs.next());
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullDataTableName);
} finally {
conn.close();
}
@@ -859,7 +848,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
Connection conn = DriverManager.getConnection(getUrl(), props);
String dataTableName = generateUniqueName();
- String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
String indexName = generateUniqueName();
try {
@@ -946,7 +934,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
ResultSet rs;
PreparedStatement stmt;
String dataTableName = generateUniqueName();
- String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
String indexName = generateUniqueName();
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
@@ -1058,7 +1045,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
PreparedStatement stmt;
String dataTableName = generateUniqueName();
- String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
String indexName = generateUniqueName();
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
@@ -1181,7 +1167,6 @@ public class IndexExpressionIT extends ParallelStatsDisabledIT {
private void helpTestUpdatableViewIndex(boolean local) throws Exception {
Connection conn = DriverManager.getConnection(getUrl());
String dataTableName = generateUniqueName();
- String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
String indexName1 = generateUniqueName();
String viewName = generateUniqueName();
String indexName2 = generateUniqueName();
[02/25] phoenix git commit: PHOENIX-4096 Disallow DML operations on
connections with CURRENT_SCN set
Posted by ja...@apache.org.
PHOENIX-4096 Disallow DML operations on connections with CURRENT_SCN set
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/06f58d56
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/06f58d56
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/06f58d56
Branch: refs/heads/master
Commit: 06f58d56c9e2b3badb5e3f6bd5092f03f58f00a8
Parents: 45079c4
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 11:24:22 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 17:51:53 2017 -0700
----------------------------------------------------------------------
.../phoenix/end2end/ExecuteStatementsIT.java | 4 +-
.../end2end/IndexToolForPartialBuildIT.java | 5 +-
.../phoenix/end2end/QueryExecWithoutSCNIT.java | 3 +-
.../org/apache/phoenix/end2end/QueryMoreIT.java | 2 +-
.../org/apache/phoenix/end2end/UpgradeIT.java | 23 +-
.../end2end/index/PartialIndexRebuilderIT.java | 3 +-
.../EndToEndCoveredColumnsIndexBuilderIT.java | 354 ------------
.../index/covered/FailWithoutRetriesIT.java | 140 -----
.../org/apache/phoenix/tx/TransactionIT.java | 23 +
.../phoenix/compile/CreateTableCompiler.java | 22 +-
.../apache/phoenix/compile/UpsertCompiler.java | 8 +-
.../coprocessor/MetaDataRegionObserver.java | 3 -
.../phoenix/exception/SQLExceptionCode.java | 3 +-
.../apache/phoenix/execute/MutationState.java | 8 -
.../org/apache/phoenix/hbase/index/Indexer.java | 11 +-
.../apache/phoenix/jdbc/PhoenixConnection.java | 567 ++++++++++++-------
.../phoenix/mapreduce/PhoenixInputFormat.java | 5 +-
.../index/PhoenixIndexImportDirectMapper.java | 2 +-
.../index/PhoenixIndexImportMapper.java | 2 +-
.../index/PhoenixIndexPartialBuildMapper.java | 2 +-
.../query/ConnectionQueryServicesImpl.java | 1 +
.../query/ConnectionlessQueryServicesImpl.java | 1 +
.../apache/phoenix/schema/MetaDataClient.java | 33 +-
.../java/org/apache/phoenix/util/JDBCUtil.java | 4 +-
.../org/apache/phoenix/util/PhoenixRuntime.java | 23 +-
.../phoenix/compile/QueryCompilerTest.java | 30 +-
.../java/org/apache/phoenix/util/TestUtil.java | 8 +-
27 files changed, 442 insertions(+), 848 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExecuteStatementsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExecuteStatementsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExecuteStatementsIT.java
index c8c0d37..9c11144 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExecuteStatementsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ExecuteStatementsIT.java
@@ -17,11 +17,9 @@
*/
package org.apache.phoenix.end2end;
-import static org.apache.phoenix.util.TestUtil.ATABLE_NAME;
import static org.apache.phoenix.util.TestUtil.A_VALUE;
import static org.apache.phoenix.util.TestUtil.BTABLE_NAME;
import static org.apache.phoenix.util.TestUtil.B_VALUE;
-import static org.apache.phoenix.util.TestUtil.PTSDB_NAME;
import static org.apache.phoenix.util.TestUtil.ROW6;
import static org.apache.phoenix.util.TestUtil.ROW7;
import static org.apache.phoenix.util.TestUtil.ROW8;
@@ -145,7 +143,7 @@ public class ExecuteStatementsIT extends ParallelStatsDisabledIT {
conn.commit();
String btableName = generateUniqueName();
- ensureTableCreated(getUrl(),btableName, BTABLE_NAME, nextTimestamp()-2);
+ ensureTableCreated(getUrl(),btableName, BTABLE_NAME);
statement = conn.prepareStatement(
"upsert into " + btableName + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, "abc");
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolForPartialBuildIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolForPartialBuildIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolForPartialBuildIT.java
index b71750a..19ffe1a 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolForPartialBuildIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/IndexToolForPartialBuildIT.java
@@ -162,7 +162,8 @@ public class IndexToolForPartialBuildIT extends BaseOwnClusterIT {
PTable pindexTable = PhoenixRuntime.getTable(conn, SchemaUtil.getTableName(schemaName, indxTable));
assertEquals(PIndexState.BUILDING, pindexTable.getIndexState());
assertEquals(rs.getLong(1), pindexTable.getTimeStamp());
- //assert disabled timestamp is set correctly when index mutations are processed on the server
+
+ //assert disabled timestamp
assertEquals(0, rs.getLong(2));
String selectSql = String.format("SELECT LPAD(UPPER(NAME),11,'x')||'_xyz',ID FROM %s", fullTableName);
@@ -216,8 +217,6 @@ public class IndexToolForPartialBuildIT extends BaseOwnClusterIT {
assertEquals("xxUNAME" + i*1000 + "_xyz", rs.getString(1));
}
assertFalse(rs.next());
-
- // conn.createStatement().execute(String.format("DROP INDEX %s ON %s", indxTable, fullTableName));
} finally {
conn.close();
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryExecWithoutSCNIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryExecWithoutSCNIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryExecWithoutSCNIT.java
index 51d08d8..a18caf8 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryExecWithoutSCNIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryExecWithoutSCNIT.java
@@ -35,9 +35,8 @@ import org.junit.Test;
public class QueryExecWithoutSCNIT extends ParallelStatsDisabledIT {
@Test
public void testScanNoSCN() throws Exception {
- long ts = System.currentTimeMillis();
String tenantId = getOrganizationId();
- String tableName = initATableValues(tenantId, getDefaultSplits(tenantId), null, ts, getUrl());
+ String tableName = initATableValues(tenantId, getDefaultSplits(tenantId), null, null, getUrl());
String query = "SELECT a_string, b_string FROM " + tableName + " WHERE organization_id=? and a_integer = 5";
Properties props = new Properties(); // Test with no CurrentSCN property set
Connection conn = DriverManager.getConnection(getUrl(), props);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryMoreIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryMoreIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryMoreIT.java
index 8397e4d..77cb19f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryMoreIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/QueryMoreIT.java
@@ -336,7 +336,7 @@ public class QueryMoreIT extends ParallelStatsDisabledIT {
@Test // see - https://issues.apache.org/jira/browse/PHOENIX-1696
public void testSelectColumnMoreThanOnce() throws Exception {
Date date = new Date(System.currentTimeMillis());
- initEntityHistoryTableValues("abcd", getDefaultSplits("abcd"), date, 100l);
+ initEntityHistoryTableValues("abcd", getDefaultSplits("abcd"), date, null);
String query = "SELECT NEW_VALUE, NEW_VALUE FROM " + TestUtil.ENTITY_HISTORY_TABLE_NAME + " LIMIT 1";
ResultSet rs = DriverManager.getConnection(getUrl()).createStatement().executeQuery(query);
assertTrue(rs.next());
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIT.java
index 8cba241..4cb4642 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UpgradeIT.java
@@ -20,7 +20,6 @@ package org.apache.phoenix.end2end;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.phoenix.query.ConnectionQueryServicesImpl.UPGRADE_MUTEX;
-import static org.apache.phoenix.query.ConnectionQueryServicesImpl.UPGRADE_MUTEX_LOCKED;
import static org.apache.phoenix.query.ConnectionQueryServicesImpl.UPGRADE_MUTEX_UNLOCKED;
import static org.apache.phoenix.query.QueryConstants.BASE_TABLE_BASE_COLUMN_COUNT;
import static org.apache.phoenix.query.QueryConstants.DIVERGED_VIEW_BASE_COLUMN_COUNT;
@@ -64,10 +63,16 @@ import org.apache.phoenix.query.ConnectionQueryServicesImpl;
import org.apache.phoenix.query.DelegateConnectionQueryServices;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.schema.*;
+import org.apache.phoenix.schema.PMetaData;
+import org.apache.phoenix.schema.PName;
+import org.apache.phoenix.schema.PNameFactory;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.PhoenixRuntime;
+import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.TestUtil;
import org.apache.phoenix.util.UpgradeUtil;
import org.junit.Before;
import org.junit.Test;
@@ -490,7 +495,7 @@ public class UpgradeIT extends ParallelStatsDisabledIT {
}
// run upgrade
- UpgradeUtil.upgradeTo4_5_0(conn.unwrap(PhoenixConnection.class));
+ upgradeTo4_5_0(conn);
// Verify base column counts for tenant specific views
for (int i = 0; i < 2 ; i++) {
@@ -508,6 +513,12 @@ public class UpgradeIT extends ParallelStatsDisabledIT {
}
+
+ private static void upgradeTo4_5_0(Connection conn) throws SQLException {
+ PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
+ pconn.setRunningUpgrade(true);
+ UpgradeUtil.upgradeTo4_5_0(pconn);
+ }
private enum ColumnDiff {
MORE, EQUAL, LESS
@@ -570,7 +581,7 @@ public class UpgradeIT extends ParallelStatsDisabledIT {
checkBaseColumnCount(null, baseTableSchema, baseTableName, 0);
// run upgrade
- UpgradeUtil.upgradeTo4_5_0(conn.unwrap(PhoenixConnection.class));
+ upgradeTo4_5_0(conn);
checkBaseColumnCount(tenantId, viewSchema, viewName, expectedBaseColumnCount);
checkBaseColumnCount(null, baseTableSchema, baseTableName, BASE_TABLE_BASE_COLUMN_COUNT);
@@ -639,8 +650,8 @@ public class UpgradeIT extends ParallelStatsDisabledIT {
return true;
}
};
- try (PhoenixConnection phxConn = new PhoenixConnection(servicesWithUpgrade,
- conn.unwrap(PhoenixConnection.class), HConstants.LATEST_TIMESTAMP)) {
+ try (PhoenixConnection phxConn = new PhoenixConnection(servicesWithUpgrade, getUrl(), PropertiesUtil.deepCopy(TestUtil.TEST_PROPERTIES),
+ conn.unwrap(PhoenixConnection.class).getMetaDataCache())) {
try {
phxConn.createStatement().execute(
"CREATE TABLE " + generateUniqueName()
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/PartialIndexRebuilderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/PartialIndexRebuilderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/PartialIndexRebuilderIT.java
index 8bf2bc8..d0a06b4 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/PartialIndexRebuilderIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/PartialIndexRebuilderIT.java
@@ -895,7 +895,8 @@ public class PartialIndexRebuilderIT extends BaseUniqueNamesOwnClusterIT {
assertEquals("0", rs.getString(1));
assertEquals(indexStateOnFailure == PIndexState.DISABLE ? fullTableName : fullIndexName, stmt.getQueryPlan().getContext().getCurrentTable().getTable().getName().getString());
TestUtil.removeCoprocessor(conn, fullIndexName, WriteFailingRegionObserver.class);
-
+
+ clock.time += 1000;
runIndexRebuilder();
assertEquals(indexStateOnFailure == PIndexState.DISABLE ? PIndexState.INACTIVE : PIndexState.ACTIVE, TestUtil.getIndexState(conn, fullIndexName));
clock.time += WAIT_AFTER_DISABLED;
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/EndToEndCoveredColumnsIndexBuilderIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/EndToEndCoveredColumnsIndexBuilderIT.java b/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/EndToEndCoveredColumnsIndexBuilderIT.java
deleted file mode 100644
index 5aa0161..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/EndToEndCoveredColumnsIndexBuilderIT.java
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * 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.hbase.index.covered;
-
-import static org.apache.phoenix.query.BaseTest.setUpConfigForMiniCluster;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.Coprocessor;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.regionserver.Region;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.coprocessor.BaseScannerRegionObserver.ReplayWrite;
-import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
-import org.apache.phoenix.hbase.index.IndexTestingUtils;
-import org.apache.phoenix.hbase.index.Indexer;
-import org.apache.phoenix.hbase.index.TableName;
-import org.apache.phoenix.hbase.index.covered.update.ColumnReference;
-import org.apache.phoenix.hbase.index.scanner.Scanner;
-import org.apache.phoenix.util.EnvironmentEdge;
-import org.apache.phoenix.util.EnvironmentEdgeManager;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-/**
- * End-to-End test of just the {@link NonTxIndexBuilder}, but with a simple
- * {@link IndexCodec} and BatchCache implementation.
- */
-@Category(NeedsOwnMiniClusterTest.class)
-public class EndToEndCoveredColumnsIndexBuilderIT {
-
- public class TestState {
-
- private HTable table;
- private long ts;
- private VerifyingIndexCodec codec;
-
- /**
- * @param primary
- * @param codec
- * @param ts
- */
- public TestState(HTable primary, VerifyingIndexCodec codec, long ts) {
- this.table = primary;
- this.ts = ts;
- this.codec = codec;
- }
-
- }
-
- private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
-
- private static final byte[] row = Bytes.toBytes("row");
- private static final byte[] family = Bytes.toBytes("FAM");
- private static final byte[] qual = Bytes.toBytes("qual");
- private static final HColumnDescriptor FAM1 = new HColumnDescriptor(family);
-
- @Rule
- public TableName TestTable = new TableName();
-
- private TestState state;
-
- @BeforeClass
- public static void setupCluster() throws Exception {
- Configuration conf = UTIL.getConfiguration();
- setUpConfigForMiniCluster(conf);
- IndexTestingUtils.setupConfig(conf);
- // disable version checking, so we can test against whatever version of HBase happens to be
- // installed (right now, its generally going to be SNAPSHOT versions).
- conf.setBoolean(Indexer.CHECK_VERSION_CONF_KEY, false);
- UTIL.startMiniCluster();
- }
-
- @Before
- public void setup() throws Exception {
- this.state = setupTest(TestTable.getTableNameString());
- }
-
- private interface TableStateVerifier {
-
- /**
- * Verify that the state of the table is correct. Should fail the unit test if it isn't as
- * expected.
- * @param state
- */
- public void verify(TableState state);
-
- }
-
- /**
- * {@link TableStateVerifier} that ensures the kvs returned from the table match the passed
- * {@link KeyValue}s when querying on the given columns.
- */
- private class ListMatchingVerifier implements TableStateVerifier {
-
- private List<Cell> expectedKvs;
- private ColumnReference[] columns;
- private String msg;
-
- public ListMatchingVerifier(String msg, List<Cell> kvs, ColumnReference... columns) {
- this.expectedKvs = kvs;
- this.columns = columns;
- this.msg = msg;
- }
-
- @Override
- public void verify(TableState state) {
- IndexMetaData indexMetaData = new IndexMetaData() {
-
- @Override
- public boolean isImmutableRows() {
- return false;
- }
-
- @Override
- public ReplayWrite getReplayWrite() {
- return null;
- }
-
- };
- try {
- Scanner kvs =
- ((LocalTableState) state).getIndexedColumnsTableState(Arrays.asList(columns), false, false, indexMetaData).getFirst();
-
- int count = 0;
- Cell kv;
- while ((kv = kvs.next()) != null) {
- Cell next = expectedKvs.get(count++);
- assertEquals(
- msg + ": Unexpected kv in table state!\nexpected v1: "
- + Bytes.toString(next.getValue()) + "\nactual v1:" + Bytes.toString(kv.getValue()),
- next, kv);
- }
-
- assertEquals(msg + ": Didn't find enough kvs in table state!", expectedKvs.size(), count);
- } catch (IOException e) {
- fail(msg + ": Got an exception while reading local table state! " + e.getMessage());
- }
- }
- }
-
- private class VerifyingIndexCodec extends CoveredIndexCodecForTesting {
-
- private Queue<TableStateVerifier> verifiers = new ArrayDeque<TableStateVerifier>();
-
- @Override
- public Iterable<IndexUpdate> getIndexDeletes(TableState state, IndexMetaData context) {
- verify(state);
- return super.getIndexDeletes(state, context);
- }
-
- @Override
- public Iterable<IndexUpdate> getIndexUpserts(TableState state, IndexMetaData context) {
- verify(state);
- return super.getIndexUpserts(state, context);
- }
-
- private void verify(TableState state) {
- TableStateVerifier verifier = verifiers.poll();
- if (verifier == null) return;
- verifier.verify(state);
- }
- }
-
- /**
- * Test that we see the expected values in a {@link TableState} when doing single puts against a
- * region.
- * @throws Exception on failure
- */
- @Test
- public void testExpectedResultsInTableStateForSinglePut() throws Exception {
- //just do a simple Put to start with
- long ts = state.ts;
- Put p = new Put(row, ts);
- p.add(family, qual, Bytes.toBytes("v1"));
-
- // get all the underlying kvs for the put
- final List<Cell> expectedKvs = new ArrayList<Cell>();
- final List<Cell> allKvs = new ArrayList<Cell>();
- allKvs.addAll(p.getFamilyMap().get(family));
-
- // setup the verifier for the data we expect to write
- // first call shouldn't have anything in the table
- final ColumnReference familyRef =
- new ColumnReference(EndToEndCoveredColumnsIndexBuilderIT.family, ColumnReference.ALL_QUALIFIERS);
-
- VerifyingIndexCodec codec = state.codec;
- codec.verifiers.add(new ListMatchingVerifier("cleanup state 1", expectedKvs, familyRef));
- codec.verifiers.add(new ListMatchingVerifier("put state 1", allKvs, familyRef));
-
- // do the actual put (no indexing will actually be done)
- HTable primary = state.table;
- primary.put(p);
- primary.flushCommits();
-
- // now we do another put to the same row. We should see just the old row state, followed by the
- // new + old
- p = new Put(row, ts + 1);
- p.add(family, qual, Bytes.toBytes("v2"));
- expectedKvs.addAll(allKvs);
- // add them first b/c the ts is newer
- allKvs.addAll(0, p.get(family, qual));
- codec.verifiers.add(new ListMatchingVerifier("cleanup state 2", expectedKvs, familyRef));
- codec.verifiers.add(new ListMatchingVerifier("put state 2", allKvs, familyRef));
-
- // do the actual put
- primary.put(p);
- primary.flushCommits();
-
- // cleanup after ourselves
- cleanup(state);
- }
-
- /**
- * Similar to {@link #testExpectedResultsInTableStateForSinglePut()}, but against batches of puts.
- * Previous implementations managed batches by playing current state against each element in the
- * batch, rather than combining all the per-row updates into a single mutation for the batch. This
- * test ensures that we see the correct expected state.
- * @throws Exception on failure
- */
- @Test
- public void testExpectedResultsInTableStateForBatchPuts() throws Exception {
- long ts = state.ts;
- // build up a list of puts to make, all on the same row
- Put p1 = new Put(row, ts);
- p1.add(family, qual, Bytes.toBytes("v1"));
- Put p2 = new Put(row, ts + 1);
- p2.add(family, qual, Bytes.toBytes("v2"));
-
- // setup all the verifiers we need. This is just the same as above, but will be called twice
- // since we need to iterate the batch.
-
- // get all the underlying kvs for the put
- final List<Cell> allKvs = new ArrayList<Cell>(2);
- allKvs.addAll(p2.getFamilyCellMap().get(family));
- allKvs.addAll(p1.getFamilyCellMap().get(family));
-
- // setup the verifier for the data we expect to write
- // both puts should be put into a single batch
- final ColumnReference familyRef =
- new ColumnReference(EndToEndCoveredColumnsIndexBuilderIT.family, ColumnReference.ALL_QUALIFIERS);
- VerifyingIndexCodec codec = state.codec;
- // no previous state in the table
- codec.verifiers.add(new ListMatchingVerifier("cleanup state 1", Collections
- .<Cell> emptyList(), familyRef));
- codec.verifiers.add(new ListMatchingVerifier("put state 1", p1.getFamilyCellMap().get(family),
- familyRef));
-
- codec.verifiers.add(new ListMatchingVerifier("cleanup state 2", p1.getFamilyCellMap().get(family),
- familyRef));
- // kvs from both puts should be in the table now
- codec.verifiers.add(new ListMatchingVerifier("put state 2", allKvs, familyRef));
-
- // do the actual put (no indexing will actually be done)
- HTable primary = state.table;
- primary.setAutoFlush(false);
- primary.put(Arrays.asList(p1, p2));
- primary.flushCommits();
-
- // cleanup after ourselves
- cleanup(state);
- }
-
- /**
- * @param tableName name of the table to create for the test
- * @return the supporting state for the test
- */
- private TestState setupTest(String tableName) throws IOException {
- byte[] tableNameBytes = Bytes.toBytes(tableName);
- @SuppressWarnings("deprecation")
- HTableDescriptor desc = new HTableDescriptor(tableNameBytes);
- desc.addFamily(FAM1);
- // add the necessary simple options to create the builder
- Map<String, String> indexerOpts = new HashMap<String, String>();
- // just need to set the codec - we are going to set it later, but we need something here or the
- // initializer blows up.
- indexerOpts.put(NonTxIndexBuilder.CODEC_CLASS_NAME_KEY,
- CoveredIndexCodecForTesting.class.getName());
- Indexer.enableIndexing(desc, NonTxIndexBuilder.class, indexerOpts, Coprocessor.PRIORITY_USER);
-
- // create the table
- HBaseAdmin admin = UTIL.getHBaseAdmin();
- admin.createTable(desc);
- HTable primary = new HTable(UTIL.getConfiguration(), tableNameBytes);
-
- // overwrite the codec so we can verify the current state
- Region region = UTIL.getMiniHBaseCluster().getRegions(tableNameBytes).get(0);
- Indexer indexer =
- (Indexer) region.getCoprocessorHost().findCoprocessor(Indexer.class.getName());
- NonTxIndexBuilder builder =
- (NonTxIndexBuilder) indexer.getBuilderForTesting();
- VerifyingIndexCodec codec = new VerifyingIndexCodec();
- builder.setIndexCodecForTesting(codec);
-
- // setup the Puts we want to write
- final long ts = System.currentTimeMillis();
- EnvironmentEdge edge = new EnvironmentEdge() {
-
- @Override
- public long currentTime() {
- return ts;
- }
- };
- EnvironmentEdgeManager.injectEdge(edge);
-
- return new TestState(primary, codec, ts);
- }
-
- /**
- * Cleanup the test based on the passed state.
- * @param state
- */
- private void cleanup(TestState state) throws IOException {
- EnvironmentEdgeManager.reset();
- state.table.close();
- UTIL.deleteTable(state.table.getTableName());
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/FailWithoutRetriesIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/FailWithoutRetriesIT.java b/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/FailWithoutRetriesIT.java
deleted file mode 100644
index ba8340c..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/hbase/index/covered/FailWithoutRetriesIT.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.hbase.index.covered;
-
-import static org.apache.phoenix.query.BaseTest.setUpConfigForMiniCluster;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.DoNotRetryIOException;
-import org.apache.hadoop.hbase.HBaseTestingUtility;
-import org.apache.hadoop.hbase.HColumnDescriptor;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException;
-import org.apache.hadoop.hbase.util.Bytes;
-import org.apache.phoenix.end2end.NeedsOwnMiniClusterTest;
-import org.apache.phoenix.hbase.index.IndexTestingUtils;
-import org.apache.phoenix.hbase.index.Indexer;
-import org.apache.phoenix.hbase.index.TableName;
-import org.apache.phoenix.hbase.index.builder.BaseIndexCodec;
-import org.apache.phoenix.hbase.index.covered.ColumnGroup;
-import org.apache.phoenix.hbase.index.covered.CoveredColumn;
-import org.apache.phoenix.hbase.index.covered.CoveredColumnIndexSpecifierBuilder;
-import org.apache.phoenix.hbase.index.covered.IndexMetaData;
-import org.apache.phoenix.hbase.index.covered.IndexUpdate;
-import org.apache.phoenix.hbase.index.covered.TableState;
-import org.apache.phoenix.hbase.index.util.IndexManagementUtil;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-/**
- * If {@link DoNotRetryIOException} is not subclassed correctly (with the {@link String} constructor),
- * {@link MultiResponse#readFields(java.io.DataInput)} will not correctly deserialize the exception, and just return
- * <tt>null</tt> to the client, which then just goes and retries.
- */
-@Category(NeedsOwnMiniClusterTest.class)
-public class FailWithoutRetriesIT {
-
- private static final Log LOG = LogFactory.getLog(FailWithoutRetriesIT.class);
- @Rule
- public TableName table = new TableName();
-
- private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
-
- private String getIndexTableName() {
- return Bytes.toString(table.getTableName()) + "_index";
- }
-
- public static class FailingTestCodec extends BaseIndexCodec {
-
- @Override
- public Iterable<IndexUpdate> getIndexDeletes(TableState state, IndexMetaData context) throws IOException {
- throw new RuntimeException("Intentionally failing deletes for " + FailWithoutRetriesIT.class.getName());
- }
-
- @Override
- public Iterable<IndexUpdate> getIndexUpserts(TableState state, IndexMetaData context) throws IOException {
- throw new RuntimeException("Intentionally failing upserts for " + FailWithoutRetriesIT.class.getName());
- }
- }
-
- @BeforeClass
- public static void setupCluster() throws Exception {
- // setup and verify the config
- Configuration conf = UTIL.getConfiguration();
- setUpConfigForMiniCluster(conf);
- IndexTestingUtils.setupConfig(conf);
- IndexManagementUtil.ensureMutableIndexingCorrectlyConfigured(conf);
- // start the cluster
- UTIL.startMiniCluster();
- }
-
- /**
- * If this test times out, then we didn't fail quickly enough. {@link Indexer} maybe isn't rethrowing the exception
- * correctly?
- * <p>
- * We use a custom codec to enforce the thrown exception.
- *
- * @throws Exception
- */
- @Test(timeout = 300000)
- public void testQuickFailure() throws Exception {
- // incorrectly setup indexing for the primary table - target index table doesn't exist, which
- // should quickly return to the client
- byte[] family = Bytes.toBytes("family");
- ColumnGroup fam1 = new ColumnGroup(getIndexTableName());
- // values are [col1]
- fam1.add(new CoveredColumn(family, CoveredColumn.ALL_QUALIFIERS));
- CoveredColumnIndexSpecifierBuilder builder = new CoveredColumnIndexSpecifierBuilder();
- // add the index family
- builder.addIndexGroup(fam1);
- // usually, we would create the index table here, but we don't for the sake of the test.
-
- // setup the primary table
- String primaryTable = Bytes.toString(table.getTableName());
- @SuppressWarnings("deprecation")
- HTableDescriptor pTable = new HTableDescriptor(primaryTable);
- pTable.addFamily(new HColumnDescriptor(family));
- // override the codec so we can use our test one
- builder.build(pTable, FailingTestCodec.class);
-
- // create the primary table
- HBaseAdmin admin = UTIL.getHBaseAdmin();
- admin.createTable(pTable);
- Configuration conf = new Configuration(UTIL.getConfiguration());
- // up the number of retries/wait time to make it obvious that we are failing with retries here
- conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 20);
- conf.setLong(HConstants.HBASE_CLIENT_PAUSE, 1000);
- HTable primary = new HTable(conf, primaryTable);
- primary.setAutoFlush(false, true);
-
- // do a simple put that should be indexed
- Put p = new Put(Bytes.toBytes("row"));
- p.add(family, null, Bytes.toBytes("value"));
- primary.put(p);
- try {
- primary.flushCommits();
- fail("Shouldn't have gotten a successful write to the primary table");
- } catch (RetriesExhaustedWithDetailsException e) {
- LOG.info("Correclty got a failure of the put!");
- }
- primary.close();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/it/java/org/apache/phoenix/tx/TransactionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/tx/TransactionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/tx/TransactionIT.java
index c76e19c..9286c2e 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/tx/TransactionIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/tx/TransactionIT.java
@@ -44,6 +44,8 @@ import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.query.QueryServicesOptions;
import org.apache.phoenix.schema.PTableKey;
import org.apache.phoenix.transaction.PhoenixTransactionContext;
+import org.apache.phoenix.util.EnvironmentEdgeManager;
+import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.StringUtil;
import org.apache.phoenix.util.TestUtil;
@@ -52,6 +54,27 @@ import org.junit.Test;
public class TransactionIT extends ParallelStatsDisabledIT {
@Test
+ public void testQueryWithSCN() throws Exception {
+ String tableName = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props);) {
+ conn.createStatement().execute(
+ "CREATE TABLE " + tableName + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR) TRANSACTIONAL=true");
+ }
+ props.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(EnvironmentEdgeManager.currentTimeMillis()));
+ try (Connection conn = DriverManager.getConnection(getUrl(), props);) {
+ try {
+ conn.createStatement().executeQuery("SELECT * FROM " + tableName);
+ fail();
+ } catch (SQLException e) {
+ assertEquals("Unexpected Exception",
+ SQLExceptionCode.CANNOT_START_TRANSACTION_WITH_SCN_SET
+ .getErrorCode(), e.getErrorCode());
+ }
+ }
+ }
+
+ @Test
public void testReCreateTxnTableAfterDroppingExistingNonTxnTable() throws SQLException {
String tableName = generateUniqueName();
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java
index 6448edc..4e5580a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java
@@ -52,7 +52,6 @@ import org.apache.phoenix.parse.PrimaryKeyConstraint;
import org.apache.phoenix.parse.SQLParser;
import org.apache.phoenix.parse.SelectStatement;
import org.apache.phoenix.parse.TableName;
-import org.apache.phoenix.query.DelegateConnectionQueryServices;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.ColumnRef;
import org.apache.phoenix.schema.MetaDataClient;
@@ -84,7 +83,6 @@ public class CreateTableCompiler {
final PhoenixConnection connection = statement.getConnection();
ColumnResolver resolver = FromCompiler.getResolverForCreation(create, connection);
PTableType type = create.getTableType();
- PhoenixConnection connectionToBe = connection;
PTable parentToBe = null;
ViewType viewTypeToBe = null;
Scan scan = new Scan();
@@ -148,24 +146,6 @@ public class CreateTableCompiler {
viewStatementToBe = QueryUtil.getViewStatement(baseTableName.getSchemaName(), baseTableName.getTableName(), buf.toString());
}
if (viewTypeToBe != ViewType.MAPPED) {
- Long scn = connection.getSCN();
- connectionToBe = (scn != null || tableRef.getTable().isTransactional()) ? connection :
- // If we haved no SCN on our connection and the base table is not transactional, freeze the SCN at when
- // the base table was resolved to prevent any race condition on
- // the error checking we do for the base table. The only potential
- // issue is if the base table lives on a different region server
- // than the new table will, then we're relying here on the system
- // clocks being in sync.
- new PhoenixConnection(
- // When the new table is created, we still want to cache it
- // on our connection.
- new DelegateConnectionQueryServices(connection.getQueryServices()) {
- @Override
- public void addTable(PTable table, long resolvedTime) throws SQLException {
- connection.addTable(table, resolvedTime);
- }
- },
- connection, tableRef.getCurrentTime()+1);
viewColumnConstantsToBe = new byte[nColumns][];
ViewWhereExpressionVisitor visitor = new ViewWhereExpressionVisitor(parentToBe, viewColumnConstantsToBe);
where.accept(visitor);
@@ -201,7 +181,7 @@ public class CreateTableCompiler {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.SPLIT_POINT_NOT_CONSTANT)
.setMessage("Node: " + node).build().buildException();
}
- final MetaDataClient client = new MetaDataClient(connectionToBe);
+ final MetaDataClient client = new MetaDataClient(connection);
final PTable parent = parentToBe;
return new BaseMutationPlan(context, operation) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
index 6f45e28..6445894 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/UpsertCompiler.java
@@ -352,8 +352,12 @@ public class UpsertCompiler {
// - transactional table with a connection having an SCN
if (table.getType() == PTableType.VIEW && table.getViewType().isReadOnly()) {
throw new ReadOnlyTableException(schemaName,tableName);
- }
- else if (table.isTransactional() && connection.getSCN() != null) {
+ } else if (connection.isBuildingIndex() && table.getType() != PTableType.INDEX) {
+ throw new SQLExceptionInfo.Builder(SQLExceptionCode.ONLY_INDEX_UPDATABLE_AT_SCN)
+ .setSchemaName(schemaName)
+ .setTableName(tableName)
+ .build().buildException();
+ } else if (table.isTransactional() && connection.getSCN() != null) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.CANNOT_SPECIFY_SCN_FOR_TXN_TABLE).setSchemaName(schemaName)
.setTableName(tableName).build().buildException();
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataRegionObserver.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataRegionObserver.java b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataRegionObserver.java
index 8f02901..5717c70 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataRegionObserver.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/coprocessor/MetaDataRegionObserver.java
@@ -530,9 +530,6 @@ public class MetaDataRegionObserver extends BaseRegionObserver {
int indexRebuildRpcRetriesCounter =
config.getInt(QueryServices.INDEX_REBUILD_RPC_RETRIES_COUNTER,
QueryServicesOptions.DEFAULT_INDEX_REBUILD_RPC_RETRIES_COUNTER);
- // Set SCN so that we don't ping server and have the upper bound set back to
- // the timestamp when the failure occurred.
- props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(Long.MAX_VALUE));
// Set various phoenix and hbase level timeouts and rpc retries
props.setProperty(QueryServices.THREAD_TIMEOUT_MS_ATTRIB,
Long.toString(indexRebuildQueryTimeoutMs));
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
index 76cc2ba..f25f7f1 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
@@ -183,7 +183,8 @@ public enum SQLExceptionCode {
ROWTIMESTAMP_NOT_ALLOWED_ON_VIEW(531, "42908", "Declaring a column as row_timestamp is not allowed for views."),
INVALID_SCN(532, "42909", "Value of SCN cannot be less than zero."),
INVALID_REPLAY_AT(533, "42910", "Value of REPLAY_AT cannot be less than zero."),
- UNEQUAL_SCN_AND_REPLAY_AT(534, "42911", "If both specified, values of CURRENT_SCN and REPLAY_AT must be equal."),
+ UNEQUAL_SCN_AND_BUILD_INDEX_AT(534, "42911", "If both specified, values of CURRENT_SCN and BUILD_INDEX_AT must be equal."),
+ ONLY_INDEX_UPDATABLE_AT_SCN(535, "42912", "Only an index may be updated when the BUILD_INDEX_AT property is specified"),
/**
* HBase and Phoenix specific implementation defined sub-classes.
* Column family related exceptions.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
index f8cf9ad..4f96207 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/execute/MutationState.java
@@ -585,14 +585,6 @@ public class MutationState implements SQLCloseable {
rowMutationsPertainingToIndex = rowMutations;
}
mutationList.addAll(rowMutations);
- if (connection.isReplayMutations()) {
- // Propagate IGNORE_NEWER_MUTATIONS when replaying mutations since there will be
- // future dated data row mutations that will get in the way of generating the
- // correct index rows on replay.
- for (Mutation mutation : rowMutations) {
- mutation.setAttribute(BaseScannerRegionObserver.REPLAY_WRITES, BaseScannerRegionObserver.REPLAY_TABLE_AND_INDEX_WRITES);
- }
- }
if (mutationsPertainingToIndex != null) mutationsPertainingToIndex
.addAll(rowMutationsPertainingToIndex);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/06f58d56/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/Indexer.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/Indexer.java b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/Indexer.java
index e9d735d..8957b30 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/Indexer.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/hbase/index/Indexer.java
@@ -99,7 +99,6 @@ import org.apache.phoenix.trace.TracingUtils;
import org.apache.phoenix.trace.util.NullSpan;
import org.apache.phoenix.util.EnvironmentEdgeManager;
import org.apache.phoenix.util.IndexUtil;
-import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.QueryUtil;
@@ -395,14 +394,6 @@ public class Indexer extends BaseRegionObserver {
"Somehow didn't return an index update but also didn't propagate the failure to the client!");
}
- // Assume time stamp of mutation a client defined time stamp if it's not within
- // a factor of ten of the current time.
- // TODO: get rid of this and have client pass LATEST_TIMESTAMP unless an SCN is set
- private static boolean isProbablyClientControlledTimeStamp(Mutation m) {
- double ratio = EnvironmentEdgeManager.currentTimeMillis() / MetaDataUtil.getClientTimeStamp(m);
- return ratio > 10 || ratio < 0.10;
- }
-
private static void setTimeStamp(KeyValue kv, byte[] tsBytes) {
int tsOffset = kv.getTimestampOffset();
System.arraycopy(tsBytes, 0, kv.getBuffer(), tsOffset, Bytes.SIZEOF_LONG);
@@ -470,7 +461,7 @@ public class Indexer extends BaseRegionObserver {
Mutation firstMutation = miniBatchOp.getOperation(0);
ReplayWrite replayWrite = this.builder.getReplayWrite(firstMutation);
- boolean resetTimeStamp = replayWrite == null && !isProbablyClientControlledTimeStamp(firstMutation);
+ boolean resetTimeStamp = replayWrite == null;
long now = EnvironmentEdgeManager.currentTimeMillis();
byte[] byteNow = Bytes.toBytes(now);
for (int i = 0; i < miniBatchOp.size(); i++) {
[20/25] phoenix git commit: PHOENIX-4248 Breakup IndexExpressionIT
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
deleted file mode 100644
index b540ad1..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
+++ /dev/null
@@ -1,1194 +0,0 @@
-/*
- * 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.end2end.index;
-
-import static org.apache.phoenix.query.QueryConstants.MILLIS_IN_DAY;
-import static org.apache.phoenix.util.TestUtil.ROW5;
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Properties;
-import java.util.Random;
-
-import org.apache.hadoop.hbase.Cell;
-import org.apache.hadoop.hbase.CellScanner;
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory;
-import org.apache.phoenix.compile.ColumnResolver;
-import org.apache.phoenix.compile.FromCompiler;
-import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
-import org.apache.phoenix.jdbc.PhoenixResultSet;
-import org.apache.phoenix.jdbc.PhoenixStatement;
-import org.apache.phoenix.parse.NamedTableNode;
-import org.apache.phoenix.parse.TableName;
-import org.apache.phoenix.query.BaseTest;
-import org.apache.phoenix.schema.PTable;
-import org.apache.phoenix.schema.PTableImpl;
-import org.apache.phoenix.schema.PTableKey;
-import org.apache.phoenix.schema.PTableType;
-import org.apache.phoenix.util.DateUtil;
-import org.apache.phoenix.util.EnvironmentEdgeManager;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.apache.phoenix.util.ReadOnlyProps;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TestUtil;
-import org.apache.phoenix.util.TransactionUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-@RunWith(Parameterized.class)
-public abstract class IndexIT extends ParallelStatsDisabledIT {
- private static final Random RAND = new Random();
-
- private final boolean localIndex;
- private final boolean transactional;
- private final boolean mutable;
- private final String tableDDLOptions;
-
- protected IndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
- this.localIndex = localIndex;
- this.transactional = transactional;
- this.mutable = mutable;
- StringBuilder optionBuilder = new StringBuilder();
- if (!columnEncoded) {
- if (optionBuilder.length()!=0)
- optionBuilder.append(",");
- optionBuilder.append("COLUMN_ENCODED_BYTES=0");
- }
- if (!mutable) {
- if (optionBuilder.length()!=0)
- optionBuilder.append(",");
- optionBuilder.append("IMMUTABLE_ROWS=true");
- if (!columnEncoded) {
- optionBuilder.append(",IMMUTABLE_STORAGE_SCHEME="+PTableImpl.ImmutableStorageScheme.ONE_CELL_PER_COLUMN);
- }
- }
- if (transactional) {
- if (optionBuilder.length()!=0)
- optionBuilder.append(",");
- optionBuilder.append(" TRANSACTIONAL=true ");
- }
- this.tableDDLOptions = optionBuilder.toString();
- }
-
- @Test
- public void testIndexWithNullableFixedWithCols() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
-
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
- + " (char_col1 ASC, int_col1 ASC)"
- + " INCLUDE (long_col1, long_col2)";
- stmt.execute(ddl);
-
- String query = "SELECT d.char_col1, int_col1 from " + fullTableName + " as d";
- ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex) {
- assertEquals(
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + tableName + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT",
- QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + indexName + "\n"
- + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("chara", rs.getString(1));
- assertEquals("chara", rs.getString("char_col1"));
- assertEquals(2, rs.getInt(2));
- assertTrue(rs.next());
- assertEquals("chara", rs.getString(1));
- assertEquals(3, rs.getInt(2));
- assertTrue(rs.next());
- assertEquals("chara", rs.getString(1));
- assertEquals(4, rs.getInt(2));
- assertFalse(rs.next());
-
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
-
- query = "SELECT char_col1, int_col1 from " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
-
- query = "SELECT char_col1, int_col1 from "+indexName;
- try{
- rs = conn.createStatement().executeQuery(query);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.TABLE_UNDEFINED.getErrorCode(), e.getErrorCode());
- }
- }
- }
-
- @Test
- public void testDeleteFromAllPKColumnIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
- + " (long_pk, varchar_pk)"
- + " INCLUDE (long_col1, long_col2)";
- stmt.execute(ddl);
-
- ResultSet rs;
-
- rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
- assertTrue(rs.next());
- assertEquals(3,rs.getInt(1));
- rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexName);
- assertTrue(rs.next());
- assertEquals(3,rs.getInt(1));
-
- String dml = "DELETE from " + fullTableName + " WHERE long_col2 = 4";
- assertEquals(1,conn.createStatement().executeUpdate(dml));
- conn.commit();
-
- String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertFalse(rs.next());
-
- query = "SELECT long_pk FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertFalse(rs.next());
-
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertFalse(rs.next());
-
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
- }
- }
-
- @Test
- public void testCreateIndexAfterUpsertStarted() throws Exception {
- testCreateIndexAfterUpsertStarted(false,
- SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()),
- SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()));
- }
-
- @Test
- public void testCreateIndexAfterUpsertStartedTxnl() throws Exception {
- if (transactional) {
- testCreateIndexAfterUpsertStarted(true,
- SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()),
- SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, generateUniqueName()));
- }
- }
-
- private void testCreateIndexAfterUpsertStarted(boolean readOwnWrites, String fullTableName, String fullIndexName) throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- try (Connection conn1 = DriverManager.getConnection(getUrl(), props)) {
- conn1.setAutoCommit(true);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt1 = conn1.createStatement();
- stmt1.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
-
- ResultSet rs;
-
- rs = conn1.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
- assertTrue(rs.next());
- assertEquals(3,rs.getInt(1));
-
- try (Connection conn2 = DriverManager.getConnection(getUrl(), props)) {
-
- String upsert = "UPSERT INTO " + fullTableName
- + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
- PreparedStatement pstmt2 = conn2.prepareStatement(upsert);
- pstmt2.setString(1, "varchar4");
- pstmt2.setString(2, "char4");
- pstmt2.setInt(3, 4);
- pstmt2.setLong(4, 4L);
- pstmt2.setBigDecimal(5, new BigDecimal(4.0));
- Date date = DateUtil.parseDate("2015-01-01 00:00:00");
- pstmt2.setDate(6, date);
- pstmt2.setString(7, "varchar_a");
- pstmt2.setString(8, "chara");
- pstmt2.setInt(9, 2);
- pstmt2.setLong(10, 2L);
- pstmt2.setBigDecimal(11, new BigDecimal(2.0));
- pstmt2.setDate(12, date);
- pstmt2.setString(13, "varchar_b");
- pstmt2.setString(14, "charb");
- pstmt2.setInt(15, 3);
- pstmt2.setLong(16, 3L);
- pstmt2.setBigDecimal(17, new BigDecimal(3.0));
- pstmt2.setDate(18, date);
- pstmt2.executeUpdate();
-
- if (readOwnWrites) {
- String query = "SELECT long_pk FROM " + fullTableName + " WHERE long_pk=4";
- rs = conn2.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertFalse(rs.next());
- }
-
- String indexName = SchemaUtil.getTableNameFromFullName(fullIndexName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
- + " (long_pk, varchar_pk)"
- + " INCLUDE (long_col1, long_col2)";
- stmt1.execute(ddl);
-
- /*
- * Commit upsert after index created through different connection.
- * This forces conn2 (which doesn't know about the index yet) to update the metadata
- * at commit time, recognize the new index, and generate the correct metadata (or index
- * rows for immutable indexes).
- *
- * For transactional data, this is problematic because the index
- * gets a timestamp *after* the commit timestamp of conn2 and thus won't be seen during
- * the commit. Also, when the index is being built, the data hasn't yet been committed
- * and thus won't be part of the initial index build (fixed by PHOENIX-2446).
- */
- conn2.commit();
-
- stmt1 = conn1.createStatement();
- rs = stmt1.executeQuery("SELECT COUNT(*) FROM " + fullTableName);
- assertTrue(rs.next());
- assertEquals(4,rs.getInt(1));
- assertEquals(fullIndexName, stmt1.unwrap(PhoenixStatement.class).getQueryPlan().getTableRef().getTable().getName().getString());
-
- String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
- rs = conn1.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(2L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(4L, rs.getLong(1));
- assertFalse(rs.next());
- }
- }
- }
-
- @Test
- public void testDeleteFromNonPKColumnIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
-
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName
- + " (long_col1, long_col2)"
- + " INCLUDE (decimal_col1, decimal_col2)";
- stmt.execute(ddl);
- }
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- ResultSet rs;
-
- rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullTableName);
- assertTrue(rs.next());
- assertEquals(3,rs.getInt(1));
- rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexName);
- assertTrue(rs.next());
- assertEquals(3,rs.getInt(1));
-
- String dml = "DELETE from " + fullTableName + " WHERE long_col2 = 4";
- assertEquals(1,conn.createStatement().executeUpdate(dml));
- conn.commit();
-
- // query the data table
- String query = "SELECT /*+ NO_INDEX */ long_pk FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertFalse(rs.next());
-
- // query the index table
- query = "SELECT long_pk FROM " + fullTableName + " ORDER BY long_col1";
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(1L, rs.getLong(1));
- assertTrue(rs.next());
- assertEquals(3L, rs.getLong(1));
- assertFalse(rs.next());
-
- conn.createStatement().execute("DROP INDEX " + indexName + " ON " + fullTableName);
- }
- }
-
- @Test
- public void testGroupByCount() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col2)";
- stmt.execute(ddl);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT int_col2, COUNT(*) FROM " + fullTableName + " GROUP BY int_col2");
- assertTrue(rs.next());
- assertEquals(1,rs.getInt(2));
- }
- }
-
- @Test
- public void testSelectDistinctOnTableWithSecondaryImmutableIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col2)";
- conn.createStatement().execute(ddl);
- ResultSet rs = conn.createStatement().executeQuery("SELECT distinct int_col2 FROM " + fullTableName + " where int_col2 > 0");
- assertTrue(rs.next());
- assertEquals(3, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(4, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(5, rs.getInt(1));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testInClauseWithIndexOnColumnOfUsignedIntType() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullTableName + " (int_col1)";
- stmt.execute(ddl);
- ResultSet rs = conn.createStatement().executeQuery("SELECT int_col1 FROM " + fullTableName + " where int_col1 IN (1, 2, 3, 4)");
- assertTrue(rs.next());
- assertEquals(2, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(3, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(4, rs.getInt(1));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void createIndexOnTableWithSpecifiedDefaultCF() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- String ddl ="CREATE TABLE " + fullTableName
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) DEFAULT_COLUMN_FAMILY='A'" + (!tableDDLOptions.isEmpty() ? "," + tableDDLOptions : "");
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
-
- query = "SELECT * FROM " + tableName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- String options = localIndex ? "SALT_BUCKETS=10, MULTI_TENANT=true, IMMUTABLE_ROWS=true, DISABLE_WAL=true" : "";
- conn.createStatement().execute(
- "CREATE INDEX " + indexName + " ON " + fullTableName + " (v1) INCLUDE (v2) " + options);
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- //check options set correctly on index
- TableName indexTableName = TableName.create(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- NamedTableNode indexNode = NamedTableNode.create(null, indexTableName, null);
- ColumnResolver resolver = FromCompiler.getResolver(indexNode, conn.unwrap(PhoenixConnection.class));
- PTable indexTable = resolver.getTables().get(0).getTable();
- // Can't set IMMUTABLE_ROWS, MULTI_TENANT or DEFAULT_COLUMN_FAMILY_NAME on an index
- assertNull(indexTable.getDefaultFamilyName());
- assertFalse(indexTable.isMultiTenant());
- assertEquals(mutable, !indexTable.isImmutableRows()); // Should match table
- if(localIndex) {
- assertEquals(10, indexTable.getBucketNum().intValue());
- assertTrue(indexTable.isWALDisabled());
- }
- }
- }
-
- @Test
- public void testIndexWithNullableDateCol() throws Exception {
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- Date date = new Date(System.currentTimeMillis());
-
- TestUtil.createMultiCFTestTable(conn, fullTableName, tableDDLOptions);
- populateMultiCFTestTable(fullTableName, date);
- String ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (date_col)";
- conn.createStatement().execute(ddl);
-
- String query = "SELECT int_pk from " + fullTableName ;
- ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if (localIndex) {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName +" [1]\n"
- + " SERVER FILTER BY FIRST KEY ONLY\n"
- + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
- + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(2, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(1, rs.getInt(1));
- assertTrue(rs.next());
- assertEquals(3, rs.getInt(1));
- assertFalse(rs.next());
-
- query = "SELECT date_col from " + fullTableName + " order by date_col" ;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if (localIndex) {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1]\n"
- + " SERVER FILTER BY FIRST KEY ONLY\n"
- + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
- + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(date, rs.getDate(1));
- assertTrue(rs.next());
- assertEquals(new Date(date.getTime() + MILLIS_IN_DAY), rs.getDate(1));
- assertTrue(rs.next());
- assertEquals(new Date(date.getTime() + 2 * MILLIS_IN_DAY), rs.getDate(1));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testSelectAllAndAliasWithIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- String ddl = "CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) " + tableDDLOptions;
- conn.createStatement().execute(ddl);
- query = "SELECT * FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (v2 DESC) INCLUDE (v1)";
- conn.createStatement().execute(ddl);
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
- stmt.setString(1,"a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- stmt.setString(1,"b");
- stmt.setString(2, "y");
- stmt.setString(3, "2");
- stmt.execute();
- conn.commit();
-
- query = "SELECT * FROM " + fullTableName;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex){
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("b",rs.getString(1));
- assertEquals("y",rs.getString(2));
- assertEquals("2",rs.getString(3));
- assertEquals("b",rs.getString("k"));
- assertEquals("y",rs.getString("v1"));
- assertEquals("2",rs.getString("v2"));
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("x",rs.getString(2));
- assertEquals("1",rs.getString(3));
- assertEquals("a",rs.getString("k"));
- assertEquals("x",rs.getString("v1"));
- assertEquals("1",rs.getString("v2"));
- assertFalse(rs.next());
-
- query = "SELECT v1 as foo FROM " + fullTableName + " WHERE v2 = '1' ORDER BY foo";
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex){
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +fullTableName + " [1,~'1']\n" +
- " SERVER SORTED BY [\"V1\"]\n" +
- "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +fullIndexName + " [~'1']\n" +
- " SERVER SORTED BY [\"V1\"]\n" +
- "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("x",rs.getString(1));
- assertEquals("x",rs.getString("foo"));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testSelectCF() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- String ddl = "CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, a.v1 VARCHAR, a.v2 VARCHAR, b.v1 VARCHAR) " + tableDDLOptions;
- conn.createStatement().execute(ddl);
- query = "SELECT * FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
- ddl = "CREATE " + (localIndex ? " LOCAL " : "") + " INDEX " + indexName + " ON " + fullTableName + " (v2 DESC) INCLUDE (a.v1)";
- conn.createStatement().execute(ddl);
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?,?)");
- stmt.setString(1,"a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.setString(4, "A");
- stmt.execute();
- stmt.setString(1,"b");
- stmt.setString(2, "y");
- stmt.setString(3, "2");
- stmt.setString(4, "B");
- stmt.execute();
- conn.commit();
-
- query = "SELECT * FROM " + fullTableName;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullTableName, QueryUtil.getExplainPlan(rs));
-
- query = "SELECT a.* FROM " + fullTableName;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex) {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
- }
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("y",rs.getString(1));
- assertEquals("2",rs.getString(2));
- assertEquals("y",rs.getString("v1"));
- assertEquals("2",rs.getString("v2"));
- assertTrue(rs.next());
- assertEquals("x",rs.getString(1));
- assertEquals("1",rs.getString(2));
- assertEquals("x",rs.getString("v1"));
- assertEquals("1",rs.getString("v2"));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testUpsertAfterIndexDrop() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- // make sure that the tables are empty, but reachable
- conn.createStatement().execute(
- "CREATE TABLE " + fullTableName
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)" + tableDDLOptions);
- query = "SELECT * FROM " + fullTableName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- conn.createStatement().execute(
- "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + " (v1, v2)");
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- // load some data into the table
- PreparedStatement stmt =
- conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- conn.commit();
-
- // make sure the index is working as expected
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("x", rs.getString(1));
- assertEquals("1", rs.getString(2));
- assertEquals("a", rs.getString(3));
- assertFalse(rs.next());
-
- String ddl = "DROP INDEX " + indexName + " ON " + fullTableName;
- conn.createStatement().execute(ddl);
-
- stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + "(k, v1) VALUES(?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "y");
- stmt.execute();
- conn.commit();
-
- query = "SELECT * FROM " + fullTableName;
-
- // check that the data table matches as expected
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("y", rs.getString(2));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testMultipleUpdatesAcrossRegions() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
-
- String testTable = fullTableName+"_MULTIPLE_UPDATES";
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- // make sure that the tables are empty, but reachable
- conn.createStatement().execute(
- "CREATE TABLE " + testTable
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) "
- + (!tableDDLOptions.isEmpty() ? tableDDLOptions : "") + " SPLIT ON ('b')");
- query = "SELECT * FROM " + testTable;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- conn.createStatement().execute(
- "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + testTable + " (v1, v2)");
- query = "SELECT * FROM " + fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- // load some data into the table
- PreparedStatement stmt =
- conn.prepareStatement("UPSERT INTO " + testTable + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- stmt.setString(1, "b");
- stmt.setString(2, "y");
- stmt.setString(3, "2");
- stmt.execute();
- stmt.setString(1, "c");
- stmt.setString(2, "z");
- stmt.setString(3, "3");
- stmt.execute();
- conn.commit();
-
- query = "SELECT /*+ NO_INDEX */ * FROM " + testTable;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("x", rs.getString(2));
- assertEquals("1", rs.getString(3));
- assertTrue(rs.next());
- assertEquals("b", rs.getString(1));
- assertEquals("y", rs.getString(2));
- assertEquals("2", rs.getString(3));
- assertTrue(rs.next());
- assertEquals("c", rs.getString(1));
- assertEquals("z", rs.getString(2));
- assertEquals("3", rs.getString(3));
- assertFalse(rs.next());
-
- // make sure the index is working as expected
- query = "SELECT * FROM " + testTable;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if (localIndex) {
- assertEquals("CLIENT PARALLEL 2-WAY RANGE SCAN OVER " + testTable+" [1]\n"
- + " SERVER FILTER BY FIRST KEY ONLY\n"
- + "CLIENT MERGE SORT",
- QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName + "\n"
- + " SERVER FILTER BY FIRST KEY ONLY",
- QueryUtil.getExplainPlan(rs));
- }
-
- // check that the data table matches as expected
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("x", rs.getString(2));
- assertEquals("1", rs.getString(3));
- assertTrue(rs.next());
- assertEquals("b", rs.getString(1));
- assertEquals("y", rs.getString(2));
- assertEquals("2", rs.getString(3));
- assertTrue(rs.next());
- assertEquals("c", rs.getString(1));
- assertEquals("z", rs.getString(2));
- assertEquals("3", rs.getString(3));
- assertFalse(rs.next());
- }
- }
-
- @Test
- public void testIndexWithCaseSensitiveCols() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- conn.createStatement().execute("CREATE TABLE " + fullTableName + " (k VARCHAR NOT NULL PRIMARY KEY, \"V1\" VARCHAR, \"v2\" VARCHAR)"+tableDDLOptions);
- query = "SELECT * FROM "+fullTableName;
- rs = conn.createStatement().executeQuery(query);
- long ts = conn.unwrap(PhoenixConnection.class).getTable(new PTableKey(null,fullTableName)).getTimeStamp();
- assertFalse(rs.next());
- conn.createStatement().execute(
- "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + "(\"v2\") INCLUDE (\"V1\")");
- query = "SELECT * FROM "+fullIndexName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + fullTableName + " VALUES(?,?,?)");
- stmt.setString(1,"a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- stmt.setString(1,"b");
- stmt.setString(2, "y");
- stmt.setString(3, "2");
- stmt.execute();
- conn.commit();
-
- query = "SELECT * FROM " + fullTableName + " WHERE \"v2\" = '1'";
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex){
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1,'1']\n"
- + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullIndexName + " ['1']", QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("x",rs.getString(2));
- assertEquals("1",rs.getString(3));
- assertEquals("a",rs.getString("k"));
- assertEquals("x",rs.getString("V1"));
- assertEquals("1",rs.getString("v2"));
- assertFalse(rs.next());
-
- query = "SELECT \"V1\", \"V1\" as foo1, \"v2\" as foo, \"v2\" as \"Foo1\", \"v2\" FROM " + fullTableName + " ORDER BY foo";
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex){
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName + " [1]\nCLIENT MERGE SORT",
- QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER "+fullIndexName, QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("x",rs.getString(1));
- assertEquals("x",rs.getString("V1"));
- assertEquals("x",rs.getString(2));
- assertEquals("x",rs.getString("foo1"));
- assertEquals("1",rs.getString(3));
- assertEquals("1",rs.getString("Foo"));
- assertEquals("1",rs.getString(4));
- assertEquals("1",rs.getString("Foo1"));
- assertEquals("1",rs.getString(5));
- assertEquals("1",rs.getString("v2"));
- assertTrue(rs.next());
- assertEquals("y",rs.getString(1));
- assertEquals("y",rs.getString("V1"));
- assertEquals("y",rs.getString(2));
- assertEquals("y",rs.getString("foo1"));
- assertEquals("2",rs.getString(3));
- assertEquals("2",rs.getString("Foo"));
- assertEquals("2",rs.getString(4));
- assertEquals("2",rs.getString("Foo1"));
- assertEquals("2",rs.getString(5));
- assertEquals("2",rs.getString("v2"));
- assertFalse(rs.next());
-
- assertNoIndexDeletes(conn, ts, fullIndexName);
- }
- }
-
- private void assertNoIndexDeletes(Connection conn, long minTimestamp, String fullIndexName) throws IOException, SQLException {
- if (!this.mutable) {
- PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- PTable index = pconn.getTable(new PTableKey(null, fullIndexName));
- byte[] physicalIndexTable = index.getPhysicalName().getBytes();
- try (HTableInterface hIndex = pconn.getQueryServices().getTable(physicalIndexTable)) {
- Scan scan = new Scan();
- scan.setRaw(true);
- if (this.transactional) {
- minTimestamp = TransactionUtil.convertToNanoseconds(minTimestamp);
- }
- scan.setTimeRange(minTimestamp, HConstants.LATEST_TIMESTAMP);
- ResultScanner scanner = hIndex.getScanner(scan);
- Result result;
- while ((result = scanner.next()) != null) {
- CellScanner cellScanner = result.cellScanner();
- while (cellScanner.advance()) {
- Cell current = cellScanner.current();
- assertEquals (KeyValue.Type.Put.getCode(), current.getTypeByte());
- }
- }
- };
- }
- }
-
- @Test
- public void testInFilterOnIndexedTable() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- String ddl = "CREATE TABLE " + fullTableName +" (PK1 CHAR(2) NOT NULL PRIMARY KEY, CF1.COL1 BIGINT) " + tableDDLOptions;
- conn.createStatement().execute(ddl);
- ddl = "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + "(COL1)";
- conn.createStatement().execute(ddl);
-
- query = "SELECT COUNT(COL1) FROM " + fullTableName +" WHERE COL1 IN (1,25,50,75,100)";
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- }
- }
-
- @Test
- public void testIndexWithDecimalCol() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- String query;
- ResultSet rs;
- Date date = new Date(System.currentTimeMillis());
-
- TestUtil.createMultiCFTestTable(conn, fullTableName, tableDDLOptions);
- populateMultiCFTestTable(fullTableName, date);
- String ddl = null;
- ddl = "CREATE " + (localIndex ? "LOCAL " : "") + "INDEX " + indexName + " ON " + fullTableName + " (decimal_pk) INCLUDE (decimal_col1, decimal_col2)";
- conn.createStatement().execute(ddl);
-
- query = "SELECT decimal_pk, decimal_col1, decimal_col2 from " + fullTableName ;
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- if(localIndex) {
- assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullTableName+" [1]\nCLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
- } else {
- assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + fullIndexName, QueryUtil.getExplainPlan(rs));
- }
-
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals(new BigDecimal("1.1"), rs.getBigDecimal(1));
- assertEquals(new BigDecimal("2.1"), rs.getBigDecimal(2));
- assertEquals(new BigDecimal("3.1"), rs.getBigDecimal(3));
- assertTrue(rs.next());
- assertEquals(new BigDecimal("2.2"), rs.getBigDecimal(1));
- assertEquals(new BigDecimal("3.2"), rs.getBigDecimal(2));
- assertEquals(new BigDecimal("4.2"), rs.getBigDecimal(3));
- assertTrue(rs.next());
- assertEquals(new BigDecimal("3.3"), rs.getBigDecimal(1));
- assertEquals(new BigDecimal("4.3"), rs.getBigDecimal(2));
- assertEquals(new BigDecimal("5.3"), rs.getBigDecimal(3));
- assertFalse(rs.next());
- }
- }
-
- /**
- * Ensure that HTD contains table priorities correctly.
- */
- @Test
- public void testTableDescriptorPriority() throws SQLException, IOException {
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- // Check system tables priorities.
- try (HBaseAdmin admin = driver.getConnectionQueryServices(null, null).getAdmin();
- Connection c = DriverManager.getConnection(getUrl())) {
- ResultSet rs = c.getMetaData().getTables("",
- "\""+ PhoenixDatabaseMetaData.SYSTEM_CATALOG_SCHEMA + "\"",
- null,
- new String[] {PTableType.SYSTEM.toString()});
- ReadOnlyProps p = c.unwrap(PhoenixConnection.class).getQueryServices().getProps();
- while (rs.next()) {
- String schemaName = rs.getString(PhoenixDatabaseMetaData.TABLE_SCHEM);
- String tName = rs.getString(PhoenixDatabaseMetaData.TABLE_NAME);
- org.apache.hadoop.hbase.TableName hbaseTableName = SchemaUtil.getPhysicalTableName(SchemaUtil.getTableName(schemaName, tName), p);
- HTableDescriptor htd = admin.getTableDescriptor(hbaseTableName);
- String val = htd.getValue("PRIORITY");
- assertNotNull("PRIORITY is not set for table:" + htd, val);
- assertTrue(Integer.parseInt(val)
- >= PhoenixRpcSchedulerFactory.getMetadataPriority(config));
- }
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl ="CREATE TABLE " + fullTableName + TestUtil.TEST_TABLE_SCHEMA + tableDDLOptions;
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- conn.setAutoCommit(false);
- Statement stmt = conn.createStatement();
- stmt.execute(ddl);
- BaseTest.populateTestTable(fullTableName);
- ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName
- + " ON " + fullTableName + " (long_col1, long_col2)"
- + " INCLUDE (decimal_col1, decimal_col2)";
- stmt.execute(ddl);
- }
-
- HTableDescriptor dataTable = admin.getTableDescriptor(
- org.apache.hadoop.hbase.TableName.valueOf(fullTableName));
- String val = dataTable.getValue("PRIORITY");
- assertTrue(val == null || Integer.parseInt(val) < HConstants.HIGH_QOS);
-
- if (!localIndex && mutable) {
- HTableDescriptor indexTable = admin.getTableDescriptor(
- org.apache.hadoop.hbase.TableName.valueOf(indexName));
- val = indexTable.getValue("PRIORITY");
- assertNotNull("PRIORITY is not set for table:" + indexTable, val);
- assertTrue(Integer.parseInt(val) >= PhoenixRpcSchedulerFactory.getIndexPriority(config));
- }
- }
- }
-
- @Test
- public void testQueryBackToDataTableWithDescPKColumn() throws SQLException {
- doTestQueryBackToDataTableWithDescPKColumn(true);
- doTestQueryBackToDataTableWithDescPKColumn(false);
- }
-
- private void doTestQueryBackToDataTableWithDescPKColumn(boolean isSecondPKDesc) throws SQLException {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String tableName = "TBL_" + generateUniqueName();
- String indexName = "IND_" + generateUniqueName();
- String fullTableName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, tableName);
- String fullIndexName = SchemaUtil.getTableName(TestUtil.DEFAULT_SCHEMA_NAME, indexName);
-
- try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
- // create data table and index table
- conn.setAutoCommit(true);
- Statement stmt = conn.createStatement();
- String ddl = "CREATE TABLE " + fullTableName + "(p1 integer not null, p2 integer not null, " +
- " a integer, b integer CONSTRAINT PK PRIMARY KEY ";
- if (isSecondPKDesc) {
- ddl += "(p1, p2 desc))";
- } else {
- ddl += "(p1 desc, p2))";
- }
- stmt.executeUpdate(ddl);
- ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + fullIndexName + " on " + fullTableName + "(a)";
- stmt.executeUpdate(ddl);
-
- // upsert a single row
- String upsert = "UPSERT INTO " + fullTableName + " VALUES(1,2,3,4)";
- stmt.executeUpdate(upsert);
-
- // try select with index
- // a = 3, should hit index table, but we select column B, so it will query back to data table
- String query = "SELECT /*+index(" + fullTableName + " " + fullIndexName + "*/ b from " + fullTableName +
- " WHERE a = 3";
- ResultSet rs = stmt.executeQuery(query);
- assertTrue(rs.next());
- assertEquals(4, rs.getInt(1));
- assertFalse(rs.next());
- rs.close();
- stmt.close();
- }
- }
-
- @Test
- public void testReturnedTimestamp() throws Exception {
- String tenantId = getOrganizationId();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- String indexName = generateUniqueName();
- String tableName =
- initATableValues(generateUniqueName(), tenantId, getDefaultSplits(tenantId),
- new Date(System.currentTimeMillis()), null, getUrl(), tableDDLOptions);
- String ddl = "CREATE "+ (localIndex ? "LOCAL " : "") + " INDEX " + indexName + " on " + tableName + "(A_STRING) INCLUDE (B_STRING)";
- conn.createStatement().executeUpdate(ddl);
- String query = "SELECT ENTITY_ID,A_STRING,B_STRING FROM " + tableName + " WHERE organization_id=? and entity_id=?";
-
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
-
- long currentTime = EnvironmentEdgeManager.currentTimeMillis();
- String entityId = mutable ? ROW5 : Integer.toString(Math.abs(RAND.nextInt() % 1000000000));
- PreparedStatement ddlStatement = conn.prepareStatement("UPSERT INTO " + tableName + "(ORGANIZATION_ID, ENTITY_ID,A_STRING) VALUES('" + tenantId + "',?,?)");
- ddlStatement.setString(1, entityId);
- ddlStatement.setString(2, Integer.toString(Math.abs(RAND.nextInt() % 1000000000)));
- ddlStatement.executeUpdate();
- conn.commit();
-
- statement.setString(2, entityId);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertTrue(rs.unwrap(PhoenixResultSet.class).getCurrentRow().getValue(0).getTimestamp() >= currentTime);
- assertEquals(rs.getString(1).trim(), entityId);
- assertFalse(rs.next());
-
- currentTime = EnvironmentEdgeManager.currentTimeMillis();
- entityId = mutable ? ROW5 : Integer.toString(Math.abs(RAND.nextInt() % 1000000000));
- ddlStatement = conn.prepareStatement("UPSERT INTO " + tableName + "(ORGANIZATION_ID, ENTITY_ID,B_STRING) VALUES('" + tenantId + "',?,?)");
- ddlStatement.setString(1, entityId);
- ddlStatement.setString(2, Integer.toString(Math.abs(RAND.nextInt() % 1000000000)));
- ddlStatement.executeUpdate();
- conn.commit();
-
- statement.setString(2, entityId);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertTrue(rs.unwrap(PhoenixResultSet.class).getCurrentRow().getValue(0).getTimestamp() >= currentTime);
- assertEquals(rs.getString(1).trim(), entityId);
- assertFalse(rs.next());
-
- } finally {
- conn.close();
- }
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMaintenanceIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMaintenanceIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMaintenanceIT.java
new file mode 100644
index 0000000..7d02e80
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMaintenanceIT.java
@@ -0,0 +1,457 @@
+/*
+ * 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.end2end.index;
+
+import static org.apache.phoenix.query.QueryConstants.MILLIS_IN_DAY;
+import static org.apache.phoenix.util.TestUtil.INDEX_DATA_SCHEMA;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+public class IndexMaintenanceIT extends ParallelStatsDisabledIT {
+
+ @Test
+ public void testImmutableIndexCreateAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexCreateAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(false, true);
+ }
+
+ @Test
+ public void testMutableIndexCreateAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexCreateAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(true, true);
+ }
+
+ /**
+ * Adds a row to the index data table
+ *
+ * @param i
+ * row number
+ */
+ private void insertRow(PreparedStatement stmt, int i) throws SQLException {
+ // insert row
+ stmt.setString(1, "varchar" + String.valueOf(i));
+ stmt.setString(2, "char" + String.valueOf(i));
+ stmt.setInt(3, i);
+ stmt.setLong(4, i);
+ stmt.setBigDecimal(5, new BigDecimal(i*0.5d));
+ Date date = new Date(DateUtil.parseDate("2015-01-01 00:00:00").getTime() + (i - 1) * MILLIS_IN_DAY);
+ stmt.setDate(6, date);
+ stmt.setString(7, "a.varchar" + String.valueOf(i));
+ stmt.setString(8, "a.char" + String.valueOf(i));
+ stmt.setInt(9, i);
+ stmt.setLong(10, i);
+ stmt.setBigDecimal(11, new BigDecimal(i*0.5d));
+ stmt.setDate(12, date);
+ stmt.setString(13, "b.varchar" + String.valueOf(i));
+ stmt.setString(14, "b.char" + String.valueOf(i));
+ stmt.setInt(15, i);
+ stmt.setLong(16, i);
+ stmt.setBigDecimal(17, new BigDecimal(i*0.5d));
+ stmt.setDate(18, date);
+ stmt.executeUpdate();
+ }
+
+ private void verifyResult(ResultSet rs, int i) throws SQLException {
+ assertTrue(rs.next());
+ assertEquals("VARCHAR" + String.valueOf(i) + "_" + StringUtils.rightPad("CHAR" + String.valueOf(i), 10, ' ')
+ + "_A.VARCHAR" + String.valueOf(i) + "_" + StringUtils.rightPad("B.CHAR" + String.valueOf(i), 10, ' '),
+ rs.getString(1));
+ assertEquals(i * 3, rs.getInt(2));
+ Date date = new Date(DateUtil.parseDate("2015-01-01 00:00:00").getTime() + (i) * MILLIS_IN_DAY);
+ assertEquals(date, rs.getDate(3));
+ assertEquals(date, rs.getDate(4));
+ assertEquals(date, rs.getDate(5));
+ assertEquals("varchar" + String.valueOf(i), rs.getString(6));
+ assertEquals("char" + String.valueOf(i), rs.getString(7));
+ assertEquals(i, rs.getInt(8));
+ assertEquals(i, rs.getLong(9));
+ assertEquals(i*0.5d, rs.getDouble(10), 0.000001);
+ assertEquals(i, rs.getLong(11));
+ assertEquals(i, rs.getLong(12));
+ }
+
+ private void createDataTable(Connection conn, String dataTableName, String tableProps) throws SQLException {
+ String tableDDL = "create table " + dataTableName + TestUtil.TEST_TABLE_SCHEMA + tableProps;
+ conn.createStatement().execute(tableDDL);
+ }
+
+ private void helpTestCreateAndUpdate(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+
+ // create an expression index
+ String ddl = "CREATE "
+ + (localIndex ? "LOCAL" : "")
+ + " INDEX " + indexName + " ON "
+ + fullDataTableName
+ + " ((UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(b.char_col2)),"
+ + " (decimal_pk+int_pk+decimal_col2+int_col1)," + " date_pk+1, date1+1, date2+1 )"
+ + " INCLUDE (long_col1, long_col2)";
+ conn.createStatement().execute(ddl);
+
+ // run select query with expression in WHERE clause
+ String whereSql = "SELECT long_col1, long_col2 from "
+ + fullDataTableName
+ + " WHERE UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(b.char_col2) = ?"
+ + " AND decimal_pk+int_pk+decimal_col2+int_col1=?"
+ // since a.date1 and b.date2 are NULLABLE and date is fixed width, these expressions are stored as
+ // DECIMAL in the index (which is not fixed width)
+ + " AND date_pk+1=? AND date1+1=? AND date2+1=?";
+ PreparedStatement stmt = conn.prepareStatement(whereSql);
+ stmt.setString(1, "VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ");
+ stmt.setInt(2, 3);
+ Date date = DateUtil.parseDate("2015-01-02 00:00:00");
+ stmt.setDate(3, date);
+ stmt.setDate(4, date);
+ stmt.setDate(5, date);
+
+ // verify that the query does a range scan on the index table
+ ResultSet rs = stmt.executeQuery("EXPLAIN " + whereSql);
+ assertEquals(
+ localIndex ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER INDEX_TEST."
+ + dataTableName
+ + " [1,'VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ',3,'2015-01-02 00:00:00.000',1,420,156,800,000,1,420,156,800,000]\nCLIENT MERGE SORT"
+ : "CLIENT PARALLEL 1-WAY RANGE SCAN OVER INDEX_TEST." + indexName + " ['VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ',3,'2015-01-02 00:00:00.000',1,420,156,800,000,1,420,156,800,000]",
+ QueryUtil.getExplainPlan(rs));
+
+ // verify that the correct results are returned
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+
+ // verify all rows in data table are present in index table
+ String indexSelectSql = "SELECT UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(b.char_col2), "
+ + "decimal_pk+int_pk+decimal_col2+int_col1, "
+ + "date_pk+1, date1+1, date2+1, "
+ + "varchar_pk, char_pk, int_pk, long_pk, decimal_pk, "
+ + "long_col1, long_col2 "
+ + "from "
+ + fullDataTableName;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + indexSelectSql);
+ assertEquals(localIndex ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + fullDataTableName
+ + " [1]\nCLIENT MERGE SORT" : "CLIENT PARALLEL 1-WAY FULL SCAN OVER INDEX_TEST." + indexName,
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(indexSelectSql);
+ verifyResult(rs, 1);
+ verifyResult(rs, 2);
+
+ // Insert two more rows to the index data table
+ String upsert = "UPSERT INTO " + fullDataTableName
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ stmt = conn.prepareStatement(upsert);
+ insertRow(stmt, 3);
+ insertRow(stmt, 4);
+ conn.commit();
+
+ rs = conn.createStatement().executeQuery(indexSelectSql);
+ verifyResult(rs, 1);
+ verifyResult(rs, 2);
+ // verify that two rows added after index was created were also added to
+ // the index table
+ verifyResult(rs, 3);
+ verifyResult(rs, 4);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testMutableIndexUpdate() throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ helpTestUpdate(fullDataTableName, indexName, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexUpdate() throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ helpTestUpdate(fullDataTableName, indexName, true);
+ }
+
+ private void helpTestUpdate(String fullDataTableName, String indexName, boolean localIndex) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, "");
+ populateDataTable(conn, fullDataTableName);
+
+ // create an expression index
+ String ddl = "CREATE "
+ + (localIndex ? "LOCAL" : "")
+ + " INDEX " + indexName + " ON "
+ + fullDataTableName
+ + " ((UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2)),"
+ + " (decimal_pk+int_pk+decimal_col2+int_col1)," + " date_pk+1, date1+1, date2+1 )"
+ + " INCLUDE (long_col1, long_col2)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+
+ // update index pk column and covered column
+ String upsert = "UPSERT INTO "
+ + fullDataTableName
+ + "(varchar_pk, char_pk, int_pk, long_pk, decimal_pk, date_pk, varchar_col1, long_col1) VALUES(?, ?, ?, ?, ?, ?, ?, ?)";
+
+ stmt = conn.prepareStatement(upsert);
+ stmt.setString(1, "varchar1");
+ stmt.setString(2, "char1");
+ stmt.setInt(3, 1);
+ stmt.setLong(4, 1l);
+ stmt.setBigDecimal(5, new BigDecimal(0.5));
+ stmt.setDate(6, DateUtil.parseDate("2015-01-01 00:00:00"));
+ stmt.setString(7, "a.varchar_updated");
+ stmt.setLong(8, 101);
+ stmt.executeUpdate();
+ conn.commit();
+
+ // verify only one row was updated in the data table
+ String selectSql = "UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2), long_col1 from "
+ + fullDataTableName;
+ ResultSet rs = conn.createStatement().executeQuery("SELECT /*+ NO_INDEX */ " + selectSql);
+ assertTrue(rs.next());
+ assertEquals("VARCHAR1_CHAR1 _A.VARCHAR_UPDATED_B.CHAR1 ", rs.getString(1));
+ assertEquals(101, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR2_CHAR2 _A.VARCHAR2_B.CHAR2 ", rs.getString(1));
+ assertEquals(2, rs.getLong(2));
+ assertFalse(rs.next());
+
+ // verify that the rows in the index table are also updated
+ rs = conn.createStatement().executeQuery("SELECT " + selectSql);
+ assertTrue(rs.next());
+ assertEquals("VARCHAR1_CHAR1 _A.VARCHAR_UPDATED_B.CHAR1 ", rs.getString(1));
+ assertEquals(101, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR2_CHAR2 _A.VARCHAR2_B.CHAR2 ", rs.getString(1));
+ assertEquals(2, rs.getLong(2));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ private void populateDataTable(Connection conn, String dataTable) throws SQLException {
+ String upsert = "UPSERT INTO " + dataTable
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement stmt1 = conn.prepareStatement(upsert);
+ // insert two rows
+ insertRow(stmt1, 1);
+ insertRow(stmt1, 2);
+ conn.commit();
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionImmutableIndex() throws Exception {
+ helpTestDeleteIndexedExpression(false, false);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionImmutableLocalIndex() throws Exception {
+ helpTestDeleteIndexedExpression(false, true);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionMutableIndex() throws Exception {
+ helpTestDeleteIndexedExpression(true, false);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionMutableLocalIndex() throws Exception {
+ helpTestDeleteIndexedExpression(true, true);
+ }
+
+ protected void helpTestDeleteIndexedExpression(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ String fullIndexTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + indexName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (2*long_col2)";
+ conn.createStatement().execute(ddl);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+
+ conn.setAutoCommit(true);
+ String dml = "DELETE from " + fullDataTableName + " WHERE long_col2 = 2";
+ try {
+ conn.createStatement().execute(dml);
+ if (!mutable) {
+ fail();
+ }
+ } catch (SQLException e) {
+ if (!mutable) {
+ assertEquals(SQLExceptionCode.INVALID_FILTER_ON_IMMUTABLE_ROWS.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ if (!mutable) {
+ dml = "DELETE from " + fullDataTableName + " WHERE 2*long_col2 = 4";
+ conn.createStatement().execute(dml);
+ }
+
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDeleteCoveredColImmutableIndex() throws Exception {
+ helpTestDeleteCoveredCol(false, false);
+ }
+
+ @Test
+ public void testDeleteCoveredColImmutableLocalIndex() throws Exception {
+ helpTestDeleteCoveredCol(false, true);
+ }
+
+ @Test
+ public void testDeleteCoveredColMutableIndex() throws Exception {
+ helpTestDeleteCoveredCol(true, false);
+ }
+
+ @Test
+ public void testDeleteCoveredColMutableLocalIndex() throws Exception {
+ helpTestDeleteCoveredCol(true, true);
+ }
+
+ protected void helpTestDeleteCoveredCol(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ String fullIndexTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + indexName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) )" + " INCLUDE (long_col1, long_col2)";
+ conn.createStatement().execute(ddl);
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+
+ String sql = "SELECT LONG_COL1 from " + fullDataTableName + " WHERE LONG_COL2 = 2";
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertFalse(rs.next());
+
+ String dml = "DELETE from " + fullDataTableName + " WHERE long_col2 = 2";
+ assertEquals(1, conn.createStatement().executeUpdate(dml));
+ conn.commit();
+
+ String query = "SELECT /*+ NO_INDEX */ long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) FROM "
+ + fullDataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+
+ query = "SELECT long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) FROM " + fullDataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + fullIndexTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java
index e9f0194..0ce36dd 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java
@@ -607,4 +607,71 @@ public class IndexMetadataIT extends ParallelStatsDisabledIT {
"order by table_name" );
assertFalse(rs.next());
}
+
+ @Test
+ public void testImmutableTableOnlyHasPrimaryKeyIndex() throws Exception {
+ helpTestTableOnlyHasPrimaryKeyIndex(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalTableOnlyHasPrimaryKeyIndex() throws Exception {
+ helpTestTableOnlyHasPrimaryKeyIndex(false, true);
+ }
+
+ @Test
+ public void testMutableTableOnlyHasPrimaryKeyIndex() throws Exception {
+ helpTestTableOnlyHasPrimaryKeyIndex(true, false);
+ }
+
+ @Test
+ public void testMutableLocalTableOnlyHasPrimaryKeyIndex() throws Exception {
+ helpTestTableOnlyHasPrimaryKeyIndex(true, true);
+ }
+
+ private void helpTestTableOnlyHasPrimaryKeyIndex(boolean mutable,
+ boolean localIndex) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableName + " ("
+ + "pk1 VARCHAR not null, "
+ + "pk2 VARCHAR not null, "
+ + "CONSTRAINT PK PRIMARY KEY (pk1, pk2))"
+ + (!mutable ? "IMMUTABLE_ROWS=true" : ""));
+ String query = "SELECT * FROM " + dataTableName;
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ conn.createStatement().execute(
+ "CREATE " + (localIndex ? "LOCAL" : "")
+ + " INDEX " + indexName + " ON " + dataTableName + " (pk2, pk1)");
+ query = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?)");
+ stmt.setString(1, "k11");
+ stmt.setString(2, "k21");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("k21", rs.getString(1));
+ assertEquals("k11", rs.getString(2));
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + dataTableName + " WHERE pk2='k21'";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("k11", rs.getString(1));
+ assertEquals("k21", rs.getString(2));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
}
[07/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinIT.java
new file mode 100644
index 0000000..56ec7f2
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinIT.java
@@ -0,0 +1,2316 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.Properties;
+
+import org.apache.phoenix.cache.ServerCacheClient;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class HashJoinIT extends BaseJoinIT {
+
+
+ public HashJoinIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+
+ @Test
+ public void testDefaultJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInnerJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertEquals(1, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertEquals(2, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertEquals(3, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertEquals(4, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertEquals(5, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertEquals(6, rs.getInt(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query[] = new String[3];
+ query[0] = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ query[1] = "SELECT " + tableName1 + ".\"item_id\", " + tableName1 + ".name, " + tableName2 + ".\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " LEFT JOIN " + tableName2 + " ON " + tableName1 + ".\"supplier_id\" = " + tableName2 + ".\"supplier_id\" ORDER BY \"item_id\"";
+ query[2] = "SELECT item.\"item_id\", " + tableName1 + ".name, supp.\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ for (int i = 0; i < query.length; i++) {
+ PreparedStatement statement = conn.prepareStatement(query[i]);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ rs.close();
+ statement.close();
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRightJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " supp RIGHT JOIN " + tableName2 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInnerJoinWithPreFilters() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query1 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005'";
+ String query2 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005')";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoinWithPreFilters() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005') ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithPostFilters() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String query1 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " supp RIGHT JOIN " + tableName2 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005'";
+ String query2 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName2 + " item LEFT JOIN " + tableName1 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005'";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testStarJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String[] query = new String[5];
+ query[0] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName1 + " o JOIN "
+ + tableName2 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ + tableName3 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
+ query[1] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName1 + " o, "
+ + tableName2 + " c, "
+ + tableName3 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[2] = "SELECT /*+ NO_STAR_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName1 + " o JOIN "
+ + tableName2 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ + tableName3 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
+ query[3] = "SELECT /*+ NO_STAR_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM (" + tableName1 + " o, "
+ + tableName2 + " c), "
+ + tableName3 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[4] = "SELECT \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName1 + " o, ("
+ + tableName2 + " c, "
+ + tableName3 + " i) WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ try {
+ for (int i = 0; i < query.length; i++) {
+ PreparedStatement statement = conn.prepareStatement(query[i]);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString("\"order_id\""), "000000000000001");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getString("C.name"), "C4");
+ assertEquals(rs.getString(3), "T1");
+ assertEquals(rs.getString("iName"), "T1");
+ assertEquals(rs.getInt(4), 1000);
+ assertEquals(rs.getInt("Quantity"), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "C3");
+ assertEquals(rs.getString(3), "T6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "C2");
+ assertEquals(rs.getString(3), "T2");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getString(3), "T6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "C5");
+ assertEquals(rs.getString(3), "T3");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+
+ if (i < 4) {
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query[i]);
+ assertPlansEqual(plans[11 + (i/2)], QueryUtil.getExplainPlan(rs));
+ }
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoinWithAggregation() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String query1 = "SELECT i.name, sum(quantity) FROM " + tableName1 + " o LEFT JOIN "
+ + tableName2 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
+ String query2 = "SELECT i.\"item_id\" iid, sum(quantity) q FROM " + tableName1 + " o LEFT JOIN "
+ + tableName2 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC";
+ String query3 = "SELECT i.\"item_id\" iid, sum(quantity) q FROM " + tableName2 + " i LEFT JOIN "
+ + tableName1 + " o ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getInt(2), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getInt(2), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getInt(2), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getInt(2), 6000);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query1);
+ assertPlansEqual(plans[0], QueryUtil.getExplainPlan(rs));
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query2);
+ assertPlansEqual(plans[1], QueryUtil.getExplainPlan(rs));
+
+ statement = conn.prepareStatement(query3);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000004");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000005");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "invalid001");
+ assertEquals(rs.getInt("q"), 0);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query3);
+ assertPlansEqual(plans[2], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRightJoinWithAggregation() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String query1 = "SELECT i.name, sum(quantity) FROM " + tableName1 + " o RIGHT JOIN "
+ + tableName2 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
+ String query2 = "SELECT i.\"item_id\" iid, sum(quantity) q FROM " + tableName1 + " o RIGHT JOIN "
+ + tableName2 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "INVALID-1");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getInt(2), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getInt(2), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getInt(2), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getInt(2), 6000);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query1);
+ assertPlansEqual(plans[3], QueryUtil.getExplainPlan(rs));
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000004");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000005");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "invalid001");
+ assertEquals(rs.getInt("q"), 0);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query2);
+ assertPlansEqual(plans[4], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftRightJoin() throws Exception {
+ Connection conn = getConnection();
+ String tableName1 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query1 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName1 + " o LEFT JOIN "
+ + tableName2 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + tableName3 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ String query2 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName1 + " o LEFT JOIN "
+ + "(" + tableName2 + " i RIGHT JOIN " + tableName3 + " s ON i.\"supplier_id\" = s.\"supplier_id\")"
+ + " ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testMultiLeftJoin() throws Exception {
+ Connection conn = getConnection();
+ String[] queries = {
+ "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o LEFT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\"",
+ "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o LEFT JOIN "
+ + "(" + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i LEFT JOIN " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\") "
+ + "ON o.\"item_id\" = i.\"item_id\""};
+ try {
+ for (String query : queries) {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testMultiRightJoin() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o RIGHT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ // Basically a copy of testMultiRightJoin, but with a very small result scan chunk size
+ // to test that repeated row keys within a single chunk are handled properly
+ @Test
+ public void testMultiRightJoin_SmallChunkSize() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(QueryServices.SCAN_RESULT_CHUNK_SIZE, "1");
+ props.put(ServerCacheClient.HASH_JOIN_SERVER_CACHE_RESEND_PER_SERVER, "true");
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o RIGHT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithWildcard() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT * FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " LEFT JOIN " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " supp ON " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T1");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 100);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T1");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
+ assertEquals(rs.getString("supp.name"), "S1");
+ assertEquals(rs.getString("supp.phone"), "888-888-1111");
+ assertEquals(rs.getString("supp.address"), "101 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T2");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 200);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 8);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T2");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
+ assertEquals(rs.getString("supp.name"), "S1");
+ assertEquals(rs.getString("supp.phone"), "888-888-1111");
+ assertEquals(rs.getString("supp.address"), "101 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000003");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T3");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 300);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 12);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T3");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
+ assertEquals(rs.getString("supp.name"), "S2");
+ assertEquals(rs.getString("supp.phone"), "888-888-2222");
+ assertEquals(rs.getString("supp.address"), "202 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000004");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T4");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 400);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 6);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T4");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
+ assertEquals(rs.getString("supp.name"), "S2");
+ assertEquals(rs.getString("supp.phone"), "888-888-2222");
+ assertEquals(rs.getString("supp.address"), "202 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000005");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T5");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 500);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000005");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T5");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000005");
+ assertEquals(rs.getString("supp.name"), "S5");
+ assertEquals(rs.getString("supp.phone"), "888-888-5555");
+ assertEquals(rs.getString("supp.address"), "505 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10005");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000006");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T6");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 600);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000006");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T6");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000006");
+ assertEquals(rs.getString("supp.name"), "S6");
+ assertEquals(rs.getString("supp.phone"), "888-888-6666");
+ assertEquals(rs.getString("supp.address"), "606 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10006");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "invalid001");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "INVALID-1");
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 0);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 0);
+ assertEquals(rs.getInt(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 0);
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000000");
+ assertEquals(rs.getString(getDisplayTableName(conn,JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Invalid item for join test");
+ assertNull(rs.getString("SUPP.supplier_id"));
+ assertNull(rs.getString("supp.name"));
+ assertNull(rs.getString("supp.phone"));
+ assertNull(rs.getString("supp.address"));
+ assertNull(rs.getString("supp.loc_id"));
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[5], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithTableWildcard() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT s.*, "+ getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".*, \"order_id\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o RIGHT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ ResultSetMetaData md = rs.getMetaData();
+ assertEquals(md.getColumnCount(), 13);
+
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "S5");
+ assertEquals(rs.getString(3), "888-888-5555");
+ assertEquals(rs.getString(4), "505 YYY Street");
+ assertEquals(rs.getString(5), "10005");
+ assertEquals(rs.getString(6), "0000000005");
+ assertEquals(rs.getString(7), "T5");
+ assertEquals(rs.getInt(8), 500);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000005");
+ assertEquals(rs.getString(12), "Item T5");
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "S4");
+ assertEquals(rs.getString(3), "888-888-4444");
+ assertEquals(rs.getString(4), "404 YYY Street");
+ assertNull(rs.getString(5));
+ assertNull(rs.getString(6));
+ assertNull(rs.getString(7));
+ assertEquals(rs.getInt(8), 0);
+ assertEquals(rs.getInt(9), 0);
+ assertEquals(rs.getInt(10), 0);
+ assertNull(rs.getString(11));
+ assertNull(rs.getString(12));
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S3");
+ assertEquals(rs.getString(3), "888-888-3333");
+ assertEquals(rs.getString(4), "303 YYY Street");
+ assertNull(rs.getString(5));
+ assertNull(rs.getString(6));
+ assertNull(rs.getString(7));
+ assertEquals(rs.getInt(8), 0);
+ assertEquals(rs.getInt(9), 0);
+ assertEquals(rs.getInt(10), 0);
+ assertNull(rs.getString(11));
+ assertNull(rs.getString(12));
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S2");
+ assertEquals(rs.getString(3), "888-888-2222");
+ assertEquals(rs.getString(4), "202 YYY Street");
+ assertEquals(rs.getString(5), "10002");
+ assertEquals(rs.getString(6), "0000000004");
+ assertEquals(rs.getString(7), "T4");
+ assertEquals(rs.getInt(8), 400);
+ assertEquals(rs.getInt(9), 6);
+ assertEquals(rs.getInt(10), 10);
+ assertEquals(rs.getString(11), "0000000002");
+ assertEquals(rs.getString(12), "Item T4");
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertEquals(rs.getString(3), "888-888-1111");
+ assertEquals(rs.getString(4), "101 YYY Street");
+ assertEquals(rs.getString(5), "10001");
+ assertEquals(rs.getString(6), "0000000001");
+ assertEquals(rs.getString(7), "T1");
+ assertEquals(rs.getInt(8), 100);
+ assertEquals(rs.getInt(9), 5);
+ assertEquals(rs.getInt(10), 10);
+ assertEquals(rs.getString(11), "0000000001");
+ assertEquals(rs.getString(12), "Item T1");
+ assertEquals(rs.getString(13), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+ assertEquals(rs.getString(3), "888-888-6666");
+ assertEquals(rs.getString(4), "606 YYY Street");
+ assertEquals(rs.getString(5), "10006");
+ assertEquals(rs.getString(6), "0000000006");
+ assertEquals(rs.getString(7), "T6");
+ assertEquals(rs.getInt(8), 600);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000006");
+ assertEquals(rs.getString(12), "Item T6");
+ assertEquals(rs.getString(13), "000000000000002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertEquals(rs.getString(3), "888-888-1111");
+ assertEquals(rs.getString(4), "101 YYY Street");
+ assertEquals(rs.getString(5), "10001");
+ assertEquals(rs.getString(6), "0000000002");
+ assertEquals(rs.getString(7), "T2");
+ assertEquals(rs.getInt(8), 200);
+ assertEquals(rs.getInt(9), 5);
+ assertEquals(rs.getInt(10), 8);
+ assertEquals(rs.getString(11), "0000000001");
+ assertEquals(rs.getString(12), "Item T2");
+ assertEquals(rs.getString(13), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+ assertEquals(rs.getString(3), "888-888-6666");
+ assertEquals(rs.getString(4), "606 YYY Street");
+ assertEquals(rs.getString(5), "10006");
+ assertEquals(rs.getString(6), "0000000006");
+ assertEquals(rs.getString(7), "T6");
+ assertEquals(rs.getInt(8), 600);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000006");
+ assertEquals(rs.getString(12), "Item T6");
+ assertEquals(rs.getString(13), "000000000000004");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S2");
+ assertEquals(rs.getString(3), "888-888-2222");
+ assertEquals(rs.getString(4), "202 YYY Street");
+ assertEquals(rs.getString(5), "10002");
+ assertEquals(rs.getString(6), "0000000003");
+ assertEquals(rs.getString(7), "T3");
+ assertEquals(rs.getInt(8), 300);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 12);
+ assertEquals(rs.getString(11), "0000000002");
+ assertEquals(rs.getString(12), "Item T3");
+ assertEquals(rs.getString(13), "000000000000005");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinMultiJoinKeys() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT c.name, s.name FROM " + getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME) + " c LEFT JOIN " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON \"customer_id\" = \"supplier_id\" AND c.loc_id = s.loc_id AND substr(s.name, 2, 1) = substr(c.name, 2, 1)";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C1");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C2");
+ assertNull(rs.getString(2));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C3");
+ assertEquals(rs.getString(2), "S3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C4");
+ assertNull(rs.getString(2));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C5");
+ assertEquals(rs.getString(2), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C6");
+ assertNull(rs.getString(2));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithDifferentNumericJoinKeyTypes() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT \"order_id\", i.name, i.price, discount2, quantity FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o INNER JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" AND o.price = (i.price * (100 - discount2)) / 100.0 WHERE quantity < 5000";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getInt(3), 600);
+ assertEquals(rs.getInt(4), 15);
+ assertEquals(rs.getInt(5), 4000);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithDifferentDateJoinKeyTypes() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT \"order_id\", c.name, o.\"DATE\" FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o INNER JOIN "
+ + getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME) + " c ON o.\"customer_id\" = c.\"customer_id\" AND o.\"DATE\" = c.\"DATE\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-22 14:22:56").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "C3");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "C2");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 16:45:07").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "C5");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-27 09:37:50").getTime()));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithIncomparableJoinKeyTypes() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT \"order_id\", i.name, i.price, discount2, quantity FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o INNER JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" AND o.price / 100 = substr(i.name, 2, 1)";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail("Should have got SQLException.");
+ } catch (SQLException e) {
+ assertEquals(e.getErrorCode(), SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinPlanWithIndex() throws Exception {
+ Connection conn = getConnection();
+ String query1 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " item LEFT JOIN " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " supp ON substr(item.name, 2, 1) = substr(supp.name, 2, 1) AND (supp.name BETWEEN 'S1' AND 'S5') WHERE item.name BETWEEN 'T1' AND 'T5'";
+ String query2 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " item INNER JOIN " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE (item.name = 'T1' OR item.name = 'T5') AND (supp.name = 'S1' OR supp.name = 'S5')";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "S3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000004");
+ assertEquals(rs.getString(4), "S4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query1);
+ assertPlansEqual(plans[6], QueryUtil.getExplainPlan(rs));
+
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query2);
+ assertPlansEqual(plans[7], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithSkipMergeOptimization() throws Exception {
+ Connection conn = getConnection();
+ String query = "SELECT s.name FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i JOIN "
+ + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o ON o.\"item_id\" = i.\"item_id\" AND quantity < 5000 JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "S6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "S6");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[8], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelfJoin() throws Exception {
+ Connection conn = getConnection();
+ String query1 = "SELECT i2.\"item_id\", i1.name FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i1 JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i2 ON i1.\"item_id\" = i2.\"item_id\" ORDER BY i1.\"item_id\"";
+ String query2 = "SELECT i1.name, i2.name FROM " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i1 JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i2 ON i1.\"item_id\" = i2.\"supplier_id\" ORDER BY i1.name, i2.name";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query1);
+ assertPlansEqual(plans[9], QueryUtil.getExplainPlan(rs));
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getString(2), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query2);
+ assertPlansEqual(plans[10], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpsertWithJoin() throws Exception {
+ String tempTable = generateUniqueName();
+ Connection conn = getConnection();
+ conn.setAutoCommit(true);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTable
+ + " (\"order_id\" varchar not null, "
+ + " item_name varchar not null, "
+ + " supplier_name varchar, "
+ + " quantity integer, "
+ + " \"DATE\" timestamp "
+ + " CONSTRAINT pk PRIMARY KEY (\"order_id\", item_name))");
+ conn.createStatement().execute("UPSERT INTO " + tempTable
+ + "(\"order_id\", item_name, supplier_name, quantity, \"DATE\") "
+ + "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM "
+ + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o LEFT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
+ + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s ON i.\"supplier_id\" = s.\"supplier_id\"");
+ conn.createStatement().execute("UPSERT INTO " + tempTable
+ + "(\"order_id\", item_name, quantity) "
+ + "SELECT 'ORDER_SUM', i.name, sum(quantity) FROM "
+ + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o LEFT JOIN "
+ + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON o.\"item_id\" = i.\"item_id\" "
+ + "GROUP BY i.name ORDER BY i.name");
+
+ String query = "SELECT * FROM " + tempTable;
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "ORDER_SUM");
+ assertEquals(rs.getString(2), "T1");
+ assertNull(rs.getString(3));
+ assertEquals(rs.getInt(4), 1000);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "ORDER_SUM");
+ assertEquals(rs.getString(2), "T2");
+ assertNull(rs.getString(3));
+ assertEquals(rs.getInt(4), 3000);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "ORDER_SUM");
+ assertEquals(rs.getString(2), "T3");
+ assertNull(rs.getString(3));
+ assertEquals(rs.getInt(4), 5000);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "ORDER_SUM");
+ assertEquals(rs.getString(2), "T6");
+ assertNull(rs.getString(3));
+ assertEquals(rs.getInt(4), 6000);
+ assertNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+
+ //Bug: PHOENIX-1182
+ String sourceTable = generateUniqueName();
+ String joinTable = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + sourceTable
+ + " (TID CHAR(3) NOT NULL, "
+ + " A UNSIGNED_INT NOT NULL, "
+ + " B UNSIGNED_INT NOT NULL "
+ + " CONSTRAINT pk PRIMARY KEY (TID, A, B))");
+ conn.createStatement().execute("CREATE TABLE " + joinTable
+ + " (TID CHAR(3) NOT NULL, "
+ + " A UNSIGNED_INT NOT NULL, "
+ + " B UNSIGNED_INT NOT NULL, "
+ + " COUNT UNSIGNED_INT "
+ + " CONSTRAINT pk PRIMARY KEY (TID, A, B))");
+
+ PreparedStatement upsertStmt = conn.prepareStatement(
+ "upsert into " + sourceTable + "(TID, A, B) " + "values (?, ?, ?)");
+ upsertStmt.setString(1, "1");
+ upsertStmt.setInt(2, 1);
+ upsertStmt.setInt(3, 1);
+ upsertStmt.execute();
+ upsertStmt.setString(1, "1");
+ upsertStmt.setInt(2, 1);
+ upsertStmt.setInt(3, 2);
+ upsertStmt.execute();
+ upsertStmt.setString(1, "1");
+ upsertStmt.setInt(2, 1);
+ upsertStmt.setInt(3, 3);
+ upsertStmt.execute();
+ upsertStmt.setString(1, "1");
+ upsertStmt.setInt(2, 2);
+ upsertStmt.setInt(3, 1);
+ upsertStmt.execute();
+ upsertStmt.setString(1, "1");
+ upsertStmt.setInt(2, 2);
+ upsertStmt.setInt(3, 2);
+ upsertStmt.execute();
+ conn.commit();
+
+ upsertStmt = conn.prepareStatement(
+ "upsert into " + joinTable + "(TID, A, B, COUNT) "
+ + "SELECT t1.TID, t1.A, t2.A, COUNT(*) "
+ + "FROM " + sourceTable + " t1 "
+ + "INNER JOIN " + sourceTable + " t2 ON t1.B = t2.B "
+ + "WHERE t1.A != t2.A AND t1.TID = '1' AND t2.TID = '1' "
+ + "GROUP BY t1.TID, t1.A, t2.A");
+ upsertStmt.execute();
+ conn.commit();
+
+ rs = statement.executeQuery("SELECT * FROM " + joinTable);
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "1");
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 2);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getString(1), "1");
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 1);
+ assertEquals(rs.getInt(4), 2);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSubJoin() throws Exception {
+ Connection conn = getConnection();
+ String query1 = "SELECT i.name, count(c.name), min(s.name), max(quantity) FROM " + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o LEFT JOIN "
+ + "(" + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s RIGHT JOIN " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON i.\"supplier_id\" = s.\"supplier_id\")"
+ + " ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
+ + getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME) + " c ON c.\"customer_id\" = o.\"customer_id\" GROUP BY i.name ORDER BY i.name";
+ String query2 = "SELECT * FROM " + getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME) + " c INNER JOIN "
+ + "(" + getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME) + " o INNER JOIN "
+ + "(" + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s RIGHT JOIN " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i ON i.\"supplier_id\" = s.\"supplier_id\")"
+ + " ON o.\"item_id\" = i.\"item_id\") ON c.\"customer_id\" = o.\"customer_id\""
+ + " WHERE c.\"customer_id\" <= '0000000005' AND \"order_id\" != '000000000000003' AND i.name != 'T3' ORDER BY c.\"customer_id\", i.name";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getString("C.customer_id"), "0000000003");
+ assertEquals(rs.getString("c.name"), "C3");
+ assertEquals(rs.getString("c.phone"), "999-999-3333");
+ assertEquals(rs.getString("c.address"), "303 XXX Street");
+ assertNull(rs.getString("c.loc_id"));
+ assertEquals(rs.getDate("c.date"), new Date(format.parse("2013-11-25 10:06:29").getTime()));
+ assertEquals(rs.getString("O.order_id"), "000000000000002");
+ assertEquals(rs.getString("O.customer_id"), "0000000003");
+ assertEquals(rs.getString("O.item_id"), "0000000006");
+ assertEquals(rs.getInt("o.price"), 552);
+ assertEquals(rs.getInt("o.quantity"), 2000);
+ assertEquals(rs.getTimestamp("o.date"), new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
+ assertEquals(rs.getString("I.item_id"), "0000000006");
+ as
<TRUNCATED>
[17/25] phoenix git commit: PHOENIX-4244 Breakup ArrayIT into several
integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/527f786a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array3IT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array3IT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array3IT.java
new file mode 100644
index 0000000..73c7e63
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array3IT.java
@@ -0,0 +1,770 @@
+/*
+ * 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.end2end;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.phoenix.util.PropertiesUtil;
+import org.junit.Test;
+
+public class Array3IT extends ArrayIT {
+
+ @Test
+ public void testArrayConstructorWithMultipleRows5() throws Exception {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_APPEND(ARRAY[a,b], 'oo') from " + table);
+ assertTrue(rs.next());
+ Array arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc", "oo"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("VARCHAR", new Object[]{"abc", "dfg", "oo"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc", "oo"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ }
+
+ @Test
+ public void testPKWithDescArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE " + table + " ( a VARCHAR ARRAY PRIMARY KEY DESC)\n");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?)");
+ Array a1 = conn.createArrayOf("VARCHAR", new String[] { "a", "ba" });
+ stmt.setArray(1, a1);
+ stmt.execute();
+ Array a2 = conn.createArrayOf("VARCHAR", new String[] { "a", "c" });
+ stmt.setArray(1, a2);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT a FROM " + table + " ORDER BY a DESC");
+ assertTrue(rs.next());
+ assertEquals(a2, rs.getArray(1));
+ assertTrue(rs.next());
+ assertEquals(a1, rs.getArray(1));
+ assertFalse(rs.next());
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?)");
+ Array a3 = conn.createArrayOf("VARCHAR", new String[] { "a", "b" });
+ stmt.setArray(1, a3);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT a FROM " + table + " ORDER BY a DESC");
+ assertTrue(rs.next());
+ assertEquals(a2, rs.getArray(1));
+ assertTrue(rs.next());
+ assertEquals(a1, rs.getArray(1));
+ assertTrue(rs.next());
+ assertEquals(a3, rs.getArray(1));
+ assertFalse(rs.next());
+ conn.close();
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc1()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k >= array['a', 'b']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc2()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k >= array['a', 'c']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc3()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k > array['a', 'b']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc4()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k <= array['a', 'c']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc5()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k <= array['a', 'b']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc6()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k varchar array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k < array['a', 'c']");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc7()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k integer array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array[1, 2])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k < array[1, 4]");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testComparisonOperatorsForDesc8()throws Exception{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "create table " + table + " (k integer array primary key desc)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array[1, 2])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("select * from " + table + " where k <= array[1, 2]");
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ }
+
+ @Test
+ public void testServerArrayElementProjection1() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 VARCHAR ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY['a', 'b'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], arr2[1] FROM " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals("a", rs.getString(3));
+ }
+
+ @Test
+ public void testServerArrayElementProjection2() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 VARCHAR ARRAY, arr3 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY['a', 'b'], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], arr2[1], arr3[1] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals("a", rs.getString(3));
+ assertEquals(2, rs.getInt(4));
+ }
+
+ @Test
+ public void testServerArrayElementProjection3() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 VARCHAR ARRAY, arr3 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY['a', 'b'], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], arr2[1], arr3, arr3[1] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals("a", rs.getString(3));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{2, 3}), rs.getArray(4));
+ assertEquals(2, rs.getInt(5));
+ }
+
+ @Test
+ public void testServerArrayElementProjection4() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 VARCHAR ARRAY, arr3 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY['a', 'b'], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], arr2[1], ARRAY_APPEND(arr3, 4), arr3[1] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals("a", rs.getString(3));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{2, 3, 4}), rs.getArray(4));
+ assertEquals(2, rs.getInt(5));
+ }
+
+ @Test
+ public void testServerArrayElementProjection5() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr3 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], ARRAY_APPEND(arr1, arr3[1]) from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 2}), rs.getArray(3));
+ }
+
+ @Test
+ public void testServerArrayElementProjection6() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], ARRAY_APPEND(arr1, arr2[1]), p from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 2}), rs.getArray(3));
+ assertEquals(1, rs.getInt(4));
+ }
+
+ @Test
+ public void testServerArrayElementProjection7() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], ARRAY_APPEND(ARRAY_APPEND(arr1, arr2[2]), arr2[1]), p from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 3, 2}), rs.getArray(3));
+ assertEquals(1, rs.getInt(4));
+ }
+
+ @Test
+ public void testServerArrayElementProjection8() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], ARRAY_ELEM(ARRAY_APPEND(arr1, arr2[1]), 1), p, arr2[2] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(1, rs.getInt(3));
+ assertEquals(1, rs.getInt(4));
+ assertEquals(3, rs.getInt(5));
+ }
+
+ @Test
+ public void testServerArrayElementProjection9() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER ARRAY PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (ARRAY[5, 6], ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1, arr1[1], ARRAY_ELEM(ARRAY_APPEND(arr1, arr2[1]), 1), p, arr2[2] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2}), rs.getArray(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(1, rs.getInt(3));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{5, 6}), rs.getArray(4));
+ assertEquals(3, rs.getInt(5));
+ }
+
+ @Test
+ public void testServerArrayElementProjection10() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT arr1[1] + 5, arr2[1] FROM " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(6, rs.getInt(1));
+ assertEquals(2, rs.getInt(2));
+ }
+
+ @Test
+ public void testServerArrayElementProjection11() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (2, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (3, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (4, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT CASE WHEN p = 1 THEN arr1[1] WHEN p = 2 THEN arr1[2] WHEN p = 3 THEN arr2[1] ELSE arr2[2] END FROM " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testServerArrayElementProjection12() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (2, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (3, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (4, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT CASE WHEN p = 1 THEN arr1[1] WHEN p = 2 THEN arr1[2] WHEN p = 3 THEN arr2[1] ELSE arr2[2] END, ARRAY_APPEND(arr1, arr1[1]) FROM " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 1}), rs.getArray(2));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 1}), rs.getArray(2));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 1}), rs.getArray(2));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{1, 2, 1}), rs.getArray(2));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testServerArrayElementProjection13() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (1, ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (2, ARRAY[3, 2], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (3, ARRAY[3, 5], ARRAY[2, 3])");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (4, ARRAY[3, 5], ARRAY[6, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT CASE WHEN arr1[1] = 1 THEN 1 WHEN arr1[2] = 2 THEN 2 WHEN arr2[1] = 2 THEN 2 ELSE arr2[2] END FROM " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testServerArrayElementProjection14() throws SQLException {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (p INTEGER ARRAY PRIMARY KEY, arr1 INTEGER ARRAY, arr2 INTEGER ARRAY)";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (ARRAY[5, 6], ARRAY[1, 2], ARRAY[2, 3])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT ARRAY_ELEM(ARRAY_PREPEND(arr2[1], ARRAY_CAT(arr1, ARRAY[arr2[2],3])), 1), arr1[1], ARRAY_ELEM(ARRAY_APPEND(arr1, arr2[1]), 1), p, arr2[2] from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(1, rs.getInt(2));
+ assertEquals(1, rs.getInt(3));
+ assertEquals(conn.createArrayOf("INTEGER", new Integer[]{5, 6}), rs.getArray(4));
+ assertEquals(3, rs.getInt(5));
+ }
+
+ @Test
+ public void testCharPrimaryKey() throws SQLException{
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (testCharArray CHAR(3)[], CONSTRAINT test_pk PRIMARY KEY(testCharArray)) DEFAULT_COLUMN_FAMILY='T'";
+ conn.createStatement().execute(ddl);
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES (ARRAY['aaa', 'bbb', 'ccc'])");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ stmt = conn.prepareStatement("SELECT testCharArray from " + table);
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(conn.createArrayOf("CHAR", new String[]{"aaa", "bbb", "ccc"}), rs.getArray(1));
+ }
+
+ @Test
+ public void testArrayIndexFunctionForImmutableTable() throws Exception {
+ String tableName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ String ddl = "CREATE IMMUTABLE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY, ZIP VARCHAR ARRAY[10])";
+ conn.createStatement().execute(ddl);
+ }
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ conn.createStatement().executeUpdate("UPSERT INTO " + tableName + " (region_name,zip) VALUES('SF Bay Area',ARRAY['94115','94030','94125'])");
+ conn.commit();
+ }
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ try (Connection conn = DriverManager.getConnection(getUrl(), props)) {
+ String sql = "SELECT ZIP[2] FROM " + tableName;
+ try (ResultSet rs = conn.createStatement().executeQuery(sql)) {
+ assertTrue(rs.next());
+ assertEquals("94030", rs.getString(1));
+ }
+ }
+ }
+}
[23/25] phoenix git commit: PHOENIX-4251 Breakup ProductMetricsIT
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
PHOENIX-4251 Breakup ProductMetricsIT into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/dd3b7b6c
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/dd3b7b6c
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/dd3b7b6c
Branch: refs/heads/master
Commit: dd3b7b6c04acfc53a1d5cdd5e866a59ae71557c3
Parents: eafb58b
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 18:23:19 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 18:23:44 2017 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/DateTimeIT.java | 277 ++++++++++++++++++-
.../phoenix/end2end/ProductMetricsIT.java | 170 +-----------
2 files changed, 278 insertions(+), 169 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/dd3b7b6c/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
index fb43538..e9a98e3 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DateTimeIT.java
@@ -32,6 +32,7 @@ import static org.apache.phoenix.util.TestUtil.ROW6;
import static org.apache.phoenix.util.TestUtil.ROW7;
import static org.apache.phoenix.util.TestUtil.ROW8;
import static org.apache.phoenix.util.TestUtil.ROW9;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -39,18 +40,38 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
-import java.sql.*;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
import java.text.Format;
import java.util.Calendar;
import java.util.GregorianCalendar;
+import java.util.Properties;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.types.PDate;
+import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.PropertiesUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class DateTimeIT extends ParallelStatsDisabledIT {
+ private static final String PRODUCT_METRICS_NAME = "PRODUCT_METRICS";
+ private static final Date SPLIT1 = toDate("1970-01-01 01:30:00");
+ private static final Date SPLIT2 = toDate("1970-01-01 02:00:00");
+ private static final String R1 = "R1";
+ private static final String R2 = "R2";
protected Connection conn;
protected Date date;
@@ -58,6 +79,107 @@ public class DateTimeIT extends ParallelStatsDisabledIT {
protected final static String ROW10 = "00D123122312312";
protected String tableName;
+ private static void initDateTableValues(String tablename, Connection conn, String tenantId, Date startDate) throws Exception {
+ double dateIncrement = 2.0;
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " +tablename+
+ "(" +
+ " ORGANIZATION_ID, " +
+ " \"DATE\", " +
+ " FEATURE, " +
+ " UNIQUE_USERS, " +
+ " TRANSACTIONS, " +
+ " CPU_UTILIZATION, " +
+ " DB_UTILIZATION, " +
+ " REGION, " +
+ " IO_TIME)" +
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "A");
+ stmt.setInt(4, 10);
+ stmt.setLong(5, 100L);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(0.5));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(0.2));
+ stmt.setString(8, R2);
+ stmt.setNull(9, Types.BIGINT);
+ stmt.execute();
+
+ startDate = new Date(startDate.getTime() + (long)(QueryConstants.MILLIS_IN_DAY * dateIncrement));
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "B");
+ stmt.setInt(4, 20);
+ stmt.setLong(5, 200);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(1.0));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(0.4));
+ stmt.setString(8, null);
+ stmt.setLong(9, 2000);
+ stmt.execute();
+
+ startDate = new Date(startDate.getTime() + (long)(QueryConstants.MILLIS_IN_DAY * dateIncrement));
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "C");
+ stmt.setInt(4, 30);
+ stmt.setLong(5, 300);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(2.5));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(0.6));
+ stmt.setString(8, R1);
+ stmt.setNull(9, Types.BIGINT);
+ stmt.execute();
+
+ startDate = new Date(startDate.getTime() + (long)(QueryConstants.MILLIS_IN_DAY * dateIncrement));
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "D");
+ stmt.setInt(4, 40);
+ stmt.setLong(5, 400);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(3.0));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(0.8));
+ stmt.setString(8, R1);
+ stmt.setLong(9, 4000);
+ stmt.execute();
+
+ startDate = new Date(startDate.getTime() + (long)(QueryConstants.MILLIS_IN_DAY * dateIncrement));
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "E");
+ stmt.setInt(4, 50);
+ stmt.setLong(5, 500);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(3.5));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(1.2));
+ stmt.setString(8, R2);
+ stmt.setLong(9, 5000);
+ stmt.execute();
+
+ startDate = new Date(startDate.getTime() + (long)(QueryConstants.MILLIS_IN_DAY * dateIncrement));
+ stmt.setString(1, tenantId);
+ stmt.setDate(2, startDate);
+ stmt.setString(3, "F");
+ stmt.setInt(4, 60);
+ stmt.setLong(5, 600);
+ stmt.setBigDecimal(6, BigDecimal.valueOf(4.0));
+ stmt.setBigDecimal(7, BigDecimal.valueOf(1.4));
+ stmt.setString(8, null);
+ stmt.setNull(9, Types.BIGINT);
+ stmt.execute();
+ }
+
+ private static void initDateTableValues(String tablename, String tenantId, byte[][] splits, Date startDate) throws Exception {
+ ensureTableCreated(getUrl(), tablename, PRODUCT_METRICS_NAME, splits, null, null);
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ initDateTableValues(tablename, conn, tenantId, startDate);
+ conn.commit();
+ } finally {
+ conn.close();
+ }
+ }
+
+
public DateTimeIT() throws Exception {
super();
date = new Date(System.currentTimeMillis());
@@ -1537,4 +1659,157 @@ public class DateTimeIT extends ParallelStatsDisabledIT {
assertEquals(true, rs.getBoolean(1));
assertFalse(rs.next());
}
+
+ private static byte[][] getSplits(String tenantId) {
+ return new byte[][] {
+ ByteUtil.concat(Bytes.toBytes(tenantId), PDate.INSTANCE.toBytes(SPLIT1)),
+ ByteUtil.concat(Bytes.toBytes(tenantId), PDate.INSTANCE.toBytes(SPLIT2)),
+ };
+ }
+
+ private static Date toDate(String dateString) {
+ return DateUtil.parseDate(dateString);
+ }
+
+ @Test
+ public void testDateSubtractionCompareNumber() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and ? - \"DATE\" > 3";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ Date endDate = new Date(startDate.getTime() + 6 * QueryConstants.MILLIS_IN_DAY);
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setDate(2, endDate);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("A", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("B", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDateSubtractionLongToDecimalCompareNumber() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and ? - \"DATE\" - 1.5 > 3";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ Date endDate = new Date(startDate.getTime() + 9 * QueryConstants.MILLIS_IN_DAY);
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setDate(2, endDate);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("A", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("B", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("C", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDateSubtractionCompareDate() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and date - 1 >= ?";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ Date endDate = new Date(startDate.getTime() + 9 * QueryConstants.MILLIS_IN_DAY);
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setDate(2, endDate);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("F", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDateAddCompareDate() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and date + 1 >= ?";
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ Date endDate = new Date(startDate.getTime() + 8 * QueryConstants.MILLIS_IN_DAY);
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setDate(2, endDate);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("E", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("F", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testCurrentDate() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and \"DATE\" - current_date() > 8";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("F", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testCurrentTime() throws Exception {
+ String tablename=generateUniqueName();
+ String tenantId = getOrganizationId();
+ String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and \"DATE\" - current_time() > 8";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ Date startDate = new Date(System.currentTimeMillis());
+ initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("F", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/dd3b7b6c/phoenix-core/src/it/java/org/apache/phoenix/end2end/ProductMetricsIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ProductMetricsIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ProductMetricsIT.java
index 969b585..858a0fd 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ProductMetricsIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ProductMetricsIT.java
@@ -36,20 +36,15 @@ import java.util.Collections;
import java.util.List;
import java.util.Properties;
-import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.jdbc.PhoenixConnection;
-import org.apache.phoenix.query.ConnectionQueryServices;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.types.PDate;
import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.DateUtil;
-import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TestUtil;
-import org.junit.After;
import org.junit.Test;
import com.google.common.collect.Lists;
@@ -113,7 +108,7 @@ public class ProductMetricsIT extends ParallelStatsDisabledIT {
}
}
- protected static void initTableValues(String tablename, Connection conn, String tenantId) throws Exception {
+ private static void initTableValues(String tablename, Connection conn, String tenantId) throws Exception {
PreparedStatement stmt = conn.prepareStatement(
"upsert into " + tablename +
" (" +
@@ -298,9 +293,7 @@ public class ProductMetricsIT extends ParallelStatsDisabledIT {
stmt.execute();
}
-
-
-
+
@Test
public void testDateRangeAggregation() throws Exception {
String tablename=generateUniqueName();
@@ -1715,147 +1708,6 @@ public class ProductMetricsIT extends ParallelStatsDisabledIT {
}
@Test
- public void testDateSubtractionCompareNumber() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and ? - \"DATE\" > 3";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- Date endDate = new Date(startDate.getTime() + 6 * QueryConstants.MILLIS_IN_DAY);
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setDate(2, endDate);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("A", rs.getString(1));
- assertTrue(rs.next());
- assertEquals("B", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testDateSubtractionLongToDecimalCompareNumber() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and ? - \"DATE\" - 1.5 > 3";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- Date endDate = new Date(startDate.getTime() + 9 * QueryConstants.MILLIS_IN_DAY);
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setDate(2, endDate);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("A", rs.getString(1));
- assertTrue(rs.next());
- assertEquals("B", rs.getString(1));
- assertTrue(rs.next());
- assertEquals("C", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testDateSubtractionCompareDate() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and date - 1 >= ?";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- Date endDate = new Date(startDate.getTime() + 9 * QueryConstants.MILLIS_IN_DAY);
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setDate(2, endDate);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("F", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testDateAddCompareDate() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and date + 1 >= ?";
- Connection conn = DriverManager.getConnection(url);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- Date endDate = new Date(startDate.getTime() + 8 * QueryConstants.MILLIS_IN_DAY);
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setDate(2, endDate);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("E", rs.getString(1));
- assertTrue(rs.next());
- assertEquals("F", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testCurrentDate() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and \"DATE\" - current_date() > 8";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("F", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testCurrentTime() throws Exception {
- String tablename=generateUniqueName();
- String tenantId = getOrganizationId();
- String query = "SELECT feature FROM "+tablename+" WHERE organization_id = ? and \"DATE\" - current_time() > 8";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- Date startDate = new Date(System.currentTimeMillis());
- initDateTableValues(tablename, tenantId, getSplits(tenantId), startDate);
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("F", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
public void testTruncateNotTraversableToFormScanKey() throws Exception {
String tablename=generateUniqueName();
String tenantId = getOrganizationId();
@@ -1879,27 +1731,9 @@ public class ProductMetricsIT extends ParallelStatsDisabledIT {
}
}
- private static void destroyTable() throws Exception {
- String tablename=generateUniqueName();
- // Physically delete HBase table so that splits occur as expected for each test
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- ConnectionQueryServices services = DriverManager.getConnection(getUrl(), props).unwrap(PhoenixConnection.class).getQueryServices();
- HBaseAdmin admin = services.getAdmin();
- try {
- try {
- admin.disableTable(tablename);
- admin.deleteTable(tablename);
- } catch (TableNotFoundException e) {
- }
- } finally {
- admin.close();
- }
- }
-
@Test
public void testSaltedOrderBy() throws Exception {
String tablename=generateUniqueName();
- destroyTable();
String ddl = "create table " + tablename +
" (organization_id char(15) not null," +
" \"DATE\" date not null," +
[18/25] phoenix git commit: PHOENIX-4244 Breakup ArrayIT into several
integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
PHOENIX-4244 Breakup ArrayIT into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/527f786a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/527f786a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/527f786a
Branch: refs/heads/master
Commit: 527f786ac4b4883677fa77d0e31c71ea7d518872
Parents: 06f58d5
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 13:18:15 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 17:51:57 2017 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/Array1IT.java | 1004 +++++++
.../org/apache/phoenix/end2end/Array2IT.java | 815 ++++++
.../org/apache/phoenix/end2end/Array3IT.java | 770 ++++++
.../org/apache/phoenix/end2end/ArrayIT.java | 2543 +-----------------
4 files changed, 2617 insertions(+), 2515 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/527f786a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array1IT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array1IT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array1IT.java
new file mode 100644
index 0000000..20f4422
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array1IT.java
@@ -0,0 +1,1004 @@
+/*
+ * 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.end2end;
+
+import static org.apache.phoenix.util.TestUtil.B_VALUE;
+import static org.apache.phoenix.util.TestUtil.ROW1;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.phoenix.query.BaseTest;
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+import com.google.common.primitives.Floats;
+
+public class Array1IT extends ArrayIT {
+ private void assertArrayGetString(ResultSet rs, int arrayIndex, Array expectedArray, String expectedString)
+ throws SQLException {
+ assertEquals(expectedArray, rs.getArray(arrayIndex));
+ assertEquals("[" + expectedString + "]", rs.getString(arrayIndex));
+ }
+
+ private static String createTableWithAllArrayTypes(String url, byte[][] bs, Object object) throws SQLException {
+ String tableName = generateUniqueName();
+ String ddlStmt = "create table "
+ + tableName
+ + " (organization_id char(15) not null, \n"
+ + " entity_id char(15) not null,\n"
+ + " boolean_array boolean array,\n"
+ + " byte_array tinyint array,\n"
+ + " double_array double array[],\n"
+ + " float_array float array,\n"
+ + " int_array integer array,\n"
+ + " long_array bigint[5],\n"
+ + " short_array smallint array,\n"
+ + " string_array varchar(100) array[3],\n"
+ + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
+ + ")";
+ BaseTest.createTestTable(url, ddlStmt, bs, null);
+ return tableName;
+ }
+
+ private static String createSimpleTableWithArray(String url, byte[][] bs, Object object) throws SQLException {
+ String tableName = generateUniqueName();
+ String ddlStmt = "create table "
+ + tableName
+ + " (organization_id char(15) not null, \n"
+ + " entity_id char(15) not null,\n"
+ + " x_double double,\n"
+ + " a_double_array double array[],\n"
+ + " a_char_array char(5) array[],\n"
+ + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
+ + ")";
+ BaseTest.createTestTable(url, ddlStmt, bs, null);
+ return tableName;
+ }
+
+ private static void initSimpleArrayTable(String tableName, String tenantId, Date date, boolean useNull) throws Exception {
+ Properties props = new Properties();
+
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ // Insert all rows at ts
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + tableName +
+ "(" +
+ " ORGANIZATION_ID, " +
+ " ENTITY_ID, " +
+ " x_double, " +
+ " a_double_array, a_char_array)" +
+ "VALUES (?, ?, ?, ?, ?)");
+ stmt.setString(1, tenantId);
+ stmt.setString(2, ROW1);
+ stmt.setDouble(3, 1.2d);
+ // Need to support primitive
+ Double[] doubleArr = new Double[2];
+ doubleArr[0] = 64.87;
+ doubleArr[1] = 89.96;
+ //doubleArr[2] = 9.9;
+ Array array = conn.createArrayOf("DOUBLE", doubleArr);
+ stmt.setArray(4, array);
+
+ // create character array
+ String[] charArr = new String[2];
+ charArr[0] = "a";
+ charArr[1] = "b";
+ array = conn.createArrayOf("CHAR", charArr);
+ stmt.setArray(5, array);
+ stmt.execute();
+
+ conn.commit();
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testScanByArrayValue() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_float";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ TestUtil.analyzeTable(conn, tableName);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setFloat(2, 0.01f);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[4];
+ doubleArr[0] = 25.343;
+ doubleArr[1] = 36.763;
+ doubleArr[2] = 37.56;
+ doubleArr[3] = 386.63;
+ Array array = conn.createArrayOf("DOUBLE",
+ doubleArr);
+ PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
+ assertEquals(resultArray, array);
+ assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
+ assertEquals(rs.getString("B_string"), B_VALUE);
+ assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testScanWithArrayInWhereClause() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_byte_array";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ TestUtil.analyzeTable(conn, tableName);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ // Need to support primitive
+ Byte[] byteArr = new Byte[2];
+ byteArr[0] = 25;
+ byteArr[1] = 36;
+ Array array = conn.createArrayOf("TINYINT", byteArr);
+ statement.setArray(2, array);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[4];
+ doubleArr[0] = 25.343;
+ doubleArr[1] = 36.763;
+ doubleArr[2] = 37.56;
+ doubleArr[3] = 386.63;
+ array = conn.createArrayOf("DOUBLE", doubleArr);
+ Array resultArray = rs.getArray(1);
+ assertEquals(resultArray, array);
+ assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
+ assertEquals(rs.getString("B_string"), B_VALUE);
+ assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testScanWithNonFixedWidthArrayInWhereClause() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_string_array";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ // Need to support primitive
+ String[] strArr = new String[4];
+ strArr[0] = "ABC";
+ strArr[1] = "CEDF";
+ strArr[2] = "XYZWER";
+ strArr[3] = "AB";
+ Array array = conn.createArrayOf("VARCHAR", strArr);
+ statement.setArray(2, array);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[4];
+ doubleArr[0] = 25.343;
+ doubleArr[1] = 36.763;
+ doubleArr[2] = 37.56;
+ doubleArr[3] = 386.63;
+ array = conn.createArrayOf("DOUBLE", doubleArr);
+ Array resultArray = rs.getArray(1);
+ assertEquals(resultArray, array);
+ assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
+ assertEquals(rs.getString("B_string"), B_VALUE);
+ assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testScanWithNonFixedWidthArrayInSelectClause() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array FROM " + tableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[4];
+ strArr[0] = "ABC";
+ strArr[1] = "CEDF";
+ strArr[2] = "XYZWER";
+ strArr[3] = "AB";
+ Array array = conn.createArrayOf("VARCHAR", strArr);
+ PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
+ assertEquals(resultArray, array);
+ assertEquals("['ABC', 'CEDF', 'XYZWER', 'AB']", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSpecificIndexOfAnArrayAsArrayFunction()
+ throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + tableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 36.763;
+ conn.createArrayOf("DOUBLE", doubleArr);
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSpecificIndexOfAnArray() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array[3] FROM " + tableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 37.56;
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testCaseWithArray() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(tableName, tenantId, null, false, getUrl());
+ String query = "SELECT CASE WHEN A_INTEGER = 1 THEN a_double_array ELSE null END [3] FROM " + tableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 37.56;
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpsertValuesWithArray() throws Exception {
+ String tenantId = getOrganizationId();
+ String tableName = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ String query = "upsert into " + tableName + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) values('" + tenantId
+ + "','00A123122312312',ARRAY[2.0,345.8])";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ // at
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ int executeUpdate = statement.executeUpdate();
+ assertEquals(1, executeUpdate);
+ conn.commit();
+ statement.close();
+ conn.close();
+ // create another connection
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + tableName;
+ statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 345.8d;
+ conn.createArrayOf("DOUBLE", doubleArr);
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpsertSelectWithSelectAsSubQuery1() throws Exception {
+ String tenantId = getOrganizationId();
+ String table1 = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ Connection conn = null;
+ try {
+ String table2 = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table2, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "upsert into " + table1 + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) "
+ + "SELECT organization_id, entity_id, a_double_array FROM " + table2
+ + " WHERE a_double_array[2] = 89.96";
+ PreparedStatement statement = conn.prepareStatement(query);
+ int executeUpdate = statement.executeUpdate();
+ assertEquals(1, executeUpdate);
+ conn.commit();
+ statement.close();
+ conn.close();
+ // create another connection
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table1;
+ statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 89.96d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ assertFalse(rs.next());
+
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithORCondition() throws Exception {
+ String tenantId = getOrganizationId();
+ Connection conn = null;
+ try {
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_double_array[1] FROM " + table
+ + " WHERE a_double_array[2] = 89.96 or a_char_array[0] = 'a'";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 64.87d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ assertFalse(rs.next());
+
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithANY() throws Exception {
+ String tenantId = getOrganizationId();
+ Connection conn = null;
+ try {
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_double_array[1] FROM " + table
+ + " WHERE CAST(89.96 AS DOUBLE) = ANY(a_double_array)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 64.87d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ assertFalse(rs.next());
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithALL() throws Exception {
+ String tenantId = getOrganizationId();
+ Connection conn = null;
+ try {
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_double_array[1] FROM " + table
+ + " WHERE CAST(64.87 as DOUBLE) = ALL(a_double_array)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertFalse(rs.next());
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithANYCombinedWithOR() throws Exception {
+ String tenantId = getOrganizationId();
+ Connection conn = null;
+ try {
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_double_array[1] FROM " + table
+ + " WHERE a_char_array[0] = 'f' or CAST(89.96 AS DOUBLE) > ANY(a_double_array)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 64.87d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ assertFalse(rs.next());
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithALLCombinedWithOR() throws Exception {
+
+ String tenantId = getOrganizationId();
+ Connection conn = null;
+ try {
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_double_array[1], a_double_array[2] FROM " + table
+ + " WHERE a_char_array[0] = 'f' or CAST(100.0 AS DOUBLE) > ALL(a_double_array)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 64.87d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ doubleArr = new Double[1];
+ doubleArr[0] = 89.96d;
+ result = rs.getDouble(2);
+ assertEquals(result, doubleArr[0]);
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testArraySelectWithANYUsingVarLengthArray() throws Exception {
+ Connection conn = null;
+ try {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "SELECT a_string_array[1] FROM " + table
+ + " WHERE 'XYZWER' = ANY(a_string_array)";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "ABC";
+ String result = rs.getString(1);
+ assertEquals(result, strArr[0]);
+ assertFalse(rs.next());
+ query = "SELECT a_string_array[1] FROM " + table + " WHERE 'AB' = ANY(a_string_array)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ result = rs.getString(1);
+ assertEquals(result, strArr[0]);
+ assertFalse(rs.next());
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testSelectWithArrayWithColumnRef() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_integer,ARRAY[1,2,a_integer] FROM " + table + " where organization_id = '"
+ + tenantId + "'";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ int val = rs.getInt(1);
+ assertEquals(val, 1);
+ Array array = rs.getArray(2);
+ // Need to support primitive
+ Integer[] intArr = new Integer[3];
+ intArr[0] = 1;
+ intArr[1] = 2;
+ intArr[2] = 1;
+ Array resultArr = conn.createArrayOf("INTEGER", intArr);
+ assertEquals(resultArr, array);
+ assertEquals("[1, 2, 1]", rs.getString(2));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectWithArrayWithColumnRefWithVarLengthArray() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT b_string,ARRAY['abc','defgh',b_string] FROM " + table + " where organization_id = '"
+ + tenantId + "'";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String val = rs.getString(1);
+ assertEquals(val, "b");
+ Array array = rs.getArray(2);
+ // Need to support primitive
+ String[] strArr = new String[3];
+ strArr[0] = "abc";
+ strArr[1] = "defgh";
+ strArr[2] = "b";
+ Array resultArr = conn.createArrayOf("VARCHAR", strArr);
+ assertEquals(resultArr, array);
+ // since array is var length, last string element is messed up
+ String expectedPrefix = "['abc', 'defgh', 'b";
+ assertTrue("Expected to start with " + expectedPrefix,
+ rs.getString(2).startsWith(expectedPrefix));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectWithArrayWithColumnRefWithVarLengthArrayWithNullValue() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT b_string,ARRAY['abc',null,'bcd',null,null,b_string] FROM " + table + " where organization_id = '"
+ + tenantId + "'";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String val = rs.getString(1);
+ assertEquals(val, "b");
+ Array array = rs.getArray(2);
+ // Need to support primitive
+ String[] strArr = new String[6];
+ strArr[0] = "abc";
+ strArr[1] = null;
+ strArr[2] = "bcd";
+ strArr[3] = null;
+ strArr[4] = null;
+ strArr[5] = "b";
+ Array resultArr = conn.createArrayOf("VARCHAR", strArr);
+ assertEquals(resultArr, array);
+ String expectedPrefix = "['abc', null, 'bcd', null, null, 'b";
+ assertTrue("Expected to start with " + expectedPrefix,
+ rs.getString(2).startsWith(expectedPrefix));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpsertSelectWithColumnRef() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table1 = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ Connection conn = null;
+ try {
+ String table2 = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table2, tenantId, null, false);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String query = "upsert into " + table1 + " (ORGANIZATION_ID,ENTITY_ID, a_unsigned_double, a_double_array) "
+ + "SELECT organization_id, entity_id, x_double, ARRAY[23.4, 22.1, x_double] FROM " + table2
+ + " WHERE a_double_array[2] = 89.96";
+ PreparedStatement statement = conn.prepareStatement(query);
+ int executeUpdate = statement.executeUpdate();
+ assertEquals(1, executeUpdate);
+ conn.commit();
+ statement.close();
+ conn.close();
+ // create another connection
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table1;
+ statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 22.1d;
+ Double result = rs.getDouble(1);
+ assertEquals(result, doubleArr[0]);
+ assertFalse(rs.next());
+
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+ }
+
+ @Test
+ public void testCharArraySpecificIndex() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ initSimpleArrayTable(table, tenantId, null, false);
+ String query = "SELECT a_char_array[2] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] charArr = new String[1];
+ charArr[0] = "b";
+ String result = rs.getString(1);
+ assertEquals(charArr[0], result);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testArrayWithDescOrder() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute(
+ "CREATE TABLE " + table + " ( k VARCHAR, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4] \n"
+ + " CONSTRAINT pk PRIMARY KEY (k, b_string_array DESC)) \n");
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
+ Array array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
+ array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(3, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT b_string_array FROM " + table);
+ assertTrue(rs.next());
+ PhoenixArray strArr = (PhoenixArray)rs.getArray(1);
+ assertEquals(array, strArr);
+ assertEquals("['abc', 'def', 'ghi', 'jkll', null, null, null, 'xxx']", rs.getString(1));
+ conn.close();
+ }
+
+ @Test
+ public void testArrayWithFloatArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a Float ARRAY[])");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES('a',ARRAY[2.0,3.0])");
+ int res = stmt.executeUpdate();
+ assertEquals(1, res);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(a,2) FROM " + table);
+ assertTrue(rs.next());
+ Float f = new Float(3.0);
+ assertEquals(f, (Float)rs.getFloat(1));
+ conn.close();
+ }
+
+ @Test
+ public void testArrayWithVarCharArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a VARCHAR ARRAY[])");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES('a',ARRAY['a',null])");
+ int res = stmt.executeUpdate();
+ assertEquals(1, res);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(a,2) FROM " + table);
+ assertTrue(rs.next());
+ assertEquals(null, rs.getString(1));
+ conn.close();
+ }
+
+ @Test
+ public void testArraySelectSingleArrayElemWithCast() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a bigint ARRAY[])");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ Long[] s = new Long[] {1l, 2l};
+ Array array = conn.createArrayOf("BIGINT", s);
+ stmt.setArray(2, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT k, CAST(a[2] AS DOUBLE) FROM " + table);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ Double d = new Double(2.0);
+ assertEquals(d, (Double)rs.getDouble(2));
+ conn.close();
+ }
+
+ @Test
+ public void testArraySelectGetString() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+
+ String tenantId = getOrganizationId();
+
+ // create the table
+ String tableName = createTableWithAllArrayTypes(getUrl(), getDefaultSplits(tenantId), null);
+
+ // populate the table with data
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt =
+ conn.prepareStatement("UPSERT INTO "
+ + tableName
+ + "(ORGANIZATION_ID, ENTITY_ID, BOOLEAN_ARRAY, BYTE_ARRAY, DOUBLE_ARRAY, FLOAT_ARRAY, INT_ARRAY, LONG_ARRAY, SHORT_ARRAY, STRING_ARRAY)\n"
+ + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, tenantId);
+ stmt.setString(2, ROW1);
+ // boolean array
+ Array boolArray = conn.createArrayOf("BOOLEAN", new Boolean[] { true, false });
+ int boolIndex = 3;
+ stmt.setArray(boolIndex, boolArray);
+ // byte array
+ Array byteArray = conn.createArrayOf("TINYINT", new Byte[] { 11, 22 });
+ int byteIndex = 4;
+ stmt.setArray(byteIndex, byteArray);
+ // double array
+ Array doubleArray = conn.createArrayOf("DOUBLE", new Double[] { 67.78, 78.89 });
+ int doubleIndex = 5;
+ stmt.setArray(doubleIndex, doubleArray);
+ // float array
+ Array floatArray = conn.createArrayOf("FLOAT", new Float[] { 12.23f, 45.56f });
+ int floatIndex = 6;
+ stmt.setArray(floatIndex, floatArray);
+ // int array
+ Array intArray = conn.createArrayOf("INTEGER", new Integer[] { 5555, 6666 });
+ int intIndex = 7;
+ stmt.setArray(intIndex, intArray);
+ // long array
+ Array longArray = conn.createArrayOf("BIGINT", new Long[] { 7777777L, 8888888L });
+ int longIndex = 8;
+ stmt.setArray(longIndex, longArray);
+ // short array
+ Array shortArray = conn.createArrayOf("SMALLINT", new Short[] { 333, 444 });
+ int shortIndex = 9;
+ stmt.setArray(shortIndex, shortArray);
+ // create character array
+ Array stringArray = conn.createArrayOf("VARCHAR", new String[] { "a", "b" });
+ int stringIndex = 10;
+ stmt.setArray(stringIndex, stringArray);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt =
+ conn.prepareStatement("SELECT organization_id, entity_id, boolean_array, byte_array, double_array, float_array, int_array, long_array, short_array, string_array FROM "
+ + tableName);
+ TestUtil.analyzeTable(conn, tableName);
+
+ ResultSet rs = stmt.executeQuery();
+ assertTrue(rs.next());
+
+ assertEquals(tenantId, rs.getString(1));
+ assertEquals(ROW1, rs.getString(2));
+
+ assertArrayGetString(rs, boolIndex, boolArray, "true, false");
+ assertArrayGetString(rs, byteIndex, byteArray, "11, 22");
+ assertArrayGetString(rs, doubleIndex, doubleArray, "67.78, 78.89");
+ assertArrayGetString(rs, floatIndex, floatArray, "12.23, 45.56");
+ assertArrayGetString(rs, intIndex, intArray, "5555, 6666");
+ assertArrayGetString(rs, longIndex, longArray, "7777777, 8888888");
+ assertArrayGetString(rs, shortIndex, shortArray, "333, 444");
+ assertArrayGetString(rs, stringIndex, stringArray, "'a', 'b'");
+ conn.close();
+ }
+
+ @Test
+ public void testArrayWithCast() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a bigint ARRAY[])");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ Long[] s = new Long[] { 1l, 2l };
+ Array array = conn.createArrayOf("BIGINT", s);
+ stmt.setArray(2, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT CAST(a AS DOUBLE []) FROM " + table);
+ assertTrue(rs.next());
+ Double[] d = new Double[] { 1.0, 2.0 };
+ array = conn.createArrayOf("DOUBLE", d);
+ PhoenixArray arr = (PhoenixArray)rs.getArray(1);
+ assertEquals(array, arr);
+ assertEquals("[1.0, 2.0]", rs.getString(1));
+ conn.close();
+ }
+
+ @Test
+ public void testArrayWithCastForVarLengthArr() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a VARCHAR(5) ARRAY)");
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] { "1", "2" };
+ PhoenixArray array = (PhoenixArray)conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT CAST(a AS CHAR ARRAY) FROM " + table);
+ assertTrue(rs.next());
+ PhoenixArray arr = (PhoenixArray)rs.getArray(1);
+ String[] array2 = (String[])array.getArray();
+ String[] array3 = (String[])arr.getArray();
+ assertEquals(array2[0], array3[0]);
+ assertEquals(array2[1], array3[1]);
+ assertEquals("['1', '2']", rs.getString(1));
+ conn.close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/527f786a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array2IT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array2IT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array2IT.java
new file mode 100644
index 0000000..52bfb86
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/Array2IT.java
@@ -0,0 +1,815 @@
+/*
+ * 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.end2end;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Properties;
+
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.StringUtil;
+import org.junit.Test;
+
+public class Array2IT extends ArrayIT {
+ @Test
+ public void testFixedWidthCharArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a CHAR(5) ARRAY)");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.getMetaData().getColumns(null, null, table, "A");
+ assertTrue(rs.next());
+ assertEquals(5, rs.getInt("COLUMN_SIZE"));
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] {"1","2"};
+ Array array = conn.createArrayOf("CHAR", s);
+ stmt.setArray(2, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT k, a[2] FROM " + table);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("2",rs.getString(2));
+ conn.close();
+ }
+
+ @Test
+ public void testSelectArrayUsingUpsertLikeSyntax() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array FROM " + table + " WHERE a_double_array = CAST(ARRAY [ 25.343, 36.763, 37.56,386.63] AS DOUBLE ARRAY)";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ Double[] doubleArr = new Double[4];
+ doubleArr[0] = 25.343;
+ doubleArr[1] = 36.763;
+ doubleArr[2] = 37.56;
+ doubleArr[3] = 386.63;
+ Array array = conn.createArrayOf("DOUBLE", doubleArr);
+ PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
+ assertEquals(resultArray, array);
+ assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testArrayIndexUsedInWhereClause() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ int a_index = 0;
+ String query = "SELECT a_double_array[2] FROM " + table + " where a_double_array["+a_index+"2]<?";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 40.0;
+ conn.createArrayOf("DOUBLE", doubleArr);
+ statement.setDouble(1, 40.0d);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ doubleArr = new Double[1];
+ doubleArr[0] = 36.763;
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testArrayIndexUsedInGroupByClause() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array[2] FROM " + table + " GROUP BY a_double_array[2]";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 40.0;
+ conn.createArrayOf("DOUBLE", doubleArr);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ doubleArr = new Double[1];
+ doubleArr[0] = 36.763;
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testVariableLengthArrayWithNullValue() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, true, getUrl());
+ String query = "SELECT a_string_array[2] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ String result = rs.getString(1);
+ assertNull(result);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSpecificIndexOfAVariableArrayAlongWithAnotherColumn1() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array[3],A_INTEGER FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ String result = rs.getString(1);
+ assertEquals(strArr[0], result);
+ int a_integer = rs.getInt(2);
+ assertEquals(1, a_integer);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSpecificIndexOfAVariableArrayAlongWithAnotherColumn2() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT A_INTEGER, a_string_array[3] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ int a_integer = rs.getInt(1);
+ assertEquals(1, a_integer);
+ String result = rs.getString(2);
+ assertEquals(strArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectMultipleArrayColumns() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array[3], a_double_array[2] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 36.763d;
+ Double a_double = rs.getDouble(2);
+ assertEquals(doubleArr[0], a_double);
+ String result = rs.getString(1);
+ assertEquals(strArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSameArrayColumnMultipleTimesWithDifferentIndices() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array[1], a_string_array[2], " +
+ "a_string_array[3], a_double_array[1], a_double_array[2], a_double_array[3] " +
+ "FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("ABC", rs.getString(1));
+ assertEquals("CEDF", rs.getString(2));
+ assertEquals("XYZWER", rs.getString(3));
+ assertEquals(25.343, rs.getDouble(4), 0.0);
+ assertEquals(36.763, rs.getDouble(5), 0.0);
+ assertEquals(37.56, rs.getDouble(6), 0.0);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSameArrayColumnMultipleTimesWithSameIndices() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array[3], a_string_array[3] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ String result = rs.getString(1);
+ assertEquals(strArr[0], result);
+ result = rs.getString(2);
+ assertEquals(strArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectSpecificIndexOfAVariableArray() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_string_array[3] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = "XYZWER";
+ String result = rs.getString(1);
+ assertEquals(strArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testWithOutOfRangeIndex() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT a_double_array[100] FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
+ assertNull(resultArray);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testArrayLengthFunctionForVariableLength() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT ARRAY_LENGTH(a_string_array) FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ int result = rs.getInt(1);
+ assertEquals(result, 4);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+
+ @Test
+ public void testArrayLengthFunctionForFixedLength() throws Exception {
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ initTablesWithArrays(table, tenantId, null, false, getUrl());
+ String query = "SELECT ARRAY_LENGTH(a_double_array) FROM " + table;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ int result = rs.getInt(1);
+ assertEquals(result, 4);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testArraySizeRoundtrip() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(),
+ getDefaultSplits(tenantId), null);
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ ResultSet rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("x_long_array")));
+ assertTrue(rs.next());
+ assertEquals(5, rs.getInt("ARRAY_SIZE"));
+ assertFalse(rs.next());
+
+ rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("a_string_array")));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt("ARRAY_SIZE"));
+ assertFalse(rs.next());
+
+ rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("a_double_array")));
+ assertTrue(rs.next());
+ assertEquals(0, rs.getInt("ARRAY_SIZE"));
+ assertTrue(rs.wasNull());
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testVarLengthArrComparisonInWhereClauseWithSameArrays() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] {"abc","def", "ghi","jkl"};
+ Array array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ s = new String[] {"abc","def", "ghi","jkl"};
+ array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(3, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery("SELECT k, a_string_array[2] FROM " + table + " where a_string_array=b_string_array");
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("def",rs.getString(2));
+ conn.close();
+ }
+
+ @Test
+ public void testVarLengthArrComparisonInWhereClauseWithDiffSizeArrays() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] { "abc", "def", "ghi", "jkll" };
+ Array array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ s = new String[] { "abc", "def", "ghi", "jklm" };
+ array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(3, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery(
+ "SELECT k, a_string_array[2] FROM " + table + " where a_string_array<b_string_array");
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("def", rs.getString(2));
+ conn.close();
+ }
+
+ @Test
+ public void testVarLengthArrComparisonWithNulls() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
+ Array array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
+ array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(3, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery(
+ "SELECT k, a_string_array[2] FROM " + table + " where a_string_array>b_string_array");
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("def", rs.getString(2));
+ conn.close();
+ }
+
+ @Test
+ public void testUpsertValuesWithNull() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ String query = "upsert into " + table + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) values('" + tenantId
+ + "','00A123122312312',null)";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ // at
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ int executeUpdate = statement.executeUpdate();
+ assertEquals(1, executeUpdate);
+ conn.commit();
+ statement.close();
+ conn.close();
+ // create another connection
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table;
+ statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ // Need to support primitive
+ Double[] doubleArr = new Double[1];
+ doubleArr[0] = 0.0d;
+ conn.createArrayOf("DOUBLE", doubleArr);
+ Double result = rs.getDouble(1);
+ assertEquals(doubleArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpsertValuesWithNullUsingPreparedStmt() throws Exception {
+
+ String tenantId = getOrganizationId();
+ String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
+ String query = "upsert into " + table + " (ORGANIZATION_ID,ENTITY_ID,a_string_array) values(?, ?, ?)";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ // at
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.setString(1, tenantId);
+ statement.setString(2, "00A123122312312");
+ statement.setNull(3, Types.ARRAY);
+ int executeUpdate = statement.executeUpdate();
+ assertEquals(1, executeUpdate);
+ conn.commit();
+ statement.close();
+ conn.close();
+ // create another connection
+ props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ query = "SELECT ARRAY_ELEM(a_string_array,1) FROM " + table;
+ statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ String[] strArr = new String[1];
+ strArr[0] = null;
+ conn.createArrayOf("VARCHAR", strArr);
+ String result = rs.getString(1);
+ assertEquals(strArr[0], result);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testPKWithArray() throws Exception {
+ Connection conn;
+ PreparedStatement stmt;
+ ResultSet rs;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE " + table + " ( k VARCHAR, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4] \n"
+ + " CONSTRAINT pk PRIMARY KEY (k, b_string_array)) \n");
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
+ Array array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(2, array);
+ s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
+ array = conn.createArrayOf("VARCHAR", s);
+ stmt.setArray(3, array);
+ stmt.execute();
+ conn.commit();
+ conn.close();
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ rs = conn.createStatement().executeQuery(
+ "SELECT k, a_string_array[2] FROM " + table + " where b_string_array[8]='xxx'");
+ assertTrue(rs.next());
+ assertEquals("a", rs.getString(1));
+ assertEquals("def", rs.getString(2));
+ conn.close();
+ }
+
+ @Test
+ public void testPKWithArrayNotInEnd() throws Exception {
+ Connection conn;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE " + table + " ( a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4], k VARCHAR \n"
+ + " CONSTRAINT pk PRIMARY KEY (b_string_array, k))");
+ conn.close();
+ fail();
+ } catch (SQLException e) {
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ }
+
+ @Test
+ public void testArrayRefToLiteral() throws Exception {
+ Connection conn;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ PreparedStatement stmt = conn.prepareStatement("select ?[2] from \"SYSTEM\".\"catalog\" limit 1");
+ Array array = conn.createArrayOf("CHAR", new String[] {"a","b","c"});
+ stmt.setArray(1, array);
+ ResultSet rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals("b", rs.getString(1));
+ assertFalse(rs.next());
+ } catch (SQLException e) {
+ } finally {
+ if (conn != null) {
+ conn.close();
+ }
+ }
+
+ }
+
+ @Test
+ public void testArrayConstructorWithMultipleRows1() throws Exception {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 6,3)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 2,4)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 6,3)");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT ARRAY[a,b]) from " + table);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ }
+
+ @Test
+ public void testArrayConstructorWithMultipleRows2() throws Exception {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 6,3)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 2,4)");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 6,3)");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY[a,b] from " + table + " ");
+ assertTrue(rs.next());
+ Array arr = conn.createArrayOf("INTEGER", new Object[]{6, 3});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("INTEGER", new Object[]{2, 4});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("INTEGER", new Object[]{6, 3});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ }
+
+ @Test
+ public void testArrayConstructorWithMultipleRows3() throws Exception {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT ARRAY[a,b] from " + table + " ");
+ assertTrue(rs.next());
+ Array arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("VARCHAR", new Object[]{"abc", "dfg"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc"});
+ assertEquals(arr, rs.getArray(1));
+ rs.next();
+ }
+
+ @Test
+ public void testArrayConstructorWithMultipleRows4() throws Exception {
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String table = generateUniqueName();
+ String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
+ stmt.execute();
+ stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
+ stmt.execute();
+ conn.commit();
+ conn.close();
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT ARRAY[a,b]) from " + table);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ }
+
+}
[25/25] phoenix git commit: PHOENIX-4250 Breakup AlterTableIT into
several integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
PHOENIX-4250 Breakup AlterTableIT into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/eafb58be
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/eafb58be
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/eafb58be
Branch: refs/heads/master
Commit: eafb58bec2e35e0a999e40b2831b504c05295328
Parents: 3593ec8
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 17:46:27 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 18:23:44 2017 -0700
----------------------------------------------------------------------
.../apache/phoenix/end2end/AlterTableIT.java | 1231 ------------------
.../apache/phoenix/end2end/SetPropertyIT.java | 1022 +++++++++++++++
.../end2end/SetPropertyOnEncodedTableIT.java | 34 +
.../end2end/SetPropertyOnNonEncodedTableIT.java | 34 +
.../index/IndexWithTableSchemaChangeIT.java | 318 +++++
5 files changed, 1408 insertions(+), 1231 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/eafb58be/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
index d3a9c45..5265b09 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
@@ -17,7 +17,6 @@
*/
package org.apache.phoenix.end2end;
-import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_REPLICATION_SCOPE;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_FAMILY;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_NAME;
import static org.apache.phoenix.jdbc.PhoenixDatabaseMetaData.COLUMN_QUALIFIER;
@@ -37,7 +36,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@@ -50,12 +48,7 @@ import java.util.Properties;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.KeepDeletedCells;
import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.jdbc.PhoenixConnection;
@@ -93,11 +86,8 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
private String schemaName;
private String dataTableName;
private String indexTableName;
- private String localIndexTableName;
- private String viewName;
private String dataTableFullName;
private String indexTableFullName;
- private String localIndexTableFullName;
private String tableDDLOptions;
private final boolean columnEncoded;
@@ -116,11 +106,8 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
schemaName = "";
dataTableName = generateUniqueName();
indexTableName = "I_" + generateUniqueName();
- localIndexTableName = "LI_" + generateUniqueName();
dataTableFullName = SchemaUtil.getTableName(schemaName, dataTableName);
indexTableFullName = SchemaUtil.getTableName(schemaName, indexTableName);
- localIndexTableFullName = SchemaUtil.getTableName(schemaName, localIndexTableName);
- viewName = generateUniqueName();
}
@Test
@@ -257,22 +244,6 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
}
}
- private void assertIndexExists(Connection conn, boolean exists) throws SQLException {
- ResultSet rs = conn.getMetaData().getIndexInfo(null, schemaName, dataTableName, false, false);
- assertEquals(exists, rs.next());
- }
-
-
- @Test
- public void testDropIndexedColumnImmutableIndex() throws Exception {
- helpTestDropIndexedColumn(true);
- }
-
- @Test
- public void testDropIndexedColumnMutableIndex() throws Exception {
- helpTestDropIndexedColumn(false);
- }
-
private String generateDDLOptions(String options) {
StringBuilder sb = new StringBuilder();
if (!options.isEmpty()) {
@@ -286,270 +257,6 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
return sb.toString();
}
- private void helpTestDropIndexedColumn(boolean immutable) throws Exception {
- String query;
- ResultSet rs;
- PreparedStatement stmt;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- // make sure that the tables are empty, but reachable
- conn.createStatement().execute(
- "CREATE TABLE " + dataTableFullName
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) "
- + generateDDLOptions(immutable ? "IMMUTABLE_ROWS = true" : "")
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
- query = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- conn.createStatement().execute(
- "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1, v2)");
- conn.createStatement().execute(
- "CREATE LOCAL INDEX " + localIndexTableName + " ON " + dataTableFullName + " (v1, v2)");
-
- query = "SELECT * FROM " + indexTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- conn.commit();
-
- assertIndexExists(conn,true);
- conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " DROP COLUMN v1");
- assertIndexExists(conn,false);
-
- query = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("1",rs.getString(2));
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "2");
- stmt.execute();
- conn.commit();
-
- query = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("2",rs.getString(2));
- assertFalse(rs.next());
- }
-
- @Test
- public void testDropCoveredColumn() throws Exception {
- ResultSet rs;
- PreparedStatement stmt;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- // make sure that the tables are empty, but reachable
- conn.createStatement().execute(
- "CREATE TABLE " + dataTableFullName
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR, v3 VARCHAR) " + tableDDLOptions);
- String dataTableQuery = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(dataTableQuery);
- assertFalse(rs.next());
-
- conn.createStatement().execute(
- "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1) include (v2, v3)");
- conn.createStatement().execute(
- "CREATE LOCAL INDEX " + localIndexTableName + " ON " + dataTableFullName + " (v1) include (v2, v3)");
- rs = conn.createStatement().executeQuery(dataTableQuery);
- assertFalse(rs.next());
- String indexTableQuery = "SELECT * FROM " + indexTableName;
- rs = conn.createStatement().executeQuery(indexTableQuery);
- assertFalse(rs.next());
- String localIndexTableQuery = "SELECT * FROM " + localIndexTableFullName;
- rs = conn.createStatement().executeQuery(localIndexTableQuery);
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.setString(4, "j");
- stmt.execute();
- conn.commit();
-
- assertIndexExists(conn,true);
- conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " DROP COLUMN v2");
- assertIndexExists(conn,true);
-
- // verify data table rows
- Scan scan = new Scan();
- HTable table = (HTable) conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(dataTableFullName));
- ResultScanner results = table.getScanner(scan);
- for (Result res : results) {
- assertNull("Column value was not deleted",res.getValue(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("V2")));
- }
- results.close();
- rs = conn.createStatement().executeQuery(dataTableQuery);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("x",rs.getString(2));
- assertEquals("j",rs.getString(3));
- assertFalse(rs.next());
-
- // verify index table rows
- scan = new Scan();
- table = (HTable) conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(indexTableFullName));
- results = table.getScanner(scan);
- for (Result res : results) {
- assertNull("Column value was not deleted",res.getValue(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("0:V2")));
- }
- results.close();
- rs = conn.createStatement().executeQuery(indexTableQuery);
- assertTrue(rs.next());
- assertEquals("x",rs.getString(1));
- assertEquals("a",rs.getString(2));
- assertEquals("j",rs.getString(3));
- assertFalse(rs.next());
-
- // verify local index table rows
- rs = conn.createStatement().executeQuery(localIndexTableQuery);
- assertTrue(rs.next());
- assertEquals("x",rs.getString(1));
- assertEquals("a",rs.getString(2));
- assertEquals("j",rs.getString(3));
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "y");
- stmt.setString(3, "k");
- stmt.execute();
- conn.commit();
-
- // verify data table rows
- rs = conn.createStatement().executeQuery(dataTableQuery);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("y",rs.getString(2));
- assertEquals("k",rs.getString(3));
- assertFalse(rs.next());
-
- // verify index table rows
- rs = conn.createStatement().executeQuery(indexTableQuery);
- assertTrue(rs.next());
- assertEquals("y",rs.getString(1));
- assertEquals("a",rs.getString(2));
- assertEquals("k",rs.getString(3));
- assertFalse(rs.next());
-
- // verify local index table rows
- rs = conn.createStatement().executeQuery(localIndexTableQuery);
- assertTrue(rs.next());
- assertEquals("y",rs.getString(1));
- assertEquals("a",rs.getString(2));
- assertEquals("k",rs.getString(3));
- assertFalse(rs.next());
- }
-
- @Test
- public void testAddPKColumnToTableWithIndex() throws Exception {
- String query;
- ResultSet rs;
- PreparedStatement stmt;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- // make sure that the tables are empty, but reachable
- conn.createStatement().execute(
- "CREATE TABLE " + dataTableFullName
- + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) " + tableDDLOptions);
- query = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- conn.createStatement().execute(
- "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1) include (v2)");
- query = "SELECT * FROM " + indexTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- stmt.setString(2, "x");
- stmt.setString(3, "1");
- stmt.execute();
- conn.commit();
-
- assertIndexExists(conn,true);
- conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " ADD v3 VARCHAR, k2 DECIMAL PRIMARY KEY, k3 DECIMAL PRIMARY KEY");
- rs = conn.getMetaData().getPrimaryKeys("", schemaName, dataTableName);
- assertTrue(rs.next());
- assertEquals("K",rs.getString("COLUMN_NAME"));
- assertEquals(1, rs.getShort("KEY_SEQ"));
- assertTrue(rs.next());
- assertEquals("K2",rs.getString("COLUMN_NAME"));
- assertEquals(2, rs.getShort("KEY_SEQ"));
- assertTrue(rs.next());
- assertEquals("K3",rs.getString("COLUMN_NAME"));
- assertEquals(3, rs.getShort("KEY_SEQ"));
- assertFalse(rs.next());
-
- rs = conn.getMetaData().getPrimaryKeys("", schemaName, indexTableName);
- assertTrue(rs.next());
- assertEquals(QueryConstants.DEFAULT_COLUMN_FAMILY + IndexUtil.INDEX_COLUMN_NAME_SEP + "V1",rs.getString("COLUMN_NAME"));
- assertEquals(1, rs.getShort("KEY_SEQ"));
- assertTrue(rs.next());
- assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K",rs.getString("COLUMN_NAME"));
- assertEquals(2, rs.getShort("KEY_SEQ"));
- assertTrue(rs.next());
- assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K2",rs.getString("COLUMN_NAME"));
- assertEquals(3, rs.getShort("KEY_SEQ"));
- assertTrue(rs.next());
- assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K3",rs.getString("COLUMN_NAME"));
- assertEquals(4, rs.getShort("KEY_SEQ"));
- assertFalse(rs.next());
-
- query = "SELECT * FROM " + dataTableFullName;
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("x",rs.getString(2));
- assertEquals("1",rs.getString(3));
- assertNull(rs.getBigDecimal(4));
- assertFalse(rs.next());
-
- // load some data into the table
- stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + "(K,K2,V1,V2,K3) VALUES(?,?,?,?,?)");
- stmt.setString(1, "b");
- stmt.setBigDecimal(2, BigDecimal.valueOf(2));
- stmt.setString(3, "y");
- stmt.setString(4, "2");
- stmt.setBigDecimal(5, BigDecimal.valueOf(3));
- stmt.execute();
- conn.commit();
-
- query = "SELECT k,k2,k3 FROM " + dataTableFullName + " WHERE v1='y'";
- rs = conn.createStatement().executeQuery(query);
- assertTrue(rs.next());
- assertEquals("b",rs.getString(1));
- assertEquals(BigDecimal.valueOf(2),rs.getBigDecimal(2));
- assertEquals(BigDecimal.valueOf(3),rs.getBigDecimal(3));
- assertFalse(rs.next());
- }
@Test
public void testSetSaltedTableAsImmutable() throws Exception {
@@ -1142,903 +849,6 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
conn1.close();
}
- @Test
- public void testSetHColumnProperties() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET REPLICATION_SCOPE=1";
- conn1.createStatement().execute(ddl);
- try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertEquals(1, columnFamilies[0].getScope());
- }
- }
-
- @Test
- public void testSetHTableProperties() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED=FALSE";
- conn1.createStatement().execute(ddl);
- try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- assertEquals(1, tableDesc.getColumnFamilies().length);
- assertEquals("0", tableDesc.getColumnFamilies()[0].getNameAsString());
- assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
- }
- }
-
- @Test
- public void testSetHTableAndHColumnProperties() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, REPLICATION_SCOPE = 1";
- conn1.createStatement().execute(ddl);
- try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertEquals(1, columnFamilies[0].getScope());
- assertEquals(false, tableDesc.isCompactionEnabled());
- }
- }
-
- @Test
- public void testSetHTableHColumnAndPhoenixTableProperties() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CF1.CREATION_TIME BIGINT,\n"
- +"CF2.LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("IMMUTABLE_ROWS=true"
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, true);
- ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, VERSIONS = 10";
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, CF1.MIN_VERSIONS = 1, CF2.MIN_VERSIONS = 3, MIN_VERSIONS = 8, CF1.KEEP_DELETED_CELLS = true, KEEP_DELETED_CELLS = false";
- conn.createStatement().execute(ddl);
-
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(3, columnFamilies.length);
-
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertEquals(8, columnFamilies[0].getMinVersions());
- assertEquals(10, columnFamilies[0].getMaxVersions());
- assertEquals(KeepDeletedCells.FALSE, columnFamilies[0].getKeepDeletedCells());
-
- assertEquals("CF1", columnFamilies[1].getNameAsString());
- assertEquals(1, columnFamilies[1].getMinVersions());
- assertEquals(10, columnFamilies[1].getMaxVersions());
- assertEquals(KeepDeletedCells.TRUE, columnFamilies[1].getKeepDeletedCells());
-
- assertEquals("CF2", columnFamilies[2].getNameAsString());
- assertEquals(3, columnFamilies[2].getMinVersions());
- assertEquals(10, columnFamilies[2].getMaxVersions());
- assertEquals(KeepDeletedCells.FALSE, columnFamilies[2].getKeepDeletedCells());
-
- assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
- }
- }
-
- @Test
- public void testSpecifyingColumnFamilyForHTablePropertyFails() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET CF.COMPACTION_ENABLED = FALSE";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSpecifyingColumnFamilyForPhoenixTablePropertyFails() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET CF.DISABLE_WAL = TRUE";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSpecifyingColumnFamilyForTTLFails() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"CF.LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET CF.TTL = 86400";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSetPropertyNeedsColumnFamilyToExist() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET CF.REPLICATION_SCOPE = 1";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_FOUND.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSetDefaultColumnFamilyNotAllowed() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions(" SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET DEFAULT_COLUMN_FAMILY = 'A'";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.DEFAULT_COLUMN_FAMILY_ONLY_ON_CREATE_TABLE.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSetHColumnOrHTablePropertiesOnViewsNotAllowed() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- ddl = "CREATE VIEW " + viewName + " AS SELECT * FROM " + dataTableFullName + " WHERE CREATION_TIME = 1";
- conn1.createStatement().execute(ddl);
- ddl = "ALTER VIEW " + viewName + " SET REPLICATION_SCOPE = 1";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
- }
- ddl = "ALTER VIEW " + viewName + " SET COMPACTION_ENABLED = FALSE";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSetForSomePhoenixTablePropertiesOnViewsAllowed() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
- Connection conn1 = DriverManager.getConnection(getUrl(), props);
- conn1.createStatement().execute(ddl);
- String viewFullName = SchemaUtil.getTableName(schemaName, generateUniqueName());
- ddl = "CREATE VIEW " + viewFullName + " AS SELECT * FROM " + dataTableFullName + " WHERE CREATION_TIME = 1";
- conn1.createStatement().execute(ddl);
- ddl = "ALTER VIEW " + viewFullName + " SET UPDATE_CACHE_FREQUENCY = 10";
- conn1.createStatement().execute(ddl);
- conn1.createStatement().execute("SELECT * FROM " + viewFullName);
- PhoenixConnection pconn = conn1.unwrap(PhoenixConnection.class);
- assertEquals(10, pconn.getTable(new PTableKey(pconn.getTenantId(), viewFullName)).getUpdateCacheFrequency());
- ddl = "ALTER VIEW " + viewFullName + " SET UPDATE_CACHE_FREQUENCY = 20";
- conn1.createStatement().execute(ddl);
- conn1.createStatement().execute("SELECT * FROM " + viewFullName);
- pconn = conn1.unwrap(PhoenixConnection.class);
- assertEquals(20, pconn.getTable(new PTableKey(pconn.getTenantId(), viewFullName)).getUpdateCacheFrequency());
- assertImmutableRows(conn1, viewFullName, false);
- ddl = "ALTER VIEW " + viewFullName + " SET DISABLE_WAL = TRUE";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
- }
- ddl = "ALTER VIEW " + viewFullName + " SET THROW_INDEX_WRITE_FAILURE = FALSE";
- try {
- conn1.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
- }
- }
-
- @Test
- public void testSettingPropertiesWhenTableHasDefaultColFamilySpecified() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID1 VARCHAR(15) NOT NULL,\n"
- +"ID2 VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"CF.LAST_USED DATE,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("IMMUTABLE_ROWS=true, DEFAULT_COLUMN_FAMILY = 'XYZ'"
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, true);
- ddl = "ALTER TABLE " + dataTableFullName
- + " SET COMPACTION_ENABLED = FALSE, CF.REPLICATION_SCOPE=1, IMMUTABLE_ROWS = TRUE, TTL=1000";
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, true);
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("CF", columnFamilies[0].getNameAsString());
- assertEquals(1, columnFamilies[0].getScope());
- assertEquals(1000, columnFamilies[0].getTimeToLive());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertEquals(DEFAULT_REPLICATION_SCOPE, columnFamilies[1].getScope());
- assertEquals(1000, columnFamilies[1].getTimeToLive());
- assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
- }
- }
-
- private static void assertImmutableRows(Connection conn, String fullTableName, boolean expectedValue) throws SQLException {
- PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- assertEquals(expectedValue, pconn.getTable(new PTableKey(pconn.getTenantId(), fullTableName)).isImmutableRows());
- }
-
- @Test
- public void testSetPropertyAndAddColumnForExistingColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName
- +
- " (a_string varchar not null, col1 integer, CF.col2 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement().execute(
- "ALTER TABLE " + dataTableFullName + " ADD CF.col3 integer CF.IN_MEMORY=true");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertFalse(columnFamilies[0].isInMemory());
- assertEquals("CF", columnFamilies[1].getNameAsString());
- assertTrue(columnFamilies[1].isInMemory());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnForNewAndExistingColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName + " "
- +
- " (a_string varchar not null, col1 integer, CF1.col2 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement()
- .execute(
- "ALTER TABLE "
- + dataTableFullName
- + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false ");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(3, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertTrue(columnFamilies[0].isInMemory());
- assertEquals(0, columnFamilies[0].getScope());
- assertEquals("CF1", columnFamilies[1].getNameAsString());
- assertTrue(columnFamilies[1].isInMemory());
- assertEquals(1, columnFamilies[1].getScope());
- assertEquals("CF2", columnFamilies[2].getNameAsString());
- assertFalse(columnFamilies[2].isInMemory());
- assertEquals(0, columnFamilies[2].getScope());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnWhenTableHasExplicitDefaultColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName + " "
- +
- " (a_string varchar not null, col1 integer, CF1.col2 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement()
- .execute(
- "ALTER TABLE "
- + dataTableFullName
- + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false, XYZ.REPLICATION_SCOPE=1 ");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(3, columnFamilies.length);
- assertEquals("CF1", columnFamilies[0].getNameAsString());
- assertTrue(columnFamilies[0].isInMemory());
- assertEquals(1, columnFamilies[0].getScope());
- assertEquals("CF2", columnFamilies[1].getNameAsString());
- assertFalse(columnFamilies[1].isInMemory());
- assertEquals(0, columnFamilies[1].getScope());
- assertEquals("XYZ", columnFamilies[2].getNameAsString());
- assertTrue(columnFamilies[2].isInMemory());
- assertEquals(1, columnFamilies[2].getScope());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnFailsForColumnFamilyNotPresentInAddCol() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName + " "
- +
- " (a_string varchar not null, col1 integer, CF1.col2 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) "+ generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
- try {
- conn.createStatement().execute(ddl);
- try {
- conn.createStatement().execute(
- "ALTER TABLE " + dataTableFullName
- + " ADD col4 integer CF1.REPLICATION_SCOPE=1, XYZ.IN_MEMORY=true ");
- fail();
- } catch(SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_SET_PROPERTY_FOR_COLUMN_NOT_ADDED.getErrorCode(), e.getErrorCode());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnForDifferentColumnFamilies() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName
- +
- " (a_string varchar not null, col1 integer, CF1.col2 integer, CF2.col3 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ' ");
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement()
- .execute(
- "ALTER TABLE "
- + dataTableFullName
- + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer, CF3.col7 integer CF1.REPLICATION_SCOPE=1, CF1.IN_MEMORY=false, IN_MEMORY=true ");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(4, columnFamilies.length);
- assertEquals("CF1", columnFamilies[0].getNameAsString());
- assertFalse(columnFamilies[0].isInMemory());
- assertEquals(1, columnFamilies[0].getScope());
- assertEquals("CF2", columnFamilies[1].getNameAsString());
- assertTrue(columnFamilies[1].isInMemory());
- assertEquals(0, columnFamilies[1].getScope());
- assertEquals("CF3", columnFamilies[2].getNameAsString());
- assertTrue(columnFamilies[2].isInMemory());
- assertEquals(0, columnFamilies[2].getScope());
- assertEquals("XYZ", columnFamilies[3].getNameAsString());
- assertTrue(columnFamilies[3].isInMemory());
- assertEquals(0, columnFamilies[3].getScope());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnUsingDefaultColumnFamilySpecifier() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String ddl = "CREATE TABLE " + dataTableFullName
- +
- " (a_string varchar not null, col1 integer, CF1.col2 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement().execute(
- "ALTER TABLE " + dataTableFullName + " ADD col4 integer XYZ.REPLICATION_SCOPE=1 ");
- conn.createStatement()
- .execute("ALTER TABLE " + dataTableFullName + " ADD XYZ.col5 integer IN_MEMORY=true ");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("CF1", columnFamilies[0].getNameAsString());
- assertFalse(columnFamilies[0].isInMemory());
- assertEquals(0, columnFamilies[0].getScope());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertTrue(columnFamilies[1].isInMemory());
- assertEquals(1, columnFamilies[1].getScope());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetPropertyAndAddColumnForDefaultColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- String ddl = "CREATE TABLE " + dataTableFullName +
- " (a_string varchar not null, col1 integer" +
- " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
- try {
- conn.createStatement().execute(ddl);
- conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " ADD col2 integer IN_MEMORY=true");
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
- .getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertTrue(columnFamilies[0].isInMemory());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testAddNewColumnFamilyProperties() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- try {
- conn.createStatement()
- .execute(
- "CREATE TABLE "
- + dataTableFullName
- + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer "
- + " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("immutable_rows=true , SALT_BUCKETS=3 "
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : "")));
-
- String ddl = "Alter table " + dataTableFullName + " add cf3.col5 integer, cf4.col6 integer in_memory=true";
- conn.createStatement().execute(ddl);
-
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- assertTrue(tableDesc.isCompactionEnabled());
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(5, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertFalse(columnFamilies[0].isInMemory());
- assertEquals("CF1", columnFamilies[1].getNameAsString());
- assertFalse(columnFamilies[1].isInMemory());
- assertEquals("CF2", columnFamilies[2].getNameAsString());
- assertFalse(columnFamilies[2].isInMemory());
- assertEquals("CF3", columnFamilies[3].getNameAsString());
- assertTrue(columnFamilies[3].isInMemory());
- assertEquals("CF4", columnFamilies[4].getNameAsString());
- assertTrue(columnFamilies[4].isInMemory());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testAddProperyToExistingColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- try {
- conn.createStatement()
- .execute(
- "CREATE TABLE "
- + dataTableFullName
- + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer "
- + " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("immutable_rows=true , SALT_BUCKETS=3 "
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : "")));
-
- String ddl = "Alter table " + dataTableFullName + " add cf1.col5 integer in_memory=true";
- conn.createStatement().execute(ddl);
-
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- assertTrue(tableDesc.isCompactionEnabled());
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(3, columnFamilies.length);
- assertEquals("0", columnFamilies[0].getNameAsString());
- assertFalse(columnFamilies[0].isInMemory());
- assertEquals("CF1", columnFamilies[1].getNameAsString());
- assertTrue(columnFamilies[1].isInMemory());
- assertEquals("CF2", columnFamilies[2].getNameAsString());
- assertFalse(columnFamilies[2].isInMemory());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testAddTTLToExistingColumnFamily() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- try {
- String ddl = "CREATE TABLE " + dataTableFullName
- + " (pk char(2) not null primary key, col1 integer, b.col1 integer) " + tableDDLOptions + " SPLIT ON ('EA','EZ') ";
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " add b.col2 varchar ttl=30";
- conn.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSettingTTLWhenAddingColumnNotAllowed() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- try {
- String ddl = "CREATE TABLE " + dataTableFullName
- + " (pk char(2) not null primary key) " + generateDDLOptions("TTL=100") + " SPLIT ON ('EA','EZ')";
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " add col1 varchar ttl=30";
- conn.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
- }
- try {
- String ddl = "ALTER TABLE " + dataTableFullName + " add col1 varchar a.ttl=30";
- conn.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(), e.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetTTLForTableWithOnlyPKCols() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
- conn.createStatement().execute(ddl);
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals("XYZ", columnFamilies[0].getNameAsString());
- assertEquals(86400, columnFamilies[0].getTimeToLive());
- }
- ddl = "ALTER TABLE " + dataTableFullName + " SET TTL=30";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals(30, columnFamilies[0].getTimeToLive());
- assertEquals("XYZ", columnFamilies[0].getNameAsString());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetHColumnPropertyForTableWithOnlyPKCols1() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET IN_MEMORY=true";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals("XYZ", columnFamilies[0].getNameAsString());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetHColumnPropertyForTableWithOnlyPKCols2() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4");
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " SET IN_MEMORY=true";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals("0", columnFamilies[0].getNameAsString());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetHColumnPropertyAndAddColumnForDefaultCFForTableWithOnlyPKCols() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " ADD COL3 INTEGER IN_MEMORY=true";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(1, columnFamilies.length);
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals("XYZ", columnFamilies[0].getNameAsString());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSetHColumnPropertyAndAddColumnForNewCFForTableWithOnlyPKCols() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER IN_MEMORY=true";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("NEWCF", columnFamilies[0].getNameAsString());
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertEquals(false, columnFamilies[1].isInMemory());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testTTLAssignmentForNewEmptyCF() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER IN_MEMORY=true";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("NEWCF", columnFamilies[0].getNameAsString());
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals(86400, columnFamilies[0].getTimeToLive());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertEquals(false, columnFamilies[1].isInMemory());
- assertEquals(86400, columnFamilies[1].getTimeToLive());
- }
-
- ddl = "ALTER TABLE " + dataTableFullName + " SET TTL=1000";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("NEWCF", columnFamilies[0].getNameAsString());
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals(1000, columnFamilies[0].getTimeToLive());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertEquals(false, columnFamilies[1].isInMemory());
- assertEquals(86400, columnFamilies[1].getTimeToLive());
- }
-
- // the new column will be assigned to the column family XYZ. With the a KV column getting added for XYZ,
- // the column family will start showing up in PTable.getColumnFamilies() after the column is added. Thus
- // being a new column family for the PTable, it will end up inheriting the TTL of the emptyCF (NEWCF).
- ddl = "ALTER TABLE " + dataTableFullName + " ADD COL3 INTEGER";
- conn.createStatement().execute(ddl);
- conn.commit();
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
- assertEquals(2, columnFamilies.length);
- assertEquals("NEWCF", columnFamilies[0].getNameAsString());
- assertEquals(true, columnFamilies[0].isInMemory());
- assertEquals(1000, columnFamilies[0].getTimeToLive());
- assertEquals("XYZ", columnFamilies[1].getNameAsString());
- assertEquals(false, columnFamilies[1].isInMemory());
- assertEquals(1000, columnFamilies[1].getTimeToLive());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSettingNotHColumnNorPhoenixPropertyEndsUpAsHTableProperty() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- String ddl = "create table " + dataTableFullName + " ("
- + " id char(1) NOT NULL,"
- + " col1 integer NOT NULL,"
- + " col2 bigint NOT NULL,"
- + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
- + " ) " + tableDDLOptions;
- conn.createStatement().execute(ddl);
- ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER NEWCF.UNKNOWN_PROP='ABC'";
- try {
- conn.createStatement().execute(ddl);
- fail();
- } catch (SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
- }
- ddl = "ALTER TABLE " + dataTableFullName + " SET UNKNOWN_PROP='ABC'";
- conn.createStatement().execute(ddl);
- try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
- HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
- assertEquals("ABC", tableDesc.getValue("UNKNOWN_PROP"));
- }
- } finally {
- conn.close();
- }
- }
@Test
public void testAlterStoreNulls() throws SQLException {
@@ -2534,46 +1344,5 @@ public class AlterTableIT extends ParallelStatsDisabledIT {
}
}
- @Test
- public void testAlterImmutableRowsPropertyForOneCellPerKeyValueColumnStorageScheme() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID)) " + tableDDLOptions;
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, false);
- ddl = "ALTER TABLE " + dataTableFullName + " SET IMMUTABLE_ROWS = true";
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, true);
- }
-
- @Test
- public void testAlterImmutableRowsPropertyForOneCellPerColumnFamilyStorageScheme() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
- +"ID VARCHAR(15) NOT NULL,\n"
- +"CREATED_DATE DATE,\n"
- +"CREATION_TIME BIGINT,\n"
- +"CONSTRAINT PK PRIMARY KEY (ID)) " + generateDDLOptions("COLUMN_ENCODED_BYTES=4, IMMUTABLE_ROWS=true"
- + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.createStatement().execute(ddl);
- assertImmutableRows(conn, dataTableFullName, true);
- try {
- ddl = "ALTER TABLE " + dataTableFullName + " SET IMMUTABLE_ROWS = false";
- conn.createStatement().execute(ddl);
- if (columnEncoded) {
- fail();
- }
- }
- catch(SQLException e) {
- assertEquals(SQLExceptionCode.CANNOT_ALTER_IMMUTABLE_ROWS_PROPERTY.getErrorCode(), e.getErrorCode());
- }
- assertImmutableRows(conn, dataTableFullName, columnEncoded);
- }
-
}
[24/25] phoenix git commit: PHOENIX-4250 Breakup AlterTableIT into
several integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/eafb58be/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyIT.java
new file mode 100644
index 0000000..7a7576d
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyIT.java
@@ -0,0 +1,1022 @@
+/*
+ * 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.end2end;
+
+import static org.apache.hadoop.hbase.HColumnDescriptor.DEFAULT_REPLICATION_SCOPE;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeepDeletedCells;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.exception.SQLExceptionCode;
+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.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public abstract class SetPropertyIT extends ParallelStatsDisabledIT {
+ private String schemaName;
+ private String dataTableName;
+ private String viewName;
+ private String dataTableFullName;
+ private String tableDDLOptions;
+ private final boolean columnEncoded;
+
+ public SetPropertyIT(boolean columnEncoded) {
+ this.columnEncoded = columnEncoded;
+ this.tableDDLOptions = columnEncoded ? "" : "COLUMN_ENCODED_BYTES=0";
+ }
+
+ @Before
+ public void setupTableNames() throws Exception {
+ schemaName = "";
+ dataTableName = generateUniqueName();
+ dataTableFullName = SchemaUtil.getTableName(schemaName, dataTableName);
+ viewName = generateUniqueName();
+ }
+
+ private String generateDDLOptions(String options) {
+ StringBuilder sb = new StringBuilder();
+ if (!options.isEmpty()) {
+ sb.append(options);
+ }
+ if (!tableDDLOptions.isEmpty()) {
+ if (sb.length()!=0)
+ sb.append(",");
+ sb.append(tableDDLOptions);
+ }
+ return sb.toString();
+ }
+
+ @Test
+ public void testSetHColumnProperties() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET REPLICATION_SCOPE=1";
+ conn1.createStatement().execute(ddl);
+ try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertEquals(1, columnFamilies[0].getScope());
+ }
+ }
+
+ @Test
+ public void testSetHTableProperties() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED=FALSE";
+ conn1.createStatement().execute(ddl);
+ try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ assertEquals(1, tableDesc.getColumnFamilies().length);
+ assertEquals("0", tableDesc.getColumnFamilies()[0].getNameAsString());
+ assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
+ }
+ }
+
+ @Test
+ public void testSetHTableAndHColumnProperties() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, REPLICATION_SCOPE = 1";
+ conn1.createStatement().execute(ddl);
+ try (HBaseAdmin admin = conn1.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertEquals(1, columnFamilies[0].getScope());
+ assertEquals(false, tableDesc.isCompactionEnabled());
+ }
+ }
+
+ @Test
+ public void testSetHTableHColumnAndPhoenixTableProperties() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CF1.CREATION_TIME BIGINT,\n"
+ +"CF2.LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("IMMUTABLE_ROWS=true"
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, true);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, VERSIONS = 10";
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET COMPACTION_ENABLED = FALSE, CF1.MIN_VERSIONS = 1, CF2.MIN_VERSIONS = 3, MIN_VERSIONS = 8, CF1.KEEP_DELETED_CELLS = true, KEEP_DELETED_CELLS = false";
+ conn.createStatement().execute(ddl);
+
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(3, columnFamilies.length);
+
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertEquals(8, columnFamilies[0].getMinVersions());
+ assertEquals(10, columnFamilies[0].getMaxVersions());
+ assertEquals(KeepDeletedCells.FALSE, columnFamilies[0].getKeepDeletedCells());
+
+ assertEquals("CF1", columnFamilies[1].getNameAsString());
+ assertEquals(1, columnFamilies[1].getMinVersions());
+ assertEquals(10, columnFamilies[1].getMaxVersions());
+ assertEquals(KeepDeletedCells.TRUE, columnFamilies[1].getKeepDeletedCells());
+
+ assertEquals("CF2", columnFamilies[2].getNameAsString());
+ assertEquals(3, columnFamilies[2].getMinVersions());
+ assertEquals(10, columnFamilies[2].getMaxVersions());
+ assertEquals(KeepDeletedCells.FALSE, columnFamilies[2].getKeepDeletedCells());
+
+ assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
+ }
+ }
+
+ @Test
+ public void testSpecifyingColumnFamilyForHTablePropertyFails() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET CF.COMPACTION_ENABLED = FALSE";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSpecifyingColumnFamilyForPhoenixTablePropertyFails() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET CF.DISABLE_WAL = TRUE";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_TABLE_PROPERTY.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSpecifyingColumnFamilyForTTLFails() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"CF.LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET CF.TTL = 86400";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSetPropertyNeedsColumnFamilyToExist() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET CF.REPLICATION_SCOPE = 1";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_FOUND.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSetDefaultColumnFamilyNotAllowed() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions(" SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET DEFAULT_COLUMN_FAMILY = 'A'";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.DEFAULT_COLUMN_FAMILY_ONLY_ON_CREATE_TABLE.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSetHColumnOrHTablePropertiesOnViewsNotAllowed() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ ddl = "CREATE VIEW " + viewName + " AS SELECT * FROM " + dataTableFullName + " WHERE CREATION_TIME = 1";
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER VIEW " + viewName + " SET REPLICATION_SCOPE = 1";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
+ }
+ ddl = "ALTER VIEW " + viewName + " SET COMPACTION_ENABLED = FALSE";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSetForSomePhoenixTablePropertiesOnViewsAllowed() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("SALT_BUCKETS = 8");
+ Connection conn1 = DriverManager.getConnection(getUrl(), props);
+ conn1.createStatement().execute(ddl);
+ String viewFullName = SchemaUtil.getTableName(schemaName, generateUniqueName());
+ ddl = "CREATE VIEW " + viewFullName + " AS SELECT * FROM " + dataTableFullName + " WHERE CREATION_TIME = 1";
+ conn1.createStatement().execute(ddl);
+ ddl = "ALTER VIEW " + viewFullName + " SET UPDATE_CACHE_FREQUENCY = 10";
+ conn1.createStatement().execute(ddl);
+ conn1.createStatement().execute("SELECT * FROM " + viewFullName);
+ PhoenixConnection pconn = conn1.unwrap(PhoenixConnection.class);
+ assertEquals(10, pconn.getTable(new PTableKey(pconn.getTenantId(), viewFullName)).getUpdateCacheFrequency());
+ ddl = "ALTER VIEW " + viewFullName + " SET UPDATE_CACHE_FREQUENCY = 20";
+ conn1.createStatement().execute(ddl);
+ conn1.createStatement().execute("SELECT * FROM " + viewFullName);
+ pconn = conn1.unwrap(PhoenixConnection.class);
+ assertEquals(20, pconn.getTable(new PTableKey(pconn.getTenantId(), viewFullName)).getUpdateCacheFrequency());
+ assertImmutableRows(conn1, viewFullName, false);
+ ddl = "ALTER VIEW " + viewFullName + " SET DISABLE_WAL = TRUE";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
+ }
+ ddl = "ALTER VIEW " + viewFullName + " SET THROW_INDEX_WRITE_FAILURE = FALSE";
+ try {
+ conn1.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.VIEW_WITH_PROPERTIES.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ @Test
+ public void testSettingPropertiesWhenTableHasDefaultColFamilySpecified() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID1 VARCHAR(15) NOT NULL,\n"
+ +"ID2 VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"CF.LAST_USED DATE,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID1, ID2)) " + generateDDLOptions("IMMUTABLE_ROWS=true, DEFAULT_COLUMN_FAMILY = 'XYZ'"
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, true);
+ ddl = "ALTER TABLE " + dataTableFullName
+ + " SET COMPACTION_ENABLED = FALSE, CF.REPLICATION_SCOPE=1, IMMUTABLE_ROWS = TRUE, TTL=1000";
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, true);
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("CF", columnFamilies[0].getNameAsString());
+ assertEquals(1, columnFamilies[0].getScope());
+ assertEquals(1000, columnFamilies[0].getTimeToLive());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertEquals(DEFAULT_REPLICATION_SCOPE, columnFamilies[1].getScope());
+ assertEquals(1000, columnFamilies[1].getTimeToLive());
+ assertEquals(Boolean.toString(false), tableDesc.getValue(HTableDescriptor.COMPACTION_ENABLED));
+ }
+ }
+
+ private static void assertImmutableRows(Connection conn, String fullTableName, boolean expectedValue) throws SQLException {
+ PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
+ assertEquals(expectedValue, pconn.getTable(new PTableKey(pconn.getTenantId(), fullTableName)).isImmutableRows());
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnForExistingColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName
+ +
+ " (a_string varchar not null, col1 integer, CF.col2 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute(
+ "ALTER TABLE " + dataTableFullName + " ADD CF.col3 integer CF.IN_MEMORY=true");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertFalse(columnFamilies[0].isInMemory());
+ assertEquals("CF", columnFamilies[1].getNameAsString());
+ assertTrue(columnFamilies[1].isInMemory());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnForNewAndExistingColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName + " "
+ +
+ " (a_string varchar not null, col1 integer, CF1.col2 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement()
+ .execute(
+ "ALTER TABLE "
+ + dataTableFullName
+ + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false ");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(3, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertTrue(columnFamilies[0].isInMemory());
+ assertEquals(0, columnFamilies[0].getScope());
+ assertEquals("CF1", columnFamilies[1].getNameAsString());
+ assertTrue(columnFamilies[1].isInMemory());
+ assertEquals(1, columnFamilies[1].getScope());
+ assertEquals("CF2", columnFamilies[2].getNameAsString());
+ assertFalse(columnFamilies[2].isInMemory());
+ assertEquals(0, columnFamilies[2].getScope());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnWhenTableHasExplicitDefaultColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName + " "
+ +
+ " (a_string varchar not null, col1 integer, CF1.col2 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement()
+ .execute(
+ "ALTER TABLE "
+ + dataTableFullName
+ + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer IN_MEMORY=true, CF1.REPLICATION_SCOPE=1, CF2.IN_MEMORY=false, XYZ.REPLICATION_SCOPE=1 ");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(3, columnFamilies.length);
+ assertEquals("CF1", columnFamilies[0].getNameAsString());
+ assertTrue(columnFamilies[0].isInMemory());
+ assertEquals(1, columnFamilies[0].getScope());
+ assertEquals("CF2", columnFamilies[1].getNameAsString());
+ assertFalse(columnFamilies[1].isInMemory());
+ assertEquals(0, columnFamilies[1].getScope());
+ assertEquals("XYZ", columnFamilies[2].getNameAsString());
+ assertTrue(columnFamilies[2].isInMemory());
+ assertEquals(1, columnFamilies[2].getScope());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnFailsForColumnFamilyNotPresentInAddCol() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName + " "
+ +
+ " (a_string varchar not null, col1 integer, CF1.col2 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) "+ generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
+ try {
+ conn.createStatement().execute(ddl);
+ try {
+ conn.createStatement().execute(
+ "ALTER TABLE " + dataTableFullName
+ + " ADD col4 integer CF1.REPLICATION_SCOPE=1, XYZ.IN_MEMORY=true ");
+ fail();
+ } catch(SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_SET_PROPERTY_FOR_COLUMN_NOT_ADDED.getErrorCode(), e.getErrorCode());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnForDifferentColumnFamilies() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName
+ +
+ " (a_string varchar not null, col1 integer, CF1.col2 integer, CF2.col3 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ' ");
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement()
+ .execute(
+ "ALTER TABLE "
+ + dataTableFullName
+ + " ADD col4 integer, CF1.col5 integer, CF2.col6 integer, CF3.col7 integer CF1.REPLICATION_SCOPE=1, CF1.IN_MEMORY=false, IN_MEMORY=true ");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(4, columnFamilies.length);
+ assertEquals("CF1", columnFamilies[0].getNameAsString());
+ assertFalse(columnFamilies[0].isInMemory());
+ assertEquals(1, columnFamilies[0].getScope());
+ assertEquals("CF2", columnFamilies[1].getNameAsString());
+ assertTrue(columnFamilies[1].isInMemory());
+ assertEquals(0, columnFamilies[1].getScope());
+ assertEquals("CF3", columnFamilies[2].getNameAsString());
+ assertTrue(columnFamilies[2].isInMemory());
+ assertEquals(0, columnFamilies[2].getScope());
+ assertEquals("XYZ", columnFamilies[3].getNameAsString());
+ assertTrue(columnFamilies[3].isInMemory());
+ assertEquals(0, columnFamilies[3].getScope());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnUsingDefaultColumnFamilySpecifier() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String ddl = "CREATE TABLE " + dataTableFullName
+ +
+ " (a_string varchar not null, col1 integer, CF1.col2 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("DEFAULT_COLUMN_FAMILY = 'XYZ'");
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute(
+ "ALTER TABLE " + dataTableFullName + " ADD col4 integer XYZ.REPLICATION_SCOPE=1 ");
+ conn.createStatement()
+ .execute("ALTER TABLE " + dataTableFullName + " ADD XYZ.col5 integer IN_MEMORY=true ");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("CF1", columnFamilies[0].getNameAsString());
+ assertFalse(columnFamilies[0].isInMemory());
+ assertEquals(0, columnFamilies[0].getScope());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertTrue(columnFamilies[1].isInMemory());
+ assertEquals(1, columnFamilies[1].getScope());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetPropertyAndAddColumnForDefaultColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ String ddl = "CREATE TABLE " + dataTableFullName +
+ " (a_string varchar not null, col1 integer" +
+ " CONSTRAINT pk PRIMARY KEY (a_string)) " + tableDDLOptions;
+ try {
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " ADD col2 integer IN_MEMORY=true");
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HColumnDescriptor[] columnFamilies = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName))
+ .getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertTrue(columnFamilies[0].isInMemory());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAddNewColumnFamilyProperties() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ try {
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE "
+ + dataTableFullName
+ + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer "
+ + " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("immutable_rows=true , SALT_BUCKETS=3 "
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : "")));
+
+ String ddl = "Alter table " + dataTableFullName + " add cf3.col5 integer, cf4.col6 integer in_memory=true";
+ conn.createStatement().execute(ddl);
+
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ assertTrue(tableDesc.isCompactionEnabled());
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(5, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertFalse(columnFamilies[0].isInMemory());
+ assertEquals("CF1", columnFamilies[1].getNameAsString());
+ assertFalse(columnFamilies[1].isInMemory());
+ assertEquals("CF2", columnFamilies[2].getNameAsString());
+ assertFalse(columnFamilies[2].isInMemory());
+ assertEquals("CF3", columnFamilies[3].getNameAsString());
+ assertTrue(columnFamilies[3].isInMemory());
+ assertEquals("CF4", columnFamilies[4].getNameAsString());
+ assertTrue(columnFamilies[4].isInMemory());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAddProperyToExistingColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ try {
+ conn.createStatement()
+ .execute(
+ "CREATE TABLE "
+ + dataTableFullName
+ + " (a_string varchar not null, col1 integer, cf1.col2 integer, col3 integer , cf2.col4 integer "
+ + " CONSTRAINT pk PRIMARY KEY (a_string)) " + generateDDLOptions("immutable_rows=true , SALT_BUCKETS=3 "
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : "")));
+
+ String ddl = "Alter table " + dataTableFullName + " add cf1.col5 integer in_memory=true";
+ conn.createStatement().execute(ddl);
+
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ assertTrue(tableDesc.isCompactionEnabled());
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(3, columnFamilies.length);
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ assertFalse(columnFamilies[0].isInMemory());
+ assertEquals("CF1", columnFamilies[1].getNameAsString());
+ assertTrue(columnFamilies[1].isInMemory());
+ assertEquals("CF2", columnFamilies[2].getNameAsString());
+ assertFalse(columnFamilies[2].isInMemory());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAddTTLToExistingColumnFamily() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ try {
+ String ddl = "CREATE TABLE " + dataTableFullName
+ + " (pk char(2) not null primary key, col1 integer, b.col1 integer) " + tableDDLOptions + " SPLIT ON ('EA','EZ') ";
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " add b.col2 varchar ttl=30";
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSettingTTLWhenAddingColumnNotAllowed() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ try {
+ String ddl = "CREATE TABLE " + dataTableFullName
+ + " (pk char(2) not null primary key) " + generateDDLOptions("TTL=100") + " SPLIT ON ('EA','EZ')";
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " add col1 varchar ttl=30";
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
+ }
+ try {
+ String ddl = "ALTER TABLE " + dataTableFullName + " add col1 varchar a.ttl=30";
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.COLUMN_FAMILY_NOT_ALLOWED_FOR_TTL.getErrorCode(), e.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetTTLForTableWithOnlyPKCols() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
+ conn.createStatement().execute(ddl);
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals("XYZ", columnFamilies[0].getNameAsString());
+ assertEquals(86400, columnFamilies[0].getTimeToLive());
+ }
+ ddl = "ALTER TABLE " + dataTableFullName + " SET TTL=30";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals(30, columnFamilies[0].getTimeToLive());
+ assertEquals("XYZ", columnFamilies[0].getNameAsString());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetHColumnPropertyForTableWithOnlyPKCols1() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET IN_MEMORY=true";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals("XYZ", columnFamilies[0].getNameAsString());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetHColumnPropertyForTableWithOnlyPKCols2() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4");
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET IN_MEMORY=true";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals("0", columnFamilies[0].getNameAsString());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetHColumnPropertyAndAddColumnForDefaultCFForTableWithOnlyPKCols() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " ADD COL3 INTEGER IN_MEMORY=true";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(1, columnFamilies.length);
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals("XYZ", columnFamilies[0].getNameAsString());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSetHColumnPropertyAndAddColumnForNewCFForTableWithOnlyPKCols() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER IN_MEMORY=true";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("NEWCF", columnFamilies[0].getNameAsString());
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertEquals(false, columnFamilies[1].isInMemory());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testTTLAssignmentForNewEmptyCF() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + generateDDLOptions("TTL=86400, SALT_BUCKETS = 4, DEFAULT_COLUMN_FAMILY='XYZ'");
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER IN_MEMORY=true";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("NEWCF", columnFamilies[0].getNameAsString());
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals(86400, columnFamilies[0].getTimeToLive());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertEquals(false, columnFamilies[1].isInMemory());
+ assertEquals(86400, columnFamilies[1].getTimeToLive());
+ }
+
+ ddl = "ALTER TABLE " + dataTableFullName + " SET TTL=1000";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("NEWCF", columnFamilies[0].getNameAsString());
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals(1000, columnFamilies[0].getTimeToLive());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertEquals(false, columnFamilies[1].isInMemory());
+ assertEquals(86400, columnFamilies[1].getTimeToLive());
+ }
+
+ // the new column will be assigned to the column family XYZ. With the a KV column getting added for XYZ,
+ // the column family will start showing up in PTable.getColumnFamilies() after the column is added. Thus
+ // being a new column family for the PTable, it will end up inheriting the TTL of the emptyCF (NEWCF).
+ ddl = "ALTER TABLE " + dataTableFullName + " ADD COL3 INTEGER";
+ conn.createStatement().execute(ddl);
+ conn.commit();
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ HColumnDescriptor[] columnFamilies = tableDesc.getColumnFamilies();
+ assertEquals(2, columnFamilies.length);
+ assertEquals("NEWCF", columnFamilies[0].getNameAsString());
+ assertEquals(true, columnFamilies[0].isInMemory());
+ assertEquals(1000, columnFamilies[0].getTimeToLive());
+ assertEquals("XYZ", columnFamilies[1].getNameAsString());
+ assertEquals(false, columnFamilies[1].isInMemory());
+ assertEquals(1000, columnFamilies[1].getTimeToLive());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSettingNotHColumnNorPhoenixPropertyEndsUpAsHTableProperty() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ String ddl = "create table " + dataTableFullName + " ("
+ + " id char(1) NOT NULL,"
+ + " col1 integer NOT NULL,"
+ + " col2 bigint NOT NULL,"
+ + " CONSTRAINT NAME_PK PRIMARY KEY (id, col1, col2)"
+ + " ) " + tableDDLOptions;
+ conn.createStatement().execute(ddl);
+ ddl = "ALTER TABLE " + dataTableFullName + " ADD NEWCF.COL3 INTEGER NEWCF.UNKNOWN_PROP='ABC'";
+ try {
+ conn.createStatement().execute(ddl);
+ fail();
+ } catch (SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_SET_TABLE_PROPERTY_ADD_COLUMN.getErrorCode(), e.getErrorCode());
+ }
+ ddl = "ALTER TABLE " + dataTableFullName + " SET UNKNOWN_PROP='ABC'";
+ conn.createStatement().execute(ddl);
+ try (HBaseAdmin admin = conn.unwrap(PhoenixConnection.class).getQueryServices().getAdmin()) {
+ HTableDescriptor tableDesc = admin.getTableDescriptor(Bytes.toBytes(dataTableFullName));
+ assertEquals("ABC", tableDesc.getValue("UNKNOWN_PROP"));
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAlterImmutableRowsPropertyForOneCellPerKeyValueColumnStorageScheme() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID)) " + tableDDLOptions;
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, false);
+ ddl = "ALTER TABLE " + dataTableFullName + " SET IMMUTABLE_ROWS = true";
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, true);
+ }
+
+ @Test
+ public void testAlterImmutableRowsPropertyForOneCellPerColumnFamilyStorageScheme() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String ddl = "CREATE TABLE " + dataTableFullName + " (\n"
+ +"ID VARCHAR(15) NOT NULL,\n"
+ +"CREATED_DATE DATE,\n"
+ +"CREATION_TIME BIGINT,\n"
+ +"CONSTRAINT PK PRIMARY KEY (ID)) " + generateDDLOptions("COLUMN_ENCODED_BYTES=4, IMMUTABLE_ROWS=true"
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.createStatement().execute(ddl);
+ assertImmutableRows(conn, dataTableFullName, true);
+ try {
+ ddl = "ALTER TABLE " + dataTableFullName + " SET IMMUTABLE_ROWS = false";
+ conn.createStatement().execute(ddl);
+ if (columnEncoded) {
+ fail();
+ }
+ }
+ catch(SQLException e) {
+ assertEquals(SQLExceptionCode.CANNOT_ALTER_IMMUTABLE_ROWS_PROPERTY.getErrorCode(), e.getErrorCode());
+ }
+ assertImmutableRows(conn, dataTableFullName, columnEncoded);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/eafb58be/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnEncodedTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnEncodedTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnEncodedTableIT.java
new file mode 100644
index 0000000..77b9b79
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnEncodedTableIT.java
@@ -0,0 +1,34 @@
+/*
+ * 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.end2end;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class SetPropertyOnEncodedTableIT extends SetPropertyIT {
+ public SetPropertyOnEncodedTableIT(boolean columnEncoded) {
+ super(columnEncoded);
+ }
+
+ @Parameters(name="SetPropertyOnEncodedTableIT") // name is used by failsafe as file name in reports
+ public static Collection<Boolean> data() {
+ return Arrays.asList( true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/eafb58be/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnNonEncodedTableIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnNonEncodedTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnNonEncodedTableIT.java
new file mode 100644
index 0000000..26626d5
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SetPropertyOnNonEncodedTableIT.java
@@ -0,0 +1,34 @@
+/*
+ * 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.end2end;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class SetPropertyOnNonEncodedTableIT extends SetPropertyIT {
+ public SetPropertyOnNonEncodedTableIT(boolean columnEncoded) {
+ super(columnEncoded);
+ }
+
+ @Parameters(name="SetPropertyOnNonEncodedTableIT") // name is used by failsafe as file name in reports
+ public static Collection<Boolean> data() {
+ return Arrays.asList( false );
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/eafb58be/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
index 659866b..61ec030 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
@@ -31,13 +31,27 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.ResultScanner;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.util.Bytes;
import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.util.IndexUtil;
import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.SchemaUtil;
import org.junit.Test;
public class IndexWithTableSchemaChangeIT extends ParallelStatsDisabledIT {
+ private void assertIndexExists(Connection conn, boolean exists, String schemaName, String dataTableName) throws SQLException {
+ ResultSet rs = conn.getMetaData().getIndexInfo(null, schemaName, dataTableName, false, false);
+ assertEquals(exists, rs.next());
+ }
+
@Test
public void testImmutableIndexDropIndexedColumn() throws Exception {
helpTestDropIndexedColumn(false, false);
@@ -372,4 +386,308 @@ public class IndexWithTableSchemaChangeIT extends ParallelStatsDisabledIT {
conn.close();
}
}
+
+ @Test
+ public void testDropIndexedColumnImmutableIndex() throws Exception {
+ helpTestDropIndexedEncodedColumn(true, false);
+ }
+
+ @Test
+ public void testDropIndexedColumnMutableIndex() throws Exception {
+ helpTestDropIndexedEncodedColumn(false, false);
+ }
+
+ @Test
+ public void testDropIndexedColumnImmutableEncodedIndex() throws Exception {
+ helpTestDropIndexedEncodedColumn(true, true);
+ }
+
+ @Test
+ public void testDropIndexedColumnMutableEncodedIndex() throws Exception {
+ helpTestDropIndexedEncodedColumn(false, true);
+ }
+
+ private void helpTestDropIndexedEncodedColumn(boolean immutable, boolean columnEncoded) throws Exception {
+ String query;
+ ResultSet rs;
+ PreparedStatement stmt;
+ String schemaName = "";
+ String dataTableName = generateUniqueName();
+ String indexTableName = "I_" + generateUniqueName();
+ String localIndexTableName = "LI_" + generateUniqueName();
+ String dataTableFullName = SchemaUtil.getTableName(schemaName, dataTableName);
+ String indexTableFullName = SchemaUtil.getTableName(schemaName, indexTableName);
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableFullName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) "
+ + (immutable ? "IMMUTABLE_ROWS = true" : "")
+ + (!columnEncoded ? ",IMMUTABLE_STORAGE_SCHEME=" + PTable.ImmutableStorageScheme.ONE_CELL_PER_COLUMN : ""));
+ query = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1, v2)");
+ conn.createStatement().execute(
+ "CREATE LOCAL INDEX " + localIndexTableName + " ON " + dataTableFullName + " (v1, v2)");
+
+ query = "SELECT * FROM " + indexTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn,true,schemaName,dataTableName);
+ conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " DROP COLUMN v1");
+ assertIndexExists(conn,false,schemaName,dataTableName);
+
+ query = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("1",rs.getString(2));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("2",rs.getString(2));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testDropCoveredColumn() throws Exception {
+ ResultSet rs;
+ PreparedStatement stmt;
+ String schemaName = "";
+ String dataTableName = generateUniqueName();
+ String indexTableName = "I_" + generateUniqueName();
+ String localIndexTableName = "LI_" + generateUniqueName();
+ String dataTableFullName = SchemaUtil.getTableName(schemaName, dataTableName);
+ String indexTableFullName = SchemaUtil.getTableName(schemaName, indexTableName);
+ String localIndexTableFullName = SchemaUtil.getTableName(schemaName, localIndexTableName);
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableFullName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR, v3 VARCHAR) ");
+ String dataTableQuery = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1) include (v2, v3)");
+ conn.createStatement().execute(
+ "CREATE LOCAL INDEX " + localIndexTableName + " ON " + dataTableFullName + " (v1) include (v2, v3)");
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertFalse(rs.next());
+ String indexTableQuery = "SELECT * FROM " + indexTableName;
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertFalse(rs.next());
+ String localIndexTableQuery = "SELECT * FROM " + localIndexTableFullName;
+ rs = conn.createStatement().executeQuery(localIndexTableQuery);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.setString(4, "j");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn,true,schemaName,dataTableName);
+ conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " DROP COLUMN v2");
+ assertIndexExists(conn,true,schemaName,dataTableName);
+
+ // verify data table rows
+ Scan scan = new Scan();
+ HTable table = (HTable) conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(dataTableFullName));
+ ResultScanner results = table.getScanner(scan);
+ for (Result res : results) {
+ assertNull("Column value was not deleted",res.getValue(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("V2")));
+ }
+ results.close();
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ scan = new Scan();
+ table = (HTable) conn.unwrap(PhoenixConnection.class).getQueryServices().getTable(Bytes.toBytes(indexTableFullName));
+ results = table.getScanner(scan);
+ for (Result res : results) {
+ assertNull("Column value was not deleted",res.getValue(QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES, Bytes.toBytes("0:V2")));
+ }
+ results.close();
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify local index table rows
+ rs = conn.createStatement().executeQuery(localIndexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "y");
+ stmt.setString(3, "k");
+ stmt.execute();
+ conn.commit();
+
+ // verify data table rows
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("y",rs.getString(2));
+ assertEquals("k",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("k",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify local index table rows
+ rs = conn.createStatement().executeQuery(localIndexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("k",rs.getString(3));
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testAddPKColumnToTableWithIndex() throws Exception {
+ String query;
+ ResultSet rs;
+ PreparedStatement stmt;
+ String schemaName = "";
+ String dataTableName = generateUniqueName();
+ String indexTableName = "I_" + generateUniqueName();
+ String localIndexTableName = "LI_" + generateUniqueName();
+ String dataTableFullName = SchemaUtil.getTableName(schemaName, dataTableName);
+ String indexTableFullName = SchemaUtil.getTableName(schemaName, indexTableName);
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableFullName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) ");
+ query = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE INDEX " + indexTableName + " ON " + dataTableFullName + " (v1) include (v2)");
+ query = "SELECT * FROM " + indexTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn,true,schemaName,dataTableName);
+ conn.createStatement().execute("ALTER TABLE " + dataTableFullName + " ADD v3 VARCHAR, k2 DECIMAL PRIMARY KEY, k3 DECIMAL PRIMARY KEY");
+ rs = conn.getMetaData().getPrimaryKeys("", schemaName, dataTableName);
+ assertTrue(rs.next());
+ assertEquals("K",rs.getString("COLUMN_NAME"));
+ assertEquals(1, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals("K2",rs.getString("COLUMN_NAME"));
+ assertEquals(2, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals("K3",rs.getString("COLUMN_NAME"));
+ assertEquals(3, rs.getShort("KEY_SEQ"));
+ assertFalse(rs.next());
+
+ rs = conn.getMetaData().getPrimaryKeys("", schemaName, indexTableName);
+ assertTrue(rs.next());
+ assertEquals(QueryConstants.DEFAULT_COLUMN_FAMILY + IndexUtil.INDEX_COLUMN_NAME_SEP + "V1",rs.getString("COLUMN_NAME"));
+ assertEquals(1, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K",rs.getString("COLUMN_NAME"));
+ assertEquals(2, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K2",rs.getString("COLUMN_NAME"));
+ assertEquals(3, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K3",rs.getString("COLUMN_NAME"));
+ assertEquals(4, rs.getShort("KEY_SEQ"));
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + dataTableFullName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("1",rs.getString(3));
+ assertNull(rs.getBigDecimal(4));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableFullName + "(K,K2,V1,V2,K3) VALUES(?,?,?,?,?)");
+ stmt.setString(1, "b");
+ stmt.setBigDecimal(2, BigDecimal.valueOf(2));
+ stmt.setString(3, "y");
+ stmt.setString(4, "2");
+ stmt.setBigDecimal(5, BigDecimal.valueOf(3));
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT k,k2,k3 FROM " + dataTableFullName + " WHERE v1='y'";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertEquals(BigDecimal.valueOf(2),rs.getBigDecimal(2));
+ assertEquals(BigDecimal.valueOf(3),rs.getBigDecimal(3));
+ assertFalse(rs.next());
+ }
}
[11/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinLocalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinLocalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinLocalIndexIT.java
deleted file mode 100644
index ec05149..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinLocalIndexIT.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-
-@RunWith(Parameterized.class)
-public class HashJoinLocalIndexIT extends BaseJoinIT {
-
- public HashJoinLocalIndexIT(String[] indexDDL, String[] plans) {
- super(indexDDL, plans);
- }
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,'S1']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"S.:supplier_id\" IN (\"I.supplier_id\")",
-
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,'S1']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"S.PHONE\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"S.:supplier_id\" IN (\"I.supplier_id\")",
-
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,*] - [1,'S3']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO SINGLE ROW\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- }});
- return testCases;
- }
-
-
- @Test
- public void testJoinWithLocalIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- String query = "select phone, i.name from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" where s.name = 'S1' and i.name < 'T6'";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "888-888-1111");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "888-888-1111");
- assertFalse(rs.next());
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[0], QueryUtil.getExplainPlan(rs));
-
- query = "select phone, max(i.name) from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" where s.name = 'S1' and i.name < 'T6' group by phone";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "888-888-1111");
- assertEquals(rs.getString(2), "T2");
- assertFalse(rs.next());
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[1], QueryUtil.getExplainPlan(rs));
-
- query = "select max(phone), max(i.name) from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s left join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" and i.name < 'T6' where s.name <= 'S3'";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "888-888-3333");
- assertEquals(rs.getString(2), "T4");
- assertFalse(rs.next());
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[2], QueryUtil.getExplainPlan(rs));
- } finally {
- conn.close();
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinMoreIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinMoreIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinMoreIT.java
deleted file mode 100644
index c76eb67..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinMoreIT.java
+++ /dev/null
@@ -1,909 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Array;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.util.Properties;
-
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.junit.Test;
-
-public class HashJoinMoreIT extends ParallelStatsDisabledIT {
- private final String[] plans = new String[] {
- /*
- * testJoinWithKeyRangeOptimization()
- * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
- * FROM TEMP_TABLE_COMPOSITE_PK lhs
- * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col1 = rhs.col2
- */
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithKeyRangeOptimization()
- * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
- * FROM TEMP_TABLE_COMPOSITE_PK lhs
- * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col2
- */
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY LHS.COL0 IN (RHS.COL2)",
- /*
- * testJoinWithKeyRangeOptimization()
- * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
- * FROM TEMP_TABLE_COMPOSITE_PK lhs
- * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col1 AND lhs.col1 = rhs.col2
- */
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY (LHS.COL0, LHS.COL1) IN ((RHS.COL1, RHS.COL2))",
- /*
- * testJoinWithKeyRangeOptimization()
- * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
- * FROM TEMP_TABLE_COMPOSITE_PK lhs
- * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col1 AND lhs.col2 = rhs.col3 - 1 AND lhs.col1 = rhs.col2
- */
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY (LHS.COL0, LHS.COL1, LHS.COL2) IN ((RHS.COL1, RHS.COL2, TO_INTEGER((RHS.COL3 - 1))))",
- };
-
- @Test
- public void testJoinOverSaltedTables() throws Exception {
- String tempTableNoSalting = generateUniqueName();
- String tempTableWithSalting = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- conn.createStatement().execute("CREATE TABLE " + tempTableNoSalting
- + " (mypk INTEGER NOT NULL PRIMARY KEY, "
- + " col1 INTEGER)");
- conn.createStatement().execute("CREATE TABLE " + tempTableWithSalting
- + " (mypk INTEGER NOT NULL PRIMARY KEY, "
- + " col1 INTEGER) SALT_BUCKETS=4");
-
- PreparedStatement upsertStmt = conn.prepareStatement(
- "upsert into " + tempTableNoSalting + "(mypk, col1) " + "values (?, ?)");
- for (int i = 0; i < 3; i++) {
- upsertStmt.setInt(1, i + 1);
- upsertStmt.setInt(2, 3 - i);
- upsertStmt.execute();
- }
- conn.commit();
-
- upsertStmt = conn.prepareStatement(
- "upsert into " + tempTableWithSalting + "(mypk, col1) " + "values (?, ?)");
- for (int i = 0; i < 6; i++) {
- upsertStmt.setInt(1, i + 1);
- upsertStmt.setInt(2, 3 - (i % 3));
- upsertStmt.execute();
- }
- conn.commit();
-
- // LHS=unsalted JOIN RHS=salted
- String query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
- + tempTableNoSalting + " lhs JOIN "
- + tempTableWithSalting + " rhs ON rhs.mypk = lhs.col1";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 1);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 3);
- assertEquals(rs.getInt(4), 1);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 2);
- assertEquals(rs.getInt(3), 2);
- assertEquals(rs.getInt(4), 2);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 1);
- assertEquals(rs.getInt(3), 1);
- assertEquals(rs.getInt(4), 3);
-
- assertFalse(rs.next());
-
- // LHS=salted JOIN RHS=salted
- query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
- + tempTableWithSalting + " lhs JOIN "
- + tempTableNoSalting + " rhs ON rhs.mypk = lhs.col1";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 1);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 3);
- assertEquals(rs.getInt(4), 1);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 2);
- assertEquals(rs.getInt(3), 2);
- assertEquals(rs.getInt(4), 2);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 1);
- assertEquals(rs.getInt(3), 1);
- assertEquals(rs.getInt(4), 3);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 4);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 3);
- assertEquals(rs.getInt(4), 1);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 5);
- assertEquals(rs.getInt(2), 2);
- assertEquals(rs.getInt(3), 2);
- assertEquals(rs.getInt(4), 2);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 6);
- assertEquals(rs.getInt(2), 1);
- assertEquals(rs.getInt(3), 1);
- assertEquals(rs.getInt(4), 3);
-
- assertFalse(rs.next());
-
- // LHS=salted JOIN RHS=salted
- query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
- + tempTableWithSalting + " lhs JOIN "
- + tempTableWithSalting + " rhs ON rhs.mypk = (lhs.col1 + 3)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 1);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 6);
- assertEquals(rs.getInt(4), 1);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 2);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 2);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 1);
- assertEquals(rs.getInt(3), 4);
- assertEquals(rs.getInt(4), 3);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 4);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 6);
- assertEquals(rs.getInt(4), 1);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 5);
- assertEquals(rs.getInt(2), 2);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 2);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 6);
- assertEquals(rs.getInt(2), 1);
- assertEquals(rs.getInt(3), 4);
- assertEquals(rs.getInt(4), 3);
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinOnDynamicColumns() throws Exception {
- String tableA = generateUniqueName();
- String tableB = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = null;
- PreparedStatement stmt = null;
- try {
- conn = DriverManager.getConnection(getUrl(), props);
- String ddlA = "CREATE TABLE " + tableA + " (pkA INTEGER NOT NULL, " + " colA1 INTEGER, "
- + " colA2 VARCHAR " + "CONSTRAINT PK PRIMARY KEY" + "(pkA)" + ")";
-
- String ddlB = "CREATE TABLE " + tableB + " (pkB INTEGER NOT NULL PRIMARY KEY, " + " colB INTEGER)";
- conn.createStatement().execute(ddlA);
- conn.createStatement().execute(ddlB);
-
- String upsertA = "UPSERT INTO " + tableA + " (pkA, colA1, colA2) VALUES(?, ?, ?)";
- stmt = conn.prepareStatement(upsertA);
- int i = 0;
- for (i = 0; i < 5; i++) {
- stmt.setInt(1, i);
- stmt.setInt(2, i + 10);
- stmt.setString(3, "00" + i);
- stmt.executeUpdate();
- }
- conn.commit();
- stmt.close();
-
- String sequenceB = generateUniqueName();
- // upsert select dynamic columns in tableB
- conn.createStatement().execute("CREATE SEQUENCE " + sequenceB );
- String upsertBSelectA = "UPSERT INTO " + tableB + " (pkB, pkA INTEGER)"
- + "SELECT NEXT VALUE FOR " + sequenceB + ", pkA FROM " + tableA ;
- stmt = conn.prepareStatement(upsertBSelectA);
- stmt.executeUpdate();
- stmt.close();
- conn.commit();
- conn.createStatement().execute("DROP SEQUENCE " + sequenceB );
-
- // perform a join between tableB and tableA by joining on the dynamic column that we upserted in
- // tableB. This join should return all the rows from table A.
- String joinSql = "SELECT A.pkA, A.COLA1, A.colA2 FROM " + tableB + " B(pkA INTEGER) JOIN " + tableA + " A ON a.pkA = b.pkA";
- stmt = conn.prepareStatement(joinSql);
- ResultSet rs = stmt.executeQuery();
- i = 0;
- while (rs.next()) {
- // check that we get back all the rows that we upserted for tableA above.
- assertEquals(rs.getInt(1), i);
- assertEquals(rs.getInt(2), i + 10);
- assertEquals(rs.getString(3), "00" + i);
- i++;
- }
- assertEquals(5,i);
- } finally {
- if (stmt != null) {
- stmt.close();
- }
- if (conn != null) {
- conn.close();
- }
-
- }
-
- }
-
- @Test
- public void testJoinWithKeyRangeOptimization() throws Exception {
- String tempTableWithCompositePK = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- conn.createStatement().execute("CREATE TABLE " + tempTableWithCompositePK
- + " (col0 INTEGER NOT NULL, "
- + " col1 INTEGER NOT NULL, "
- + " col2 INTEGER NOT NULL, "
- + " col3 INTEGER "
- + " CONSTRAINT pk PRIMARY KEY (col0, col1, col2)) "
- + " SALT_BUCKETS=4");
-
- PreparedStatement upsertStmt = conn.prepareStatement(
- "upsert into " + tempTableWithCompositePK + "(col0, col1, col2, col3) " + "values (?, ?, ?, ?)");
- for (int i = 0; i < 3; i++) {
- upsertStmt.setInt(1, i + 1);
- upsertStmt.setInt(2, i + 2);
- upsertStmt.setInt(3, i + 3);
- upsertStmt.setInt(4, i + 5);
- upsertStmt.execute();
- }
- conn.commit();
-
- // No leading part of PK
- String query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
- + tempTableWithCompositePK + " lhs JOIN "
- + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 4);
- assertEquals(rs.getInt(4), 6);
- assertEquals(rs.getInt(5), 1);
- assertEquals(rs.getInt(6), 2);
- assertEquals(rs.getInt(7), 3);
- assertEquals(rs.getInt(8), 5);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 4);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 7);
- assertEquals(rs.getInt(5), 2);
- assertEquals(rs.getInt(6), 3);
- assertEquals(rs.getInt(7), 4);
- assertEquals(rs.getInt(8), 6);
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertEquals(String.format(plans[0],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
-
- // Two parts of PK but only one leading part
- query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
- + tempTableWithCompositePK + " lhs JOIN "
- + tempTableWithCompositePK + " rhs ON lhs.col2 = rhs.col3 AND lhs.col0 = rhs.col2";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 4);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 7);
- assertEquals(rs.getInt(5), 1);
- assertEquals(rs.getInt(6), 2);
- assertEquals(rs.getInt(7), 3);
- assertEquals(rs.getInt(8), 5);
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertEquals(String.format(plans[1],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
-
- // Two leading parts of PK
- query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
- + tempTableWithCompositePK + " lhs JOIN "
- + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2 AND lhs.col0 = rhs.col1";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 4);
- assertEquals(rs.getInt(4), 6);
- assertEquals(rs.getInt(5), 1);
- assertEquals(rs.getInt(6), 2);
- assertEquals(rs.getInt(7), 3);
- assertEquals(rs.getInt(8), 5);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 4);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 7);
- assertEquals(rs.getInt(5), 2);
- assertEquals(rs.getInt(6), 3);
- assertEquals(rs.getInt(7), 4);
- assertEquals(rs.getInt(8), 6);
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertEquals(String.format(plans[2],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
-
- // All parts of PK
- query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
- + tempTableWithCompositePK + " lhs JOIN "
- + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2 AND lhs.col2 = rhs.col3 - 1 AND lhs.col0 = rhs.col1";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 2);
- assertEquals(rs.getInt(2), 3);
- assertEquals(rs.getInt(3), 4);
- assertEquals(rs.getInt(4), 6);
- assertEquals(rs.getInt(5), 1);
- assertEquals(rs.getInt(6), 2);
- assertEquals(rs.getInt(7), 3);
- assertEquals(rs.getInt(8), 5);
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 3);
- assertEquals(rs.getInt(2), 4);
- assertEquals(rs.getInt(3), 5);
- assertEquals(rs.getInt(4), 7);
- assertEquals(rs.getInt(5), 2);
- assertEquals(rs.getInt(6), 3);
- assertEquals(rs.getInt(7), 4);
- assertEquals(rs.getInt(8), 6);
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertEquals(String.format(plans[3],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSubqueryWithoutData() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(false);
-
- try {
- String GRAMMAR_TABLE = "CREATE TABLE IF NOT EXISTS GRAMMAR_TABLE (ID INTEGER PRIMARY KEY, " +
- "unsig_id UNSIGNED_INT, big_id BIGINT, unsig_long_id UNSIGNED_LONG, tiny_id TINYINT," +
- "unsig_tiny_id UNSIGNED_TINYINT, small_id SMALLINT, unsig_small_id UNSIGNED_SMALLINT," +
- "float_id FLOAT, unsig_float_id UNSIGNED_FLOAT, double_id DOUBLE, unsig_double_id UNSIGNED_DOUBLE," +
- "decimal_id DECIMAL, boolean_id BOOLEAN, time_id TIME, date_id DATE, timestamp_id TIMESTAMP," +
- "unsig_time_id TIME, unsig_date_id DATE, unsig_timestamp_id TIMESTAMP, varchar_id VARCHAR (30)," +
- "char_id CHAR (30), binary_id BINARY (100), varbinary_id VARBINARY (100))";
-
- String LARGE_TABLE = "CREATE TABLE IF NOT EXISTS LARGE_TABLE (ID INTEGER PRIMARY KEY, " +
- "unsig_id UNSIGNED_INT, big_id BIGINT, unsig_long_id UNSIGNED_LONG, tiny_id TINYINT," +
- "unsig_tiny_id UNSIGNED_TINYINT, small_id SMALLINT, unsig_small_id UNSIGNED_SMALLINT," +
- "float_id FLOAT, unsig_float_id UNSIGNED_FLOAT, double_id DOUBLE, unsig_double_id UNSIGNED_DOUBLE," +
- "decimal_id DECIMAL, boolean_id BOOLEAN, time_id TIME, date_id DATE, timestamp_id TIMESTAMP," +
- "unsig_time_id TIME, unsig_date_id DATE, unsig_timestamp_id TIMESTAMP, varchar_id VARCHAR (30)," +
- "char_id CHAR (30), binary_id BINARY (100), varbinary_id VARBINARY (100))";
-
- String SECONDARY_LARGE_TABLE = "CREATE TABLE IF NOT EXISTS SECONDARY_LARGE_TABLE (SEC_ID INTEGER PRIMARY KEY," +
- "sec_unsig_id UNSIGNED_INT, sec_big_id BIGINT, sec_usnig_long_id UNSIGNED_LONG, sec_tiny_id TINYINT," +
- "sec_unsig_tiny_id UNSIGNED_TINYINT, sec_small_id SMALLINT, sec_unsig_small_id UNSIGNED_SMALLINT," +
- "sec_float_id FLOAT, sec_unsig_float_id UNSIGNED_FLOAT, sec_double_id DOUBLE, sec_unsig_double_id UNSIGNED_DOUBLE," +
- "sec_decimal_id DECIMAL, sec_boolean_id BOOLEAN, sec_time_id TIME, sec_date_id DATE," +
- "sec_timestamp_id TIMESTAMP, sec_unsig_time_id TIME, sec_unsig_date_id DATE, sec_unsig_timestamp_id TIMESTAMP," +
- "sec_varchar_id VARCHAR (30), sec_char_id CHAR (30), sec_binary_id BINARY (100), sec_varbinary_id VARBINARY (100))";
- createTestTable(getUrl(), GRAMMAR_TABLE);
- createTestTable(getUrl(), LARGE_TABLE);
- createTestTable(getUrl(), SECONDARY_LARGE_TABLE);
-
- String ddl = "SELECT * FROM (SELECT ID, BIG_ID, DATE_ID FROM LARGE_TABLE AS A WHERE (A.ID % 5) = 0) AS A " +
- "INNER JOIN (SELECT SEC_ID, SEC_TINY_ID, SEC_UNSIG_FLOAT_ID FROM SECONDARY_LARGE_TABLE AS B WHERE (B.SEC_ID % 5) = 0) AS B " +
- "ON A.ID=B.SEC_ID WHERE A.DATE_ID > ALL (SELECT SEC_DATE_ID FROM SECONDARY_LARGE_TABLE LIMIT 100) " +
- "AND B.SEC_UNSIG_FLOAT_ID = ANY (SELECT sec_unsig_float_id FROM SECONDARY_LARGE_TABLE " +
- "WHERE SEC_ID > ALL (SELECT MIN (ID) FROM GRAMMAR_TABLE WHERE UNSIG_ID IS NULL) AND " +
- "SEC_UNSIG_ID < ANY (SELECT DISTINCT(UNSIG_ID) FROM LARGE_TABLE WHERE UNSIG_ID<2500) LIMIT 1000) " +
- "AND A.ID < 10000";
- ResultSet rs = conn.createStatement().executeQuery(ddl);
- assertFalse(rs.next());
- } finally {
- Statement statement = conn.createStatement();
- String query = "drop table GRAMMAR_TABLE";
- statement.executeUpdate(query);
- query = "drop table LARGE_TABLE";
- statement.executeUpdate(query);
- query = "drop table SECONDARY_LARGE_TABLE";
- statement.executeUpdate(query);
- conn.close();
- }
- }
-
- // PHOENIX-2381
- @Test
- public void testJoinWithMultiTenancy() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- conn.createStatement().execute("CREATE TABLE INVENTORY (" +
- " TENANTID UNSIGNED_INT NOT NULL" +
- ",ID UNSIGNED_INT NOT NULL" +
- ",FOO UNSIGNED_INT NOT NULL" +
- ",\"TIMESTAMP\" UNSIGNED_LONG NOT NULL" +
- ",CODES INTEGER ARRAY[] NOT NULL" +
- ",V UNSIGNED_LONG" +
- " CONSTRAINT pk PRIMARY KEY (TENANTID, ID, FOO, \"TIMESTAMP\" , CODES))" +
- " DEFAULT_COLUMN_FAMILY ='E'," +
- " MULTI_TENANT=true");
- PreparedStatement upsertStmt = conn.prepareStatement(
- "upsert into INVENTORY "
- + "(tenantid, id, foo, \"TIMESTAMP\" , codes) "
- + "values (?, ?, ?, ?, ?)");
- upsertStmt.setInt(1, 15);
- upsertStmt.setInt(2, 5);
- upsertStmt.setInt(3, 0);
- upsertStmt.setLong(4, 6);
- Array array = conn.createArrayOf("INTEGER", new Object[] {1, 2});
- upsertStmt.setArray(5, array);
- upsertStmt.executeUpdate();
- conn.commit();
-
- conn.createStatement().execute("CREATE TABLE PRODUCT_IDS (" +
- " PRODUCT_ID UNSIGNED_INT NOT NULL" +
- ",PRODUCT_NAME VARCHAR" +
- " CONSTRAINT pk PRIMARY KEY (PRODUCT_ID))" +
- " DEFAULT_COLUMN_FAMILY ='NAME'");
- upsertStmt = conn.prepareStatement(
- "upsert into PRODUCT_IDS "
- + "(product_id, product_name) "
- + "values (?, ?)");
- upsertStmt.setInt(1, 5);
- upsertStmt.setString(2, "DUMMY");
- upsertStmt.executeUpdate();
- conn.commit();
- conn.close();
-
- // Create a tenant-specific connection.
- props.setProperty("TenantId", "15");
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs = conn.createStatement().executeQuery(
- "SELECT * FROM INVENTORY INNER JOIN PRODUCT_IDS ON (PRODUCT_ID = INVENTORY.ID)");
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 5);
- assertFalse(rs.next());
- rs.close();
- rs = conn.createStatement().executeQuery(
- "SELECT * FROM INVENTORY RIGHT JOIN PRODUCT_IDS ON (PRODUCT_ID = INVENTORY.ID)");
- assertTrue(rs.next());
- assertEquals(rs.getInt(1), 5);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testBug2480() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- try {
- conn.createStatement().execute(
- "CREATE TABLE master_businessunit ("
- + "code varchar(255) PRIMARY KEY, name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE master_company ("
- + "code varchar(255) PRIMARY KEY, name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE master_costcenter ("
- + "code varchar(255) PRIMARY KEY, name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE master_location ("
- + "code varchar(255) PRIMARY KEY, name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE master_product ("
- + "id integer PRIMARY KEY, product_name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE master_purchaseorder ("
- + "purchaseOrderNumber varchar(255), "
- + "companyCode varchar(255), "
- + "businessUnitCode varchar(255), "
- + "locationCode varchar(255), "
- + "purchaseOrderId varchar(255) PRIMARY KEY, "
- + "releasedOn date, name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE trans_purchaseorderitem ("
- + "purchaseOrderItemId varchar(255) PRIMARY KEY, "
- + "purchaseOrderId varchar(255), "
- + "lineNo varchar(255), name varchar(255))");
- conn.createStatement().execute(
- "CREATE TABLE trans_purchaseorderitem_costing ("
- + "purchaseorderItem_costing_id varchar(255) primary key, "
- + "purchaseorderItemId varchar(255), "
- + "purchaseorderId varchar(255), "
- + "costcenterCode varchar(255))");
-
- conn.createStatement().execute("upsert into master_businessunit(code,name) values ('1','BU1')");
- conn.createStatement().execute("upsert into master_businessunit(code,name) values ('2','BU2')");
- conn.createStatement().execute("upsert into master_company(code,name) values ('1','Company1')");
- conn.createStatement().execute("upsert into master_company(code,name) values ('2','Company2')");
- conn.createStatement().execute("upsert into master_costcenter(code,name) values ('1','CC1')");
- conn.createStatement().execute("upsert into master_costcenter(code,name) values ('2','CC2')");
- conn.createStatement().execute("upsert into master_location(code,name) values ('1','Location1')");
- conn.createStatement().execute("upsert into master_location(code,name) values ('2','Location2')");
- conn.createStatement().execute("upsert into master_product(id,product_name) values (1,'ProductName1')");
- conn.createStatement().execute("upsert into master_product(id,product_name) values (2,'Product2')");
- conn.createStatement().execute("upsert into master_purchaseorder(purchaseOrderNumber,companyCode,businessUnitCode,locationCode,purchaseOrderId,releasedOn,name) values ('1','1','1','1','1','2015-12-01','1')");
- conn.createStatement().execute("upsert into master_purchaseorder(purchaseOrderNumber,companyCode,businessUnitCode,locationCode,purchaseOrderId,releasedOn,name) values ('2','2','2','2','2','2015-12-02','2')");
- conn.createStatement().execute("upsert into trans_purchaseorderitem(purchaseOrderItemId,purchaseOrderId,lineNo,name) values ('1','1','1','1')");
- conn.createStatement().execute("upsert into trans_purchaseorderitem(purchaseOrderItemId,purchaseOrderId,lineNo,name) values ('2','2','2','2')");
- conn.createStatement().execute("upsert into trans_purchaseorderitem_costing(purchaseorderItem_costing_id,purchaseorderItemId,purchaseorderId,costcenterCode) values ('1','1','1','1')");
- conn.createStatement().execute("upsert into trans_purchaseorderitem_costing(purchaseorderItem_costing_id,purchaseorderItemId,purchaseorderId,costcenterCode) values ('2','2','2','2')");
-
- ResultSet rs = conn.createStatement().executeQuery(
- "SELECT DISTINCT "
- + "COALESCE( a1.name, 'N.A.'), "
- + "COALESCE( a2.name, 'N.A.'), "
- + "COALESCE( a3.name, 'N.A.'), "
- + "COALESCE( a4.purchaseOrderNumber, 'N.A.'), "
- + "COALESCE( a1.name, 'N.A.'), "
- + "COALESCE( a4.name, 'N.A.'), "
- + "COALESCE( a5.lineNo, 'N.A.'), "
- + "COALESCE( a5.name, 'N.A.'), "
- + "COALESCE( a7.name,'N.A.') "
- + "FROM (master_purchaseorder a4 "
- + "LEFT OUTER JOIN master_company a1 "
- + "ON a4.companyCode = a1.code "
- + "LEFT OUTER JOIN master_businessunit a2 "
- + "ON a4.businessUnitCode = a2.code "
- + "LEFT OUTER JOIN master_location a3 "
- + "ON a4.locationCode = a3.code "
- + "LEFT OUTER JOIN trans_purchaseorderitem a5 "
- + "ON a5.purchaseOrderId = a4.purchaseOrderId "
- + "LEFT OUTER JOIN trans_purchaseorderitem_costing a6 "
- + "ON a6.purchaseOrderItemId = a5.purchaseOrderItemId "
- + "AND a6.purchaseOrderId = a5.purchaseOrderId "
- + "LEFT OUTER JOIN master_costcenter a7 "
- + "ON a6.costCenterCode = a7.code)");
-
- assertTrue(rs.next());
- assertEquals("Company1", rs.getString(1));
- assertEquals("BU1", rs.getString(2));
- assertEquals("Location1", rs.getString(3));
- assertEquals("1", rs.getString(4));
- assertEquals("Company1", rs.getString(5));
- assertEquals("1", rs.getString(6));
- assertEquals("1", rs.getString(7));
- assertEquals("1", rs.getString(8));
- assertEquals("CC1", rs.getString(9));
- assertTrue(rs.next());
- assertEquals("Company2", rs.getString(1));
- assertEquals("BU2", rs.getString(2));
- assertEquals("Location2", rs.getString(3));
- assertEquals("2", rs.getString(4));
- assertEquals("Company2", rs.getString(5));
- assertEquals("2", rs.getString(6));
- assertEquals("2", rs.getString(7));
- assertEquals("2", rs.getString(8));
- assertEquals("CC2", rs.getString(9));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testBug2894() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- try {
- conn.createStatement().execute(
- "CREATE TABLE IF NOT EXISTS EVENT_COUNT (\n" +
- " BUCKET VARCHAR,\n" +
- " TIMESTAMP_DATE TIMESTAMP,\n" +
- " \"TIMESTAMP\" UNSIGNED_LONG NOT NULL,\n" +
- " LOCATION VARCHAR,\n" +
- " A VARCHAR,\n" +
- " B VARCHAR,\n" +
- " C VARCHAR,\n" +
- " D UNSIGNED_LONG,\n" +
- " E FLOAT\n" +
- " CONSTRAINT pk PRIMARY KEY (BUCKET, \"TIMESTAMP\" DESC, LOCATION, A, B, C)\n" +
- ") SALT_BUCKETS=2, COMPRESSION='GZ', TTL=31622400");
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO EVENT_COUNT(BUCKET, \"TIMESTAMP\", LOCATION, A, B, C) VALUES(?,?,?,?,?,?)");
- stmt.setString(1, "5SEC");
- stmt.setString(3, "Tr/Bal");
- stmt.setString(4, "A1");
- stmt.setString(5, "B1");
- stmt.setString(6, "C1");
- stmt.setLong(2, 1462993520000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993515000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993510000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993505000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993500000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993495000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993490000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993485000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993480000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993475000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993470000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993465000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993460000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993455000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993450000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993445000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993440000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993430000000000L);
- stmt.execute();
-
- // We'll test the original version of the user table as well as a slightly modified
- // version, in order to verify that hash join works for columns both having DESC
- // sort order as well as one having ASC order and the other having DESC order.
- String[] t = new String[] {"EVENT_LATENCY", "EVENT_LATENCY_2"};
- for (int i = 0; i < 2; i++) {
- conn.createStatement().execute(
- "CREATE TABLE IF NOT EXISTS " + t[i] + " (\n" +
- " BUCKET VARCHAR,\n" +
- " TIMESTAMP_DATE TIMESTAMP,\n" +
- " \"TIMESTAMP\" UNSIGNED_LONG NOT NULL,\n" +
- " SRC_LOCATION VARCHAR,\n" +
- " DST_LOCATION VARCHAR,\n" +
- " B VARCHAR,\n" +
- " C VARCHAR,\n" +
- " F UNSIGNED_LONG,\n" +
- " G UNSIGNED_LONG,\n" +
- " H UNSIGNED_LONG,\n" +
- " I UNSIGNED_LONG\n" +
- " CONSTRAINT pk PRIMARY KEY (BUCKET, \"TIMESTAMP\"" + (i == 0 ? " DESC" : "") + ", SRC_LOCATION, DST_LOCATION, B, C)\n" +
- ") SALT_BUCKETS=2, COMPRESSION='GZ', TTL=31622400");
- stmt = conn.prepareStatement("UPSERT INTO " + t[i] + "(BUCKET, \"TIMESTAMP\", SRC_LOCATION, DST_LOCATION, B, C) VALUES(?,?,?,?,?,?)");
- stmt.setString(1, "5SEC");
- stmt.setString(3, "Tr/Bal");
- stmt.setString(4, "Tr/Bal");
- stmt.setString(5, "B1");
- stmt.setString(6, "C1");
- stmt.setLong(2, 1462993520000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993515000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993510000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993505000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993490000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993485000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993480000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993475000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993470000000000L);
- stmt.execute();
- stmt.setLong(2, 1462993430000000000L);
- stmt.execute();
-
- String q =
- "SELECT C.BUCKET, C.\"TIMESTAMP\" FROM (\n" +
- " SELECT E.BUCKET as BUCKET, L.BUCKET as LBUCKET, E.\"TIMESTAMP\" as TIMESTAMP, L.\"TIMESTAMP\" as LTIMESTAMP FROM\n" +
- " (SELECT BUCKET, \"TIMESTAMP\" FROM EVENT_COUNT\n" +
- " WHERE BUCKET = '5SEC' AND LOCATION = 'Tr/Bal'\n" +
- " AND \"TIMESTAMP\" <= 1462993520000000000 AND \"TIMESTAMP\" > 1462993420000000000\n" +
- " ) E\n" +
- " JOIN\n" +
- " (SELECT BUCKET, \"TIMESTAMP\" FROM "+ t[i] +"\n" +
- " WHERE BUCKET = '5SEC' AND SRC_LOCATION = 'Tr/Bal' AND SRC_LOCATION = DST_LOCATION\n" +
- " AND \"TIMESTAMP\" <= 1462993520000000000 AND \"TIMESTAMP\" > 1462993420000000000\n" +
- " ) L\n" +
- " ON L.BUCKET = E.BUCKET AND L.\"TIMESTAMP\" = E.\"TIMESTAMP\"\n" +
- " ) C\n" +
- " GROUP BY C.BUCKET, C.\"TIMESTAMP\"";
-
- String p = i == 0 ?
- "CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER EVENT_COUNT [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [E.BUCKET, \"E.TIMESTAMP\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER " + t[i] + " [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
- " SERVER FILTER BY FIRST KEY ONLY AND SRC_LOCATION = DST_LOCATION\n" +
- " CLIENT MERGE SORT"
- :
- "CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER EVENT_COUNT [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [E.BUCKET, \"E.TIMESTAMP\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER " + t[i] + " [0,'5SEC',1462993420000000001,'Tr/Bal'] - [1,'5SEC',1462993520000000000,'Tr/Bal']\n" +
- " SERVER FILTER BY FIRST KEY ONLY AND SRC_LOCATION = DST_LOCATION\n" +
- " CLIENT MERGE SORT";
-
- ResultSet rs = conn.createStatement().executeQuery("explain " + q);
- assertEquals(p, QueryUtil.getExplainPlan(rs));
-
- rs = conn.createStatement().executeQuery(q);
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993520000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993515000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993510000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993505000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993490000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993485000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993480000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993475000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993470000000000L, rs.getLong(2));
- assertTrue(rs.next());
- assertEquals("5SEC", rs.getString(1));
- assertEquals(1462993430000000000L, rs.getLong(2));
- assertFalse(rs.next());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testBug2961() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- try {
- conn.createStatement().execute("CREATE TABLE test2961 (\n" +
- "ACCOUNT_ID VARCHAR NOT NULL,\n" +
- "BUCKET_ID VARCHAR NOT NULL,\n" +
- "OBJECT_ID VARCHAR NOT NULL,\n" +
- "OBJECT_VERSION VARCHAR NOT NULL,\n" +
- "LOC VARCHAR,\n" +
- "CONSTRAINT PK PRIMARY KEY (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION DESC))");
- conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj1', '1111', 'loc1')");
- ResultSet rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_VERSION = '1111'");
- assertTrue(rs.next());
- rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_ID = 'obj1'");
- assertTrue(rs.next());
- rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_VERSION = '1111' and OBJECT_ID = 'obj1'");
- assertTrue(rs.next());
-
- conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj1', '2222', 'loc1')");
- rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
- + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER"
- + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
- + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
- assertTrue(rs.next());
- assertEquals("2222", rs.getString(4));
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
- + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
- + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
- + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
- assertTrue(rs.next());
- assertEquals("2222", rs.getString(4));
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
- + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
- + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
- + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
- assertTrue(rs.next());
- assertEquals("2222", rs.getString(4));
- assertFalse(rs.next());
-
- conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj2', '1111', 'loc1')");
- conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj3', '1111', 'loc1')");
- String q = "SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
- + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
- + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
- + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION";
- rs = conn.createStatement().executeQuery(q);
- assertTrue(rs.next());
- assertEquals("2222", rs.getString(4));
- assertTrue(rs.next());
- assertEquals("1111", rs.getString(4));
- assertTrue(rs.next());
- assertEquals("1111", rs.getString(4));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-}
[09/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java
deleted file mode 100644
index 684c3c2..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryIT.java
+++ /dev/null
@@ -1,788 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-
-@RunWith(Parameterized.class)
-public class SubqueryIT extends BaseJoinIT {
- public SubqueryIT(String[] indexDDL, String[] plans) {
- super(indexDDL, plans);
- }
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY \\[I.NAME\\]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SKIP-SCAN-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\\$\\d+.\\$\\d+\\)",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
- " CLIENT MERGE SORT\n" +
- " SKIP-SCAN-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_ITEM_TABLE_FULL_NAME + ".item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- " SKIP-SCAN-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\"O.item_id\"\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(I.NAME = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_CUSTOMER_TABLE_FULL_NAME + ".customer_id\" IN \\(\\$\\d+.\\$\\d+\\)"
- }});
- testCases.add(new String[][] {
- {
- "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL SEMI-JOIN TABLE 1 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)"
- }});
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL SEMI-JOIN TABLE 1 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)",
-
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_item.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
-
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\"O.item_id\"\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_customer.:customer_id\" IN \\(\\$\\d+.\\$\\d+\\)"
- }});
- return testCases;
- }
-
-
- @Test
- public void testNonCorrelatedSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
- try {
- String query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" >= ALL (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < ANY (SELECT \"item_id\" FROM " + tableName4 + ")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < (SELECT max(\"item_id\") FROM " + tableName4 + ")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT * FROM " + tableName5 + " WHERE (item_id, item_name) != ALL (SELECT \"item_id\", name FROM " + tableName1 + ")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT * FROM " + tableName5 + " WHERE EXISTS (SELECT \"item_id\", name FROM " + tableName1 + ")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "T5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "T1");
-
- assertFalse(rs.next());
-
- query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < (SELECT \"item_id\" FROM " + tableName4 + ")";
- statement = conn.prepareStatement(query);
- try {
- rs = statement.executeQuery();
- fail("Should have got Exception.");
- } catch (SQLException e) {
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
- try {
- String query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT i.\"item_id\", s.name FROM " + tableName1 + " i JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + " WHERE \"order_id\" > '000000000000001') ORDER BY i.name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[0], plan);
-
- query = "SELECT i.\"item_id\", s.name FROM " + tableName2 + " s LEFT JOIN " + tableName1 + " i ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY i.name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[1], QueryUtil.getExplainPlan(rs));
-
- query = "SELECT * FROM " + tableName5 + " WHERE (item_id, item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + "))"
- + " OR (co_item_id, co_item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + "))";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "T1");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[2], plan);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testExistsSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
- try {
- String query = "SELECT \"item_id\", name FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " o WHERE o.\"item_id\" = i.\"item_id\") ORDER BY name";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[3], QueryUtil.getExplainPlan(rs));
-
- query = "SELECT * FROM " + tableName5 + " co WHERE EXISTS (SELECT 1 FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " WHERE \"item_id\" = i.\"item_id\") AND co.item_id = \"item_id\" AND name = co.item_name)"
- + " OR EXISTS (SELECT 1 FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") AND co.co_item_id = \"item_id\" AND name = co.co_item_name)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "T1");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[2], plan);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testComparisonSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- final Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- String query = "SELECT \"order_id\", name FROM " + tableName4 +
- " o JOIN " + tableName1 +
- " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " +
- tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
-
- assertFalse(rs.next());
-
- query = "SELECT \"order_id\", name FROM " + tableName4 +
- " o JOIN " + tableName1 +
- " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " +
- tableName1 + " i2 JOIN " + tableName4 +
- " q ON i2.\"item_id\" = q.\"item_id\" WHERE o.\"item_id\" = i2.\"item_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
-
- assertFalse(rs.next());
-
- query = "SELECT name from " + tableName3 +
- " WHERE \"customer_id\" IN (SELECT \"customer_id\" FROM " +
- tableName1 + " i JOIN " + tableName4 +
- " o ON o.\"item_id\" = i.\"item_id\" WHERE i.name = 'T2' OR quantity > (SELECT avg(quantity) FROM " +
- tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\"))";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C4");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[4], plan);
-
- query = "SELECT \"order_id\" FROM " + tableName4 +
- " o WHERE quantity = (SELECT quantity FROM " + tableName4 +
- " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004')";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
-
- assertFalse(rs.next());
-
- query = "SELECT \"order_id\" FROM " + tableName4 +
- " o WHERE quantity = (SELECT quantity FROM " + tableName4 +
- " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003')";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- try {
- while(rs.next());
- fail("Should have got exception.");
- } catch (SQLException e) {
- }
-
- query = "SELECT \"order_id\" FROM " + tableName4 +
- " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 +
- " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004' GROUP BY \"order_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
-
- assertFalse(rs.next());
-
- query = "SELECT \"order_id\" FROM " + tableName4 +
- " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 +
- " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003' GROUP BY \"order_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- try {
- while(rs.next());
- fail("Should have got exception.");
- } catch (SQLException e) {
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testAnyAllComparisonSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- String query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = ALL(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
-
- assertFalse(rs.next());
-
- query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ALL(SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ANY(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\" GROUP BY quantity)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSubqueryWithUpsert() throws Exception {
- String tempTable = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- conn.createStatement().execute("CREATE TABLE " + tempTable
- + " (item_id varchar not null primary key, "
- + " name varchar)");
- conn.createStatement().execute("UPSERT INTO " + tempTable + "(item_id, name)"
- + " SELECT \"item_id\", name FROM " + tableName1
- + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ")");
-
- String query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "INVALID-1");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSubqueryWithDelete() throws Exception {
- String tempTable = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- conn.createStatement().execute("CREATE TABLE " + tempTable
- + " (item_id varchar not null primary key, "
- + " name varchar)");
- conn.createStatement().execute("UPSERT INTO " + tempTable + "(item_id, name)"
- + " SELECT \"item_id\", name FROM " + tableName1);
-
- String query = "SELECT count(*) FROM " + tableName1;
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getInt(1), 7);
- assertFalse(rs.next());
-
- conn.createStatement().execute("DELETE FROM " + tempTable + " WHERE item_id IN ("
- + " SELECT \"item_id\" FROM " + tableName4 + ")");
-
- query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "INVALID-1");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java
deleted file mode 100644
index 3e64169..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SubqueryUsingSortMergeJoinIT.java
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-
-@RunWith(Parameterized.class)
-public class SubqueryUsingSortMergeJoinIT extends BaseJoinIT {
-
- public SubqueryUsingSortMergeJoinIT(String[] indexDDL, String[] plans) {
- super(indexDDL, plans);
- }
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- "SORT-MERGE-JOIN (SEMI) TABLES\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"I.supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " CLIENT SORTED BY [\"I.item_id\"]\n" +
- "AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [I.NAME]",
-
- "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"]\\\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
- " CLIENT MERGE SORT\n" +
- " SKIP-SCAN-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_ITEM_TABLE_FULL_NAME + ".item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
- "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- "AND \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\"O.item_id\"\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(I.NAME = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
- }});
- testCases.add(new String[][] {
- {
- "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (SEMI) TABLES\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER SORTED BY [\"I.0:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.:item_id\"]\n" +
- "AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I.0:NAME\"]",
-
- "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY \\[\"Join.idx_customer.:customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- "AND \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
- }});
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (SEMI) TABLES\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER SORTED BY [\"I.0:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.:item_id\"]\n" +
- "AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I.0:NAME\"]",
-
- "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
- " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
- " CLIENT MERGE SORT\n" +
- " AND\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_item.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
- "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
-
- "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY \\[\"Join.idx_customer.:customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- "AND \\(SKIP MERGE\\)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\"O.item_id\"\\)\n" +
- " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
- }});
- return testCases;
- }
-
- @Test
- public void testInSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
- try {
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\", s.name FROM " + tableName1 + " i JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + " WHERE \"order_id\" > '000000000000001') ORDER BY i.name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- assertPlansEqual(plans[0], QueryUtil.getExplainPlan(rs));
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\", s.name FROM " + tableName2 + " s LEFT JOIN " + tableName1 + " i ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY i.name";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName5 + " WHERE (item_id, item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + "))"
- + " OR (co_item_id, co_item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + "))";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "T3");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[1], plan);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testExistsSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
- try {
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " o WHERE o.\"item_id\" = i.\"item_id\") ORDER BY name";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName5 + " co WHERE EXISTS (SELECT 1 FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " WHERE \"item_id\" = i.\"item_id\") AND co.item_id = \"item_id\" AND name = co.item_name)"
- + " OR EXISTS (SELECT 1 FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") AND co.co_item_id = \"item_id\" AND name = co.co_item_name)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "T3");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[1], plan);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testComparisonSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ name from " + tableName3 + " WHERE \"customer_id\" IN (SELECT \"customer_id\" FROM " + tableName1 + " i JOIN " + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" WHERE i.name = 'T2' OR quantity > (SELECT avg(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\"))";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C4");
-
- assertFalse(rs.next());
-
- rs = conn.createStatement().executeQuery("EXPLAIN " + query);
- String plan = QueryUtil.getExplainPlan(rs);
- assertPlansMatch(plans[2], plan);
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT quantity FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004')";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT quantity FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003')";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- try {
- while(rs.next());
- fail("Should have got exception.");
- } catch (SQLException e) {
- }
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004' GROUP BY \"order_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003' GROUP BY \"order_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- try {
- while(rs.next());
- fail("Should have got exception.");
- } catch (SQLException e) {
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testAnyAllComparisonSubquery() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = ALL(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ALL(SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
-
- query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ANY(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\" GROUP BY quantity)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSubqueryWithUpsert() throws Exception {
- String tempTable = generateUniqueName();
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- conn.setAutoCommit(true);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- try {
- conn.createStatement().execute("CREATE TABLE " + tempTable
- + " (item_id varchar not null primary key, "
- + " name varchar)");
- conn.createStatement().execute("UPSERT /*+ USE_SORT_MERGE_JOIN*/ INTO " + tempTable + "(item_id, name)"
- + " SELECT \"item_id\", name FROM " + tableName1
- + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ")");
-
- String query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "INVALID-1");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
-}
-
-
[15/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
PHOENIX-4246 Breakup join related tests into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/834133a1
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/834133a1
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/834133a1
Branch: refs/heads/master
Commit: 834133a194a75c9231f9773b0bd89fd752dcf5dc
Parents: ee20a8c
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 15:06:35 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 17:51:57 2017 -0700
----------------------------------------------------------------------
.../end2end/join/HashJoinGlobalIndexIT.java | 2 +-
.../end2end/join/HashJoinLocalIndexIT.java | 2 +-
.../phoenix/end2end/join/HashJoinNoIndexIT.java | 2 +-
.../join/SortMergeJoinGlobalIndexIT.java | 84 ++++++++++++
.../phoenix/end2end/join/SortMergeJoinIT.java | 134 +------------------
.../end2end/join/SortMergeJoinLocalIndexIT.java | 84 ++++++++++++
.../end2end/join/SortMergeJoinNoIndexIT.java | 66 +++++++++
7 files changed, 238 insertions(+), 136 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
index 76944a6..a725be7 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
@@ -30,7 +30,7 @@ public class HashJoinGlobalIndexIT extends HashJoinIT {
super(indexDDL, plans);
}
- @Parameters
+ @Parameters(name="HashJoinGlobalIndexIT_{index}") // name is used by failsafe as file name in reports
public static Collection<Object> data() {
List<Object> testCases = Lists.newArrayList();
testCases.add(new String[][] {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
index dcc454f..59ddce9 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
@@ -46,7 +46,7 @@ public class HashJoinLocalIndexIT extends HashJoinIT {
super(indexDDL, plans);
}
- @Parameters
+ @Parameters(name="HashJoinLocalIndexIT_{index}") // name is used by failsafe as file name in reports
public static Collection<Object> data() {
List<Object> testCases = Lists.newArrayList();
testCases.add(new String[][] {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
index 7f8528d..3bbcaf2 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
@@ -30,7 +30,7 @@ public class HashJoinNoIndexIT extends HashJoinIT {
super(indexDDL, plans);
}
- @Parameters
+ @Parameters(name="HashJoinNoIndexIT_{index}") // name is used by failsafe as file name in reports
public static Collection<Object> data() {
List<Object> testCases = Lists.newArrayList();
testCases.add(new String[][] {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinGlobalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinGlobalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinGlobalIndexIT.java
new file mode 100644
index 0000000..ce6f032
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinGlobalIndexIT.java
@@ -0,0 +1,84 @@
+/*
+ * 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.end2end.join;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+public class SortMergeJoinGlobalIndexIT extends SortMergeJoinIT {
+
+ public SortMergeJoinGlobalIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters(name="SortMergeJoinGlobalIndexIT_{index}") // name is used by failsafe as file name in reports
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {
+ "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.0:supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I2.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I1.:item_id\"]"
+ }});
+ return testCases;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
index 8e7bfe2..234c2ee 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
@@ -34,8 +34,6 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.List;
import java.util.Properties;
import org.apache.phoenix.exception.SQLExceptionCode;
@@ -45,140 +43,10 @@ import org.apache.phoenix.util.QueryUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
@RunWith(Parameterized.class)
-public class SortMergeJoinIT extends BaseJoinIT {
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY"
- }});
- testCases.add(new String[][] {
- {
- "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.0:supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I2.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I1.:item_id\"]"
- }});
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.0:supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I2.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I1.:item_id\"]"
- }});
- return testCases;
- }
+public abstract class SortMergeJoinIT extends BaseJoinIT {
-
public SortMergeJoinIT(String[] indexDDL, String[] plans) {
super(indexDDL, plans);
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinLocalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinLocalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinLocalIndexIT.java
new file mode 100644
index 0000000..919aa69
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinLocalIndexIT.java
@@ -0,0 +1,84 @@
+/*
+ * 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.end2end.join;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+public class SortMergeJoinLocalIndexIT extends SortMergeJoinIT {
+
+ public SortMergeJoinLocalIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters(name="SortMergeJoinLocalIndexIT_{index}") // name is used by failsafe as file name in reports
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {
+ "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.0:supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I2.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I1.:item_id\"]"
+ }});
+ return testCases;
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/834133a1/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinNoIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinNoIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinNoIndexIT.java
new file mode 100644
index 0000000..6f04729
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinNoIndexIT.java
@@ -0,0 +1,66 @@
+/*
+ * 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.end2end.join;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+public class SortMergeJoinNoIndexIT extends SortMergeJoinIT {
+
+ public SortMergeJoinNoIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters(name="SortMergeJoinNoIndexIT_{index}") // name is used by failsafe as file name in reports
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {}, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY"
+ }});
+ return testCases;
+ }
+}
[03/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryIT.java
new file mode 100644
index 0000000..604db63
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryIT.java
@@ -0,0 +1,788 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+@RunWith(Parameterized.class)
+public class SubqueryIT extends BaseJoinIT {
+ public SubqueryIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {}, {
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY \\[I.NAME\\]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SKIP-SCAN-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\\$\\d+.\\$\\d+\\)",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " SKIP-SCAN-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_ITEM_TABLE_FULL_NAME + ".item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
+ " SKIP-SCAN-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\"O.item_id\"\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(I.NAME = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_CUSTOMER_TABLE_FULL_NAME + ".customer_id\" IN \\(\\$\\d+.\\$\\d+\\)"
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL SEMI-JOIN TABLE 1 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)"
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL SEMI-JOIN TABLE 1 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " \\['000000000000001'\\] - \\[\\*\\]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)",
+
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL SEMI-JOIN TABLE 1(DELAYED EVALUATION) (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_item.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\"O.item_id\"\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_customer.:customer_id\" IN \\(\\$\\d+.\\$\\d+\\)"
+ }});
+ return testCases;
+ }
+
+
+ @Test
+ public void testNonCorrelatedSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" >= ALL (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < ANY (SELECT \"item_id\" FROM " + tableName4 + ")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < (SELECT max(\"item_id\") FROM " + tableName4 + ")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + tableName5 + " WHERE (item_id, item_name) != ALL (SELECT \"item_id\", name FROM " + tableName1 + ")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + tableName5 + " WHERE EXISTS (SELECT \"item_id\", name FROM " + tableName1 + ")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "T1");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" < (SELECT \"item_id\" FROM " + tableName4 + ")";
+ statement = conn.prepareStatement(query);
+ try {
+ rs = statement.executeQuery();
+ fail("Should have got Exception.");
+ } catch (SQLException e) {
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT i.\"item_id\", s.name FROM " + tableName1 + " i JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + " WHERE \"order_id\" > '000000000000001') ORDER BY i.name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[0], plan);
+
+ query = "SELECT i.\"item_id\", s.name FROM " + tableName2 + " s LEFT JOIN " + tableName1 + " i ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY i.name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[1], QueryUtil.getExplainPlan(rs));
+
+ query = "SELECT * FROM " + tableName5 + " WHERE (item_id, item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + "))"
+ + " OR (co_item_id, co_item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + "))";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "T1");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[2], plan);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testExistsSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT \"item_id\", name FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " o WHERE o.\"item_id\" = i.\"item_id\") ORDER BY name";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[3], QueryUtil.getExplainPlan(rs));
+
+ query = "SELECT * FROM " + tableName5 + " co WHERE EXISTS (SELECT 1 FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " WHERE \"item_id\" = i.\"item_id\") AND co.item_id = \"item_id\" AND name = co.item_name)"
+ + " OR EXISTS (SELECT 1 FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") AND co.co_item_id = \"item_id\" AND name = co.co_item_name)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "T1");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[2], plan);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testComparisonSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ final Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT \"order_id\", name FROM " + tableName4 +
+ " o JOIN " + tableName1 +
+ " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " +
+ tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"order_id\", name FROM " + tableName4 +
+ " o JOIN " + tableName1 +
+ " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " +
+ tableName1 + " i2 JOIN " + tableName4 +
+ " q ON i2.\"item_id\" = q.\"item_id\" WHERE o.\"item_id\" = i2.\"item_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+
+ assertFalse(rs.next());
+
+ query = "SELECT name from " + tableName3 +
+ " WHERE \"customer_id\" IN (SELECT \"customer_id\" FROM " +
+ tableName1 + " i JOIN " + tableName4 +
+ " o ON o.\"item_id\" = i.\"item_id\" WHERE i.name = 'T2' OR quantity > (SELECT avg(quantity) FROM " +
+ tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\"))";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C4");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[4], plan);
+
+ query = "SELECT \"order_id\" FROM " + tableName4 +
+ " o WHERE quantity = (SELECT quantity FROM " + tableName4 +
+ " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004')";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"order_id\" FROM " + tableName4 +
+ " o WHERE quantity = (SELECT quantity FROM " + tableName4 +
+ " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003')";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ try {
+ while(rs.next());
+ fail("Should have got exception.");
+ } catch (SQLException e) {
+ }
+
+ query = "SELECT \"order_id\" FROM " + tableName4 +
+ " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 +
+ " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004' GROUP BY \"order_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"order_id\" FROM " + tableName4 +
+ " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 +
+ " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003' GROUP BY \"order_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ try {
+ while(rs.next());
+ fail("Should have got exception.");
+ } catch (SQLException e) {
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAnyAllComparisonSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = ALL(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ALL(SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ANY(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\" GROUP BY quantity)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSubqueryWithUpsert() throws Exception {
+ String tempTable = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTable
+ + " (item_id varchar not null primary key, "
+ + " name varchar)");
+ conn.createStatement().execute("UPSERT INTO " + tempTable + "(item_id, name)"
+ + " SELECT \"item_id\", name FROM " + tableName1
+ + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ")");
+
+ String query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "INVALID-1");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSubqueryWithDelete() throws Exception {
+ String tempTable = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTable
+ + " (item_id varchar not null primary key, "
+ + " name varchar)");
+ conn.createStatement().execute("UPSERT INTO " + tempTable + "(item_id, name)"
+ + " SELECT \"item_id\", name FROM " + tableName1);
+
+ String query = "SELECT count(*) FROM " + tableName1;
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getInt(1), 7);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("DELETE FROM " + tempTable + " WHERE item_id IN ("
+ + " SELECT \"item_id\" FROM " + tableName4 + ")");
+
+ query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "INVALID-1");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryUsingSortMergeJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryUsingSortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryUsingSortMergeJoinIT.java
new file mode 100644
index 0000000..9335065
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SubqueryUsingSortMergeJoinIT.java
@@ -0,0 +1,566 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+@RunWith(Parameterized.class)
+public class SubqueryUsingSortMergeJoinIT extends BaseJoinIT {
+
+ public SubqueryUsingSortMergeJoinIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {}, {
+ "SORT-MERGE-JOIN (SEMI) TABLES\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"I.supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " CLIENT SORTED BY [\"I.item_id\"]\n" +
+ "AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [I.NAME]",
+
+ "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"]\\\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\".+.item_id\", .+.NAME\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " SKIP-SCAN-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_ITEM_TABLE_FULL_NAME + ".item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
+ "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
+ "AND \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN \\(\"O.item_id\"\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(I.NAME = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (SEMI) TABLES\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER SORTED BY [\"I.0:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.:item_id\"]\n" +
+ "AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I.0:NAME\"]",
+
+ "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY \\[\"Join.idx_customer.:customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (SEMI) TABLES\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER SORTED BY [\"I.0:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.:item_id\"]\n" +
+ "AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + " ['000000000000001'] - [*]\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I.0:NAME\"]",
+
+ "SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " SORT-MERGE-JOIN \\(LEFT\\) TABLES\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER " + JOIN_COITEM_TABLE_FULL_NAME + "\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL ANTI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY \\[.*.CO_ITEM_ID, .*.CO_ITEM_NAME\\]\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY \\[\".+.:item_id\", \".+.0:NAME\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL SEMI-JOIN TABLE 0 \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"" + JOIN_SCHEMA + ".idx_item.:item_id\" IN \\(\\$\\d+.\\$\\d+\\)\n" +
+ "CLIENT FILTER BY \\(\\$\\d+.\\$\\d+ IS NOT NULL OR \\$\\d+.\\$\\d+ IS NOT NULL\\)",
+
+ "SORT-MERGE-JOIN \\(SEMI\\) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY \\[\"Join.idx_customer.:customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND \\(SKIP MERGE\\)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " \\[1\\]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"O.customer_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1\\(DELAYED EVALUATION\\)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY \\[\"item_id\"\\]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN \\(\"O.item_id\"\\)\n" +
+ " AFTER-JOIN SERVER FILTER BY \\(\"I.0:NAME\" = 'T2' OR O.QUANTITY > \\$\\d+.\\$\\d+\\)",
+ }});
+ return testCases;
+ }
+
+ @Test
+ public void testInSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\", s.name FROM " + tableName1 + " i JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + " WHERE \"order_id\" > '000000000000001') ORDER BY i.name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[0], QueryUtil.getExplainPlan(rs));
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\", s.name FROM " + tableName2 + " s LEFT JOIN " + tableName1 + " i ON i.\"supplier_id\" = s.\"supplier_id\" WHERE i.\"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") ORDER BY i.name";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName5 + " WHERE (item_id, item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + "))"
+ + " OR (co_item_id, co_item_name) IN (SELECT \"item_id\", name FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + "))";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "T3");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[1], plan);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testExistsSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String tableName5 = getTableName(conn, JOIN_COITEM_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"item_id\", name FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " o WHERE o.\"item_id\" = i.\"item_id\") ORDER BY name";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName5 + " co WHERE EXISTS (SELECT 1 FROM " + tableName1 + " i WHERE NOT EXISTS (SELECT 1 FROM " + tableName4 + " WHERE \"item_id\" = i.\"item_id\") AND co.item_id = \"item_id\" AND name = co.item_name)"
+ + " OR EXISTS (SELECT 1 FROM " + tableName1 + " WHERE \"item_id\" IN (SELECT \"item_id\" FROM " + tableName4 + ") AND co.co_item_id = \"item_id\" AND name = co.co_item_name)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "T3");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[1], plan);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testComparisonSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ name from " + tableName3 + " WHERE \"customer_id\" IN (SELECT \"customer_id\" FROM " + tableName1 + " i JOIN " + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" WHERE i.name = 'T2' OR quantity > (SELECT avg(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\"))";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C4");
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String plan = QueryUtil.getExplainPlan(rs);
+ assertPlansMatch(plans[2], plan);
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT quantity FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004')";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT quantity FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003')";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ try {
+ while(rs.next());
+ fail("Should have got exception.");
+ } catch (SQLException e) {
+ }
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000004' GROUP BY \"order_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\" FROM " + tableName4 + " o WHERE quantity = (SELECT max(quantity) FROM " + tableName4 + " WHERE o.\"item_id\" = \"item_id\" AND \"order_id\" != '000000000000003' GROUP BY \"order_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ try {
+ while(rs.next());
+ fail("Should have got exception.");
+ } catch (SQLException e) {
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testAnyAllComparisonSubquery() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity = ALL(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ALL(SELECT max(quantity) FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\")";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+
+ query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", name FROM " + tableName4 + " o JOIN " + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" WHERE quantity != ANY(SELECT quantity FROM " + tableName4 + " q WHERE o.\"item_id\" = q.\"item_id\" GROUP BY quantity)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSubqueryWithUpsert() throws Exception {
+ String tempTable = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTable
+ + " (item_id varchar not null primary key, "
+ + " name varchar)");
+ conn.createStatement().execute("UPSERT /*+ USE_SORT_MERGE_JOIN*/ INTO " + tempTable + "(item_id, name)"
+ + " SELECT \"item_id\", name FROM " + tableName1
+ + " WHERE \"item_id\" NOT IN (SELECT \"item_id\" FROM " + tableName4 + ")");
+
+ String query = "SELECT name FROM " + tempTable + " ORDER BY item_id";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "INVALID-1");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+}
+
+
[16/25] phoenix git commit: PHOENIX-4244 Breakup ArrayIT into several
integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/527f786a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
index cf86614..ddc965a 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java
@@ -19,35 +19,48 @@ package org.apache.phoenix.end2end;
import static org.apache.phoenix.util.TestUtil.B_VALUE;
import static org.apache.phoenix.util.TestUtil.ROW1;
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import java.sql.Array;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
-import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
import org.apache.phoenix.query.BaseTest;
-import org.apache.phoenix.schema.types.PhoenixArray;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.StringUtil;
-import org.junit.Test;
-import com.google.common.primitives.Floats;
+public abstract class ArrayIT extends ParallelStatsDisabledIT {
-public class ArrayIT extends ParallelStatsDisabledIT {
+ protected static String createTableWithArray(String url, byte[][] bs, Object object) throws SQLException {
+ String tableName = generateUniqueName();
+ String ddlStmt = "create table "
+ + tableName
+ + " (organization_id char(15) not null, \n"
+ + " entity_id char(15) not null,\n"
+ + " a_string_array varchar(100) array[3],\n"
+ + " b_string varchar(100),\n"
+ + " a_integer integer,\n"
+ + " a_date date,\n"
+ + " a_time time,\n"
+ + " a_timestamp timestamp,\n"
+ + " x_decimal decimal(31,10),\n"
+ + " x_long_array bigint[5],\n"
+ + " x_integer integer,\n"
+ + " a_byte_array tinyint array,\n"
+ + " a_short smallint,\n"
+ + " a_float float,\n"
+ + " a_double_array double array[],\n"
+ + " a_unsigned_float unsigned_float,\n"
+ + " a_unsigned_double unsigned_double \n"
+ + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
+ + ")";
+ BaseTest.createTestTable(url, ddlStmt, bs, null);
+ return tableName;
+ }
- private static void initTablesWithArrays(String tableName, String tenantId, Date date, boolean useNull, String url) throws Exception {
+ protected static void initTablesWithArrays(String tableName, String tenantId, Date date, boolean useNull, String url) throws Exception {
Properties props = new Properties();
Connection conn = DriverManager.getConnection(url, props);
try {
@@ -121,2504 +134,4 @@ public class ArrayIT extends ParallelStatsDisabledIT {
conn.close();
}
}
-
- @Test
- public void testScanByArrayValue() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_float";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- analyzeTable(conn, tableName);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setFloat(2, 0.01f);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[4];
- doubleArr[0] = 25.343;
- doubleArr[1] = 36.763;
- doubleArr[2] = 37.56;
- doubleArr[3] = 386.63;
- Array array = conn.createArrayOf("DOUBLE",
- doubleArr);
- PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
- assertEquals(resultArray, array);
- assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
- assertEquals(rs.getString("B_string"), B_VALUE);
- assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- private void analyzeTable(Connection conn, String tableWithArray) throws SQLException {
- String analyse = "UPDATE STATISTICS "+tableWithArray;
- PreparedStatement statement = conn.prepareStatement(analyse);
- statement.execute();
- }
-
- @Test
- public void testScanWithArrayInWhereClause() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_byte_array";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- //TODO: samarth do we need this?
- analyzeTable(conn, tableName);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- // Need to support primitive
- Byte[] byteArr = new Byte[2];
- byteArr[0] = 25;
- byteArr[1] = 36;
- Array array = conn.createArrayOf("TINYINT", byteArr);
- statement.setArray(2, array);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[4];
- doubleArr[0] = 25.343;
- doubleArr[1] = 36.763;
- doubleArr[2] = 37.56;
- doubleArr[3] = 386.63;
- array = conn.createArrayOf("DOUBLE", doubleArr);
- Array resultArray = rs.getArray(1);
- assertEquals(resultArray, array);
- assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
- assertEquals(rs.getString("B_string"), B_VALUE);
- assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testScanWithNonFixedWidthArrayInWhereClause() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array, /* comment ok? */ b_string, a_float FROM " + tableName + " WHERE ?=organization_id and ?=a_string_array";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- // Need to support primitive
- String[] strArr = new String[4];
- strArr[0] = "ABC";
- strArr[1] = "CEDF";
- strArr[2] = "XYZWER";
- strArr[3] = "AB";
- Array array = conn.createArrayOf("VARCHAR", strArr);
- statement.setArray(2, array);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[4];
- doubleArr[0] = 25.343;
- doubleArr[1] = 36.763;
- doubleArr[2] = 37.56;
- doubleArr[3] = 386.63;
- array = conn.createArrayOf("DOUBLE", doubleArr);
- Array resultArray = rs.getArray(1);
- assertEquals(resultArray, array);
- assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
- assertEquals(rs.getString("B_string"), B_VALUE);
- assertTrue(Floats.compare(rs.getFloat(3), 0.01f) == 0);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testScanWithNonFixedWidthArrayInSelectClause() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array FROM " + tableName;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[4];
- strArr[0] = "ABC";
- strArr[1] = "CEDF";
- strArr[2] = "XYZWER";
- strArr[3] = "AB";
- Array array = conn.createArrayOf("VARCHAR", strArr);
- PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
- assertEquals(resultArray, array);
- assertEquals("['ABC', 'CEDF', 'XYZWER', 'AB']", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSpecificIndexOfAnArrayAsArrayFunction()
- throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + tableName;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 36.763;
- conn.createArrayOf("DOUBLE", doubleArr);
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSpecificIndexOfAnArray() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array[3] FROM " + tableName;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 37.56;
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testCaseWithArray() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(tableName, tenantId, null, false, getUrl());
- String query = "SELECT CASE WHEN A_INTEGER = 1 THEN a_double_array ELSE null END [3] FROM " + tableName;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 37.56;
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testUpsertValuesWithArray() throws Exception {
- String tenantId = getOrganizationId();
- String tableName = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- String query = "upsert into " + tableName + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) values('" + tenantId
- + "','00A123122312312',ARRAY[2.0,345.8])";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- // at
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- int executeUpdate = statement.executeUpdate();
- assertEquals(1, executeUpdate);
- conn.commit();
- statement.close();
- conn.close();
- // create another connection
- props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + tableName;
- statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 345.8d;
- conn.createArrayOf("DOUBLE", doubleArr);
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testUpsertSelectWithSelectAsSubQuery1() throws Exception {
- String tenantId = getOrganizationId();
- String table1 = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- Connection conn = null;
- try {
- String table2 = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table2, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "upsert into " + table1 + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) "
- + "SELECT organization_id, entity_id, a_double_array FROM " + table2
- + " WHERE a_double_array[2] = 89.96";
- PreparedStatement statement = conn.prepareStatement(query);
- int executeUpdate = statement.executeUpdate();
- assertEquals(1, executeUpdate);
- conn.commit();
- statement.close();
- conn.close();
- // create another connection
- props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table1;
- statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 89.96d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- assertFalse(rs.next());
-
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithORCondition() throws Exception {
- String tenantId = getOrganizationId();
- Connection conn = null;
- try {
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_double_array[1] FROM " + table
- + " WHERE a_double_array[2] = 89.96 or a_char_array[0] = 'a'";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 64.87d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- assertFalse(rs.next());
-
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithANY() throws Exception {
- String tenantId = getOrganizationId();
- Connection conn = null;
- try {
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_double_array[1] FROM " + table
- + " WHERE CAST(89.96 AS DOUBLE) = ANY(a_double_array)";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 64.87d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- assertFalse(rs.next());
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithALL() throws Exception {
- String tenantId = getOrganizationId();
- Connection conn = null;
- try {
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_double_array[1] FROM " + table
- + " WHERE CAST(64.87 as DOUBLE) = ALL(a_double_array)";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertFalse(rs.next());
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithANYCombinedWithOR() throws Exception {
- String tenantId = getOrganizationId();
- Connection conn = null;
- try {
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_double_array[1] FROM " + table
- + " WHERE a_char_array[0] = 'f' or CAST(89.96 AS DOUBLE) > ANY(a_double_array)";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 64.87d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- assertFalse(rs.next());
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithALLCombinedWithOR() throws Exception {
-
- String tenantId = getOrganizationId();
- Connection conn = null;
- try {
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_double_array[1], a_double_array[2] FROM " + table
- + " WHERE a_char_array[0] = 'f' or CAST(100.0 AS DOUBLE) > ALL(a_double_array)";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 64.87d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- doubleArr = new Double[1];
- doubleArr[0] = 89.96d;
- result = rs.getDouble(2);
- assertEquals(result, doubleArr[0]);
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testArraySelectWithANYUsingVarLengthArray() throws Exception {
- Connection conn = null;
- try {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "SELECT a_string_array[1] FROM " + table
- + " WHERE 'XYZWER' = ANY(a_string_array)";
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "ABC";
- String result = rs.getString(1);
- assertEquals(result, strArr[0]);
- assertFalse(rs.next());
- query = "SELECT a_string_array[1] FROM " + table + " WHERE 'AB' = ANY(a_string_array)";
- statement = conn.prepareStatement(query);
- rs = statement.executeQuery();
- assertTrue(rs.next());
- result = rs.getString(1);
- assertEquals(result, strArr[0]);
- assertFalse(rs.next());
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testSelectWithArrayWithColumnRef() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_integer,ARRAY[1,2,a_integer] FROM " + table + " where organization_id = '"
- + tenantId + "'";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- int val = rs.getInt(1);
- assertEquals(val, 1);
- Array array = rs.getArray(2);
- // Need to support primitive
- Integer[] intArr = new Integer[3];
- intArr[0] = 1;
- intArr[1] = 2;
- intArr[2] = 1;
- Array resultArr = conn.createArrayOf("INTEGER", intArr);
- assertEquals(resultArr, array);
- assertEquals("[1, 2, 1]", rs.getString(2));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectWithArrayWithColumnRefWithVarLengthArray() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT b_string,ARRAY['abc','defgh',b_string] FROM " + table + " where organization_id = '"
- + tenantId + "'";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String val = rs.getString(1);
- assertEquals(val, "b");
- Array array = rs.getArray(2);
- // Need to support primitive
- String[] strArr = new String[3];
- strArr[0] = "abc";
- strArr[1] = "defgh";
- strArr[2] = "b";
- Array resultArr = conn.createArrayOf("VARCHAR", strArr);
- assertEquals(resultArr, array);
- // since array is var length, last string element is messed up
- String expectedPrefix = "['abc', 'defgh', 'b";
- assertTrue("Expected to start with " + expectedPrefix,
- rs.getString(2).startsWith(expectedPrefix));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectWithArrayWithColumnRefWithVarLengthArrayWithNullValue() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT b_string,ARRAY['abc',null,'bcd',null,null,b_string] FROM " + table + " where organization_id = '"
- + tenantId + "'";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String val = rs.getString(1);
- assertEquals(val, "b");
- Array array = rs.getArray(2);
- // Need to support primitive
- String[] strArr = new String[6];
- strArr[0] = "abc";
- strArr[1] = null;
- strArr[2] = "bcd";
- strArr[3] = null;
- strArr[4] = null;
- strArr[5] = "b";
- Array resultArr = conn.createArrayOf("VARCHAR", strArr);
- assertEquals(resultArr, array);
- String expectedPrefix = "['abc', null, 'bcd', null, null, 'b";
- assertTrue("Expected to start with " + expectedPrefix,
- rs.getString(2).startsWith(expectedPrefix));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testUpsertSelectWithColumnRef() throws Exception {
-
- String tenantId = getOrganizationId();
- String table1 = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- Connection conn = null;
- try {
- String table2 = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table2, tenantId, null, false);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String query = "upsert into " + table1 + " (ORGANIZATION_ID,ENTITY_ID, a_unsigned_double, a_double_array) "
- + "SELECT organization_id, entity_id, x_double, ARRAY[23.4, 22.1, x_double] FROM " + table2
- + " WHERE a_double_array[2] = 89.96";
- PreparedStatement statement = conn.prepareStatement(query);
- int executeUpdate = statement.executeUpdate();
- assertEquals(1, executeUpdate);
- conn.commit();
- statement.close();
- conn.close();
- // create another connection
- props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table1;
- statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 22.1d;
- Double result = rs.getDouble(1);
- assertEquals(result, doubleArr[0]);
- assertFalse(rs.next());
-
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
- }
-
- @Test
- public void testCharArraySpecificIndex() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createSimpleTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- initSimpleArrayTable(table, tenantId, null, false);
- String query = "SELECT a_char_array[2] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] charArr = new String[1];
- charArr[0] = "b";
- String result = rs.getString(1);
- assertEquals(charArr[0], result);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArrayWithDescOrder() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute(
- "CREATE TABLE " + table + " ( k VARCHAR, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4] \n"
- + " CONSTRAINT pk PRIMARY KEY (k, b_string_array DESC)) \n");
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
- Array array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
- array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(3, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT b_string_array FROM " + table);
- assertTrue(rs.next());
- PhoenixArray strArr = (PhoenixArray)rs.getArray(1);
- assertEquals(array, strArr);
- assertEquals("['abc', 'def', 'ghi', 'jkll', null, null, null, 'xxx']", rs.getString(1));
- conn.close();
- }
-
- @Test
- public void testArrayWithFloatArray() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a Float ARRAY[])");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES('a',ARRAY[2.0,3.0])");
- int res = stmt.executeUpdate();
- assertEquals(1, res);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(a,2) FROM " + table);
- assertTrue(rs.next());
- Float f = new Float(3.0);
- assertEquals(f, (Float)rs.getFloat(1));
- conn.close();
- }
-
- @Test
- public void testArrayWithVarCharArray() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a VARCHAR ARRAY[])");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES('a',ARRAY['a',null])");
- int res = stmt.executeUpdate();
- assertEquals(1, res);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(a,2) FROM " + table);
- assertTrue(rs.next());
- assertEquals(null, rs.getString(1));
- conn.close();
- }
-
- @Test
- public void testArraySelectSingleArrayElemWithCast() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a bigint ARRAY[])");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
- stmt.setString(1, "a");
- Long[] s = new Long[] {1l, 2l};
- Array array = conn.createArrayOf("BIGINT", s);
- stmt.setArray(2, array);
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT k, CAST(a[2] AS DOUBLE) FROM " + table);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- Double d = new Double(2.0);
- assertEquals(d, (Double)rs.getDouble(2));
- conn.close();
- }
-
- @Test
- public void testArraySelectGetString() throws Exception {
- Connection conn;
- PreparedStatement stmt;
-
- String tenantId = getOrganizationId();
-
- // create the table
- String tableName = createTableWithAllArrayTypes(getUrl(), getDefaultSplits(tenantId), null);
-
- // populate the table with data
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- stmt =
- conn.prepareStatement("UPSERT INTO "
- + tableName
- + "(ORGANIZATION_ID, ENTITY_ID, BOOLEAN_ARRAY, BYTE_ARRAY, DOUBLE_ARRAY, FLOAT_ARRAY, INT_ARRAY, LONG_ARRAY, SHORT_ARRAY, STRING_ARRAY)\n"
- + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
- stmt.setString(1, tenantId);
- stmt.setString(2, ROW1);
- // boolean array
- Array boolArray = conn.createArrayOf("BOOLEAN", new Boolean[] { true, false });
- int boolIndex = 3;
- stmt.setArray(boolIndex, boolArray);
- // byte array
- Array byteArray = conn.createArrayOf("TINYINT", new Byte[] { 11, 22 });
- int byteIndex = 4;
- stmt.setArray(byteIndex, byteArray);
- // double array
- Array doubleArray = conn.createArrayOf("DOUBLE", new Double[] { 67.78, 78.89 });
- int doubleIndex = 5;
- stmt.setArray(doubleIndex, doubleArray);
- // float array
- Array floatArray = conn.createArrayOf("FLOAT", new Float[] { 12.23f, 45.56f });
- int floatIndex = 6;
- stmt.setArray(floatIndex, floatArray);
- // int array
- Array intArray = conn.createArrayOf("INTEGER", new Integer[] { 5555, 6666 });
- int intIndex = 7;
- stmt.setArray(intIndex, intArray);
- // long array
- Array longArray = conn.createArrayOf("BIGINT", new Long[] { 7777777L, 8888888L });
- int longIndex = 8;
- stmt.setArray(longIndex, longArray);
- // short array
- Array shortArray = conn.createArrayOf("SMALLINT", new Short[] { 333, 444 });
- int shortIndex = 9;
- stmt.setArray(shortIndex, shortArray);
- // create character array
- Array stringArray = conn.createArrayOf("VARCHAR", new String[] { "a", "b" });
- int stringIndex = 10;
- stmt.setArray(stringIndex, stringArray);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt =
- conn.prepareStatement("SELECT organization_id, entity_id, boolean_array, byte_array, double_array, float_array, int_array, long_array, short_array, string_array FROM "
- + tableName);
- //TODO: samarth check if this is needed
- analyzeTable(conn, tableName);
-
- ResultSet rs = stmt.executeQuery();
- assertTrue(rs.next());
-
- assertEquals(tenantId, rs.getString(1));
- assertEquals(ROW1, rs.getString(2));
-
- assertArrayGetString(rs, boolIndex, boolArray, "true, false");
- assertArrayGetString(rs, byteIndex, byteArray, "11, 22");
- assertArrayGetString(rs, doubleIndex, doubleArray, "67.78, 78.89");
- assertArrayGetString(rs, floatIndex, floatArray, "12.23, 45.56");
- assertArrayGetString(rs, intIndex, intArray, "5555, 6666");
- assertArrayGetString(rs, longIndex, longArray, "7777777, 8888888");
- assertArrayGetString(rs, shortIndex, shortArray, "333, 444");
- assertArrayGetString(rs, stringIndex, stringArray, "'a', 'b'");
- conn.close();
- }
-
- private void assertArrayGetString(ResultSet rs, int arrayIndex, Array expectedArray, String expectedString)
- throws SQLException {
- assertEquals(expectedArray, rs.getArray(arrayIndex));
- assertEquals("[" + expectedString + "]", rs.getString(arrayIndex));
- }
-
- @Test
- public void testArrayWithCast() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a bigint ARRAY[])");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
- stmt.setString(1, "a");
- Long[] s = new Long[] { 1l, 2l };
- Array array = conn.createArrayOf("BIGINT", s);
- stmt.setArray(2, array);
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT CAST(a AS DOUBLE []) FROM " + table);
- assertTrue(rs.next());
- Double[] d = new Double[] { 1.0, 2.0 };
- array = conn.createArrayOf("DOUBLE", d);
- PhoenixArray arr = (PhoenixArray)rs.getArray(1);
- assertEquals(array, arr);
- assertEquals("[1.0, 2.0]", rs.getString(1));
- conn.close();
- }
-
- @Test
- public void testArrayWithCastForVarLengthArr() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a VARCHAR(5) ARRAY)");
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] { "1", "2" };
- PhoenixArray array = (PhoenixArray)conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT CAST(a AS CHAR ARRAY) FROM " + table);
- assertTrue(rs.next());
- PhoenixArray arr = (PhoenixArray)rs.getArray(1);
- String[] array2 = (String[])array.getArray();
- String[] array3 = (String[])arr.getArray();
- assertEquals(array2[0], array3[0]);
- assertEquals(array2[1], array3[1]);
- assertEquals("['1', '2']", rs.getString(1));
- conn.close();
- }
-
- @Test
- public void testFixedWidthCharArray() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement().execute("CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a CHAR(5) ARRAY)");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.getMetaData().getColumns(null, null, table, "A");
- assertTrue(rs.next());
- assertEquals(5, rs.getInt("COLUMN_SIZE"));
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] {"1","2"};
- Array array = conn.createArrayOf("CHAR", s);
- stmt.setArray(2, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT k, a[2] FROM " + table);
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("2",rs.getString(2));
- conn.close();
- }
-
- @Test
- public void testSelectArrayUsingUpsertLikeSyntax() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array FROM " + table + " WHERE a_double_array = CAST(ARRAY [ 25.343, 36.763, 37.56,386.63] AS DOUBLE ARRAY)";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- Double[] doubleArr = new Double[4];
- doubleArr[0] = 25.343;
- doubleArr[1] = 36.763;
- doubleArr[2] = 37.56;
- doubleArr[3] = 386.63;
- Array array = conn.createArrayOf("DOUBLE", doubleArr);
- PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
- assertEquals(resultArray, array);
- assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1));
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArrayIndexUsedInWhereClause() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- int a_index = 0;
- String query = "SELECT a_double_array[2] FROM " + table + " where a_double_array["+a_index+"2]<?";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 40.0;
- conn.createArrayOf("DOUBLE", doubleArr);
- statement.setDouble(1, 40.0d);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- doubleArr = new Double[1];
- doubleArr[0] = 36.763;
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArrayIndexUsedInGroupByClause() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array[2] FROM " + table + " GROUP BY a_double_array[2]";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 40.0;
- conn.createArrayOf("DOUBLE", doubleArr);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- doubleArr = new Double[1];
- doubleArr[0] = 36.763;
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testVariableLengthArrayWithNullValue() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, true, getUrl());
- String query = "SELECT a_string_array[2] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- String result = rs.getString(1);
- assertNull(result);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSpecificIndexOfAVariableArrayAlongWithAnotherColumn1() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array[3],A_INTEGER FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- String result = rs.getString(1);
- assertEquals(strArr[0], result);
- int a_integer = rs.getInt(2);
- assertEquals(1, a_integer);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSpecificIndexOfAVariableArrayAlongWithAnotherColumn2() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT A_INTEGER, a_string_array[3] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- int a_integer = rs.getInt(1);
- assertEquals(1, a_integer);
- String result = rs.getString(2);
- assertEquals(strArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectMultipleArrayColumns() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array[3], a_double_array[2] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 36.763d;
- Double a_double = rs.getDouble(2);
- assertEquals(doubleArr[0], a_double);
- String result = rs.getString(1);
- assertEquals(strArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSameArrayColumnMultipleTimesWithDifferentIndices() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array[1], a_string_array[2], " +
- "a_string_array[3], a_double_array[1], a_double_array[2], a_double_array[3] " +
- "FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- assertEquals("ABC", rs.getString(1));
- assertEquals("CEDF", rs.getString(2));
- assertEquals("XYZWER", rs.getString(3));
- assertEquals(25.343, rs.getDouble(4), 0.0);
- assertEquals(36.763, rs.getDouble(5), 0.0);
- assertEquals(37.56, rs.getDouble(6), 0.0);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSameArrayColumnMultipleTimesWithSameIndices() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array[3], a_string_array[3] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- String result = rs.getString(1);
- assertEquals(strArr[0], result);
- result = rs.getString(2);
- assertEquals(strArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testSelectSpecificIndexOfAVariableArray() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_string_array[3] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = "XYZWER";
- String result = rs.getString(1);
- assertEquals(strArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testWithOutOfRangeIndex() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT a_double_array[100] FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- PhoenixArray resultArray = (PhoenixArray) rs.getArray(1);
- assertNull(resultArray);
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArrayLengthFunctionForVariableLength() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT ARRAY_LENGTH(a_string_array) FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- int result = rs.getInt(1);
- assertEquals(result, 4);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
-
- @Test
- public void testArrayLengthFunctionForFixedLength() throws Exception {
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- initTablesWithArrays(table, tenantId, null, false, getUrl());
- String query = "SELECT ARRAY_LENGTH(a_double_array) FROM " + table;
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- int result = rs.getInt(1);
- assertEquals(result, 4);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArraySizeRoundtrip() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(),
- getDefaultSplits(tenantId), null);
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- ResultSet rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("x_long_array")));
- assertTrue(rs.next());
- assertEquals(5, rs.getInt("ARRAY_SIZE"));
- assertFalse(rs.next());
-
- rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("a_string_array")));
- assertTrue(rs.next());
- assertEquals(3, rs.getInt("ARRAY_SIZE"));
- assertFalse(rs.next());
-
- rs = conn.getMetaData().getColumns(null, null, StringUtil.escapeLike(table), StringUtil.escapeLike(SchemaUtil.normalizeIdentifier("a_double_array")));
- assertTrue(rs.next());
- assertEquals(0, rs.getInt("ARRAY_SIZE"));
- assertTrue(rs.wasNull());
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testVarLengthArrComparisonInWhereClauseWithSameArrays() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement()
- .execute(
- "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] {"abc","def", "ghi","jkl"};
- Array array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- s = new String[] {"abc","def", "ghi","jkl"};
- array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(3, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT k, a_string_array[2] FROM " + table + " where a_string_array=b_string_array");
- assertTrue(rs.next());
- assertEquals("a",rs.getString(1));
- assertEquals("def",rs.getString(2));
- conn.close();
- }
-
- @Test
- public void testVarLengthArrComparisonInWhereClauseWithDiffSizeArrays() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement()
- .execute(
- "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] { "abc", "def", "ghi", "jkll" };
- Array array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- s = new String[] { "abc", "def", "ghi", "jklm" };
- array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(3, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery(
- "SELECT k, a_string_array[2] FROM " + table + " where a_string_array<b_string_array");
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("def", rs.getString(2));
- conn.close();
- }
-
- @Test
- public void testVarLengthArrComparisonWithNulls() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement()
- .execute(
- "CREATE TABLE " + table + " ( k VARCHAR PRIMARY KEY, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4])");
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
- Array array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
- array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(3, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery(
- "SELECT k, a_string_array[2] FROM " + table + " where a_string_array>b_string_array");
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("def", rs.getString(2));
- conn.close();
- }
-
- @Test
- public void testUpsertValuesWithNull() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- String query = "upsert into " + table + " (ORGANIZATION_ID,ENTITY_ID,a_double_array) values('" + tenantId
- + "','00A123122312312',null)";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- // at
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- int executeUpdate = statement.executeUpdate();
- assertEquals(1, executeUpdate);
- conn.commit();
- statement.close();
- conn.close();
- // create another connection
- props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- query = "SELECT ARRAY_ELEM(a_double_array,2) FROM " + table;
- statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- // Need to support primitive
- Double[] doubleArr = new Double[1];
- doubleArr[0] = 0.0d;
- conn.createArrayOf("DOUBLE", doubleArr);
- Double result = rs.getDouble(1);
- assertEquals(doubleArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testUpsertValuesWithNullUsingPreparedStmt() throws Exception {
-
- String tenantId = getOrganizationId();
- String table = createTableWithArray(getUrl(), getDefaultSplits(tenantId), null);
- String query = "upsert into " + table + " (ORGANIZATION_ID,ENTITY_ID,a_string_array) values(?, ?, ?)";
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- // at
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.setString(1, tenantId);
- statement.setString(2, "00A123122312312");
- statement.setNull(3, Types.ARRAY);
- int executeUpdate = statement.executeUpdate();
- assertEquals(1, executeUpdate);
- conn.commit();
- statement.close();
- conn.close();
- // create another connection
- props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- query = "SELECT ARRAY_ELEM(a_string_array,1) FROM " + table;
- statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue(rs.next());
- String[] strArr = new String[1];
- strArr[0] = null;
- conn.createArrayOf("VARCHAR", strArr);
- String result = rs.getString(1);
- assertEquals(strArr[0], result);
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testPKWithArray() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement()
- .execute(
- "CREATE TABLE " + table + " ( k VARCHAR, a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4] \n"
- + " CONSTRAINT pk PRIMARY KEY (k, b_string_array)) \n");
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?,?,?)");
- stmt.setString(1, "a");
- String[] s = new String[] { "abc", "def", "ghi", "jkll", null, null, "xxx" };
- Array array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(2, array);
- s = new String[] { "abc", "def", "ghi", "jkll", null, null, null, "xxx" };
- array = conn.createArrayOf("VARCHAR", s);
- stmt.setArray(3, array);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery(
- "SELECT k, a_string_array[2] FROM " + table + " where b_string_array[8]='xxx'");
- assertTrue(rs.next());
- assertEquals("a", rs.getString(1));
- assertEquals("def", rs.getString(2));
- conn.close();
- }
-
- @Test
- public void testPKWithArrayNotInEnd() throws Exception {
- Connection conn;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- try {
- conn.createStatement().execute(
- "CREATE TABLE " + table + " ( a_string_array VARCHAR(100) ARRAY[4], b_string_array VARCHAR(100) ARRAY[4], k VARCHAR \n"
- + " CONSTRAINT pk PRIMARY KEY (b_string_array, k))");
- conn.close();
- fail();
- } catch (SQLException e) {
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
-
- }
-
- @Test
- public void testArrayRefToLiteral() throws Exception {
- Connection conn;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- try {
- PreparedStatement stmt = conn.prepareStatement("select ?[2] from \"SYSTEM\".\"catalog\" limit 1");
- Array array = conn.createArrayOf("CHAR", new String[] {"a","b","c"});
- stmt.setArray(1, array);
- ResultSet rs = stmt.executeQuery();
- assertTrue(rs.next());
- assertEquals("b", rs.getString(1));
- assertFalse(rs.next());
- } catch (SQLException e) {
- } finally {
- if (conn != null) {
- conn.close();
- }
- }
-
- }
-
- private static String createTableWithAllArrayTypes(String url, byte[][] bs, Object object) throws SQLException {
- String tableName = generateUniqueName();
- String ddlStmt = "create table "
- + tableName
- + " (organization_id char(15) not null, \n"
- + " entity_id char(15) not null,\n"
- + " boolean_array boolean array,\n"
- + " byte_array tinyint array,\n"
- + " double_array double array[],\n"
- + " float_array float array,\n"
- + " int_array integer array,\n"
- + " long_array bigint[5],\n"
- + " short_array smallint array,\n"
- + " string_array varchar(100) array[3],\n"
- + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
- + ")";
- BaseTest.createTestTable(url, ddlStmt, bs, null);
- return tableName;
- }
-
- private static String createTableWithArray(String url, byte[][] bs, Object object) throws SQLException {
- String tableName = generateUniqueName();
- String ddlStmt = "create table "
- + tableName
- + " (organization_id char(15) not null, \n"
- + " entity_id char(15) not null,\n"
- + " a_string_array varchar(100) array[3],\n"
- + " b_string varchar(100),\n"
- + " a_integer integer,\n"
- + " a_date date,\n"
- + " a_time time,\n"
- + " a_timestamp timestamp,\n"
- + " x_decimal decimal(31,10),\n"
- + " x_long_array bigint[5],\n"
- + " x_integer integer,\n"
- + " a_byte_array tinyint array,\n"
- + " a_short smallint,\n"
- + " a_float float,\n"
- + " a_double_array double array[],\n"
- + " a_unsigned_float unsigned_float,\n"
- + " a_unsigned_double unsigned_double \n"
- + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
- + ")";
- BaseTest.createTestTable(url, ddlStmt, bs, null);
- return tableName;
- }
-
- private static String createSimpleTableWithArray(String url, byte[][] bs, Object object) throws SQLException {
- String tableName = generateUniqueName();
- String ddlStmt = "create table "
- + tableName
- + " (organization_id char(15) not null, \n"
- + " entity_id char(15) not null,\n"
- + " x_double double,\n"
- + " a_double_array double array[],\n"
- + " a_char_array char(5) array[],\n"
- + " CONSTRAINT pk PRIMARY KEY (organization_id, entity_id)\n"
- + ")";
- BaseTest.createTestTable(url, ddlStmt, bs, null);
- return tableName;
- }
-
- private static void initSimpleArrayTable(String tableName, String tenantId, Date date, boolean useNull) throws Exception {
- Properties props = new Properties();
-
- Connection conn = DriverManager.getConnection(getUrl(), props);
- try {
- // Insert all rows at ts
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + tableName +
- "(" +
- " ORGANIZATION_ID, " +
- " ENTITY_ID, " +
- " x_double, " +
- " a_double_array, a_char_array)" +
- "VALUES (?, ?, ?, ?, ?)");
- stmt.setString(1, tenantId);
- stmt.setString(2, ROW1);
- stmt.setDouble(3, 1.2d);
- // Need to support primitive
- Double[] doubleArr = new Double[2];
- doubleArr[0] = 64.87;
- doubleArr[1] = 89.96;
- //doubleArr[2] = 9.9;
- Array array = conn.createArrayOf("DOUBLE", doubleArr);
- stmt.setArray(4, array);
-
- // create character array
- String[] charArr = new String[2];
- charArr[0] = "a";
- charArr[1] = "b";
- array = conn.createArrayOf("CHAR", charArr);
- stmt.setArray(5, array);
- stmt.execute();
-
- conn.commit();
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testArrayConstructorWithMultipleRows1() throws Exception {
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
- conn.createStatement().execute(ddl);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 6,3)");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 2,4)");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 6,3)");
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT ARRAY[a,b]) from " + table);
- assertTrue(rs.next());
- assertEquals(2, rs.getInt(1));
- }
-
- @Test
- public void testArrayConstructorWithMultipleRows2() throws Exception {
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a INTEGER, b INTEGER)";
- conn.createStatement().execute(ddl);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 6,3)");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 2,4)");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 6,3)");
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT ARRAY[a,b] from " + table + " ");
- assertTrue(rs.next());
- Array arr = conn.createArrayOf("INTEGER", new Object[]{6, 3});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("INTEGER", new Object[]{2, 4});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("INTEGER", new Object[]{6, 3});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- }
-
- @Test
- public void testArrayConstructorWithMultipleRows3() throws Exception {
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
- conn.createStatement().execute(ddl);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT ARRAY[a,b] from " + table + " ");
- assertTrue(rs.next());
- Array arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("VARCHAR", new Object[]{"abc", "dfg"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- }
-
- @Test
- public void testArrayConstructorWithMultipleRows4() throws Exception {
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
- conn.createStatement().execute(ddl);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT COUNT(DISTINCT ARRAY[a,b]) from " + table);
- assertTrue(rs.next());
- assertEquals(2, rs.getInt(1));
- }
-
- @Test
- public void testArrayConstructorWithMultipleRows5() throws Exception {
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY, a VARCHAR, b VARCHAR)";
- conn.createStatement().execute(ddl);
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('a', 'foo', 'abc')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('b', 'abc', 'dfg')");
- stmt.execute();
- stmt = conn.prepareStatement("UPSERT INTO " + table + " (region_name, a, b) VALUES('c', 'foo', 'abc')");
- stmt.execute();
- conn.commit();
- conn.close();
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- rs = conn.createStatement().executeQuery("SELECT ARRAY_APPEND(ARRAY[a,b], 'oo') from " + table);
- assertTrue(rs.next());
- Array arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc", "oo"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("VARCHAR", new Object[]{"abc", "dfg", "oo"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- arr = conn.createArrayOf("VARCHAR", new Object[]{"foo", "abc", "oo"});
- assertEquals(arr, rs.getArray(1));
- rs.next();
- }
-
- @Test
- public void testPKWithDescArray() throws Exception {
- Connection conn;
- PreparedStatement stmt;
- ResultSet rs;
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- conn.createStatement()
- .execute(
- "CREATE TABLE " + table + " ( a VARCHAR ARRAY PRIMARY KEY DESC)\n");
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?)");
- Array a1 = conn.createArrayOf("VARCHAR", new String[] { "a", "ba" });
- stmt.setArray(1, a1);
- stmt.execute();
- Array a2 = conn.createArrayOf("VARCHAR", new String[] { "a", "c" });
- stmt.setArray(1, a2);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT a FROM " + table + " ORDER BY a DESC");
- assertTrue(rs.next());
- assertEquals(a2, rs.getArray(1));
- assertTrue(rs.next());
- assertEquals(a1, rs.getArray(1));
- assertFalse(rs.next());
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- stmt = conn.prepareStatement("UPSERT INTO " + table + " VALUES(?)");
- Array a3 = conn.createArrayOf("VARCHAR", new String[] { "a", "b" });
- stmt.setArray(1, a3);
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- rs = conn.createStatement().executeQuery("SELECT a FROM " + table + " ORDER BY a DESC");
- assertTrue(rs.next());
- assertEquals(a2, rs.getArray(1));
- assertTrue(rs.next());
- assertEquals(a1, rs.getArray(1));
- assertTrue(rs.next());
- assertEquals(a3, rs.getArray(1));
- assertFalse(rs.next());
- conn.close();
- }
-
- @Test
- public void testComparisonOperatorsForDesc1()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k >= array['a', 'b']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc2()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k >= array['a', 'c']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc3()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'c'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k > array['a', 'b']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc4()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k <= array['a', 'c']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc5()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k <= array['a', 'b']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc6()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k varchar array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array['a', 'b'])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k < array['a', 'c']");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc7()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName();
- String ddl = "create table " + table + " (k integer array primary key desc)";
- conn.createStatement().execute(ddl);
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- PreparedStatement stmt = conn.prepareStatement("upsert into " + table + " values (array[1, 2])");
- stmt.execute();
- conn.commit();
- conn.close();
-
- conn = DriverManager.getConnection(getUrl(), props);
- ResultSet rs;
- stmt = conn.prepareStatement("select * from " + table + " where k < array[1, 4]");
- rs = stmt.executeQuery();
- assertTrue(rs.next());
- }
-
- @Test
- public void testComparisonOperatorsForDesc8()throws Exception{
-
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String table = generateUniqueName
<TRUNCATED>
[10/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java
deleted file mode 100644
index 2ecc404..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SortMergeJoinIT.java
+++ /dev/null
@@ -1,2563 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-
-@RunWith(Parameterized.class)
-public class SortMergeJoinIT extends BaseJoinIT {
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY"
- }});
- testCases.add(new String[][] {
- {
- "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.0:supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I2.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I1.:item_id\"]"
- }});
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- "SORT-MERGE-JOIN (LEFT) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " AND (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- " CLIENT SORTED BY [\"I.0:supplier_id\"]",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT",
-
- "SORT-MERGE-JOIN (INNER) TABLES\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "AND\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I2.:item_id\"]\n" +
- " CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [\"I1.:item_id\"]"
- }});
- return testCases;
- }
-
-
- public SortMergeJoinIT(String[] indexDDL, String[] plans) {
- super(indexDDL, plans);
- }
-
- @Test
- public void testDefaultJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInnerJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertEquals(1, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertEquals(2, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertEquals(3, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertEquals(4, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertEquals(5, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertEquals(6, rs.getInt(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testLeftJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query[] = new String[3];
- query[0] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- query[1] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ " + tableName1 + ".\"item_id\", " + tableName1 + ".name, " + tableName2 + ".\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " LEFT JOIN " + tableName2 + " ON " + tableName1 + ".\"supplier_id\" = " + tableName2 + ".\"supplier_id\" ORDER BY \"item_id\"";
- query[2] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", " + tableName1 + ".name, supp.\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- for (int i = 0; i < query.length; i++) {
- PreparedStatement statement = conn.prepareStatement(query[i]);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
-
- assertFalse(rs.next());
- rs.close();
- statement.close();
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testRightJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName2 + " supp RIGHT JOIN " + tableName1 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInnerJoinWithPreFilters() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005' ORDER BY \"item_id\"";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005') ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
-
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testLeftJoinWithPreFilters() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005') ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithPostFilters() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName2 + " supp RIGHT JOIN " + tableName1 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005' ORDER BY \"item_id\"";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005' ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
-
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testStarJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String[] query = new String[5];
- query[0] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o JOIN "
- + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
- query[1] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o, "
- + tableName3 + " c, "
- + tableName1 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
- query[2] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o JOIN "
- + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
- query[3] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM (" + tableName4 + " o, "
- + tableName3 + " c), "
- + tableName1 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
- query[4] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o, ("
- + tableName3 + " c, "
- + tableName1 + " i) WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
- try {
- for (int i = 0; i < query.length; i++) {
- PreparedStatement statement = conn.prepareStatement(query[i]);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString("\"order_id\""), "000000000000001");
- assertEquals(rs.getString(2), "C4");
- assertEquals(rs.getString("C.name"), "C4");
- assertEquals(rs.getString(3), "T1");
- assertEquals(rs.getString("iName"), "T1");
- assertEquals(rs.getInt(4), 1000);
- assertEquals(rs.getInt("Quantity"), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "C3");
- assertEquals(rs.getString(3), "T6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "C2");
- assertEquals(rs.getString(3), "T2");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "C4");
- assertEquals(rs.getString(3), "T6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "C5");
- assertEquals(rs.getString(3), "T3");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testLeftJoinWithAggregation() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.name, sum(quantity) FROM " + tableName4 + " o LEFT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName4 + " o LEFT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC";
- String query3 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName1 + " i LEFT JOIN "
- + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T1");
- assertEquals(rs.getInt(2), 1000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T2");
- assertEquals(rs.getInt(2), 3000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T3");
- assertEquals(rs.getInt(2), 5000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T6");
- assertEquals(rs.getInt(2), 6000);
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000006");
- assertEquals(rs.getInt("q"), 6000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000003");
- assertEquals(rs.getInt("q"), 5000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000002");
- assertEquals(rs.getInt("q"), 3000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000001");
- assertEquals(rs.getInt("q"), 1000);
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query3);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000006");
- assertEquals(rs.getInt("q"), 6000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000003");
- assertEquals(rs.getInt("q"), 5000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000002");
- assertEquals(rs.getInt("q"), 3000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000001");
- assertEquals(rs.getInt("q"), 1000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000004");
- assertEquals(rs.getInt("q"), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000005");
- assertEquals(rs.getInt("q"), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "invalid001");
- assertEquals(rs.getInt("q"), 0);
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testRightJoinWithAggregation() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.name, sum(quantity) FROM " + tableName4 + " o RIGHT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName4 + " o RIGHT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "INVALID-1");
- assertEquals(rs.getInt(2), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T1");
- assertEquals(rs.getInt(2), 1000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T2");
- assertEquals(rs.getInt(2), 3000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T3");
- assertEquals(rs.getInt(2), 5000);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T4");
- assertEquals(rs.getInt(2), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T5");
- assertEquals(rs.getInt(2), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "T6");
- assertEquals(rs.getInt(2), 6000);
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000006");
- assertEquals(rs.getInt("q"), 6000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000003");
- assertEquals(rs.getInt("q"), 5000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000002");
- assertEquals(rs.getInt("q"), 3000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000001");
- assertEquals(rs.getInt("q"), 1000);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000004");
- assertEquals(rs.getInt("q"), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "0000000005");
- assertEquals(rs.getInt("q"), 0);
- assertTrue (rs.next());
- assertEquals(rs.getString("iid"), "invalid001");
- assertEquals(rs.getInt("q"), 0);
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testLeftRightJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
- + "(" + tableName1 + " i RIGHT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\")"
- + " ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S5");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S4");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S3");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testRightLeftJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query1 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName1 + " i RIGHT JOIN "
- + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\"";
- String query2 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
- + "(" + tableName1 + " i LEFT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\")"
- + " ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "S5");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testMultiLeftJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String[] queries = {
- "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\"",
- "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
- + "(" + tableName1 + " i LEFT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\") "
- + "ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\""};
- try {
- for (String query : queries) {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testMultiRightJoin() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "S5");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S4");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S3");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- // Basically a copy of testMultiRightJoin, but with a very small result scan chunk size
- // to test that repeated row keys within a single chunk are handled properly
- @Test
- public void testMultiRightJoin_SmallChunkSize() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- props.setProperty(QueryServices.SCAN_RESULT_CHUNK_SIZE, "1");
- Connection conn = DriverManager.getConnection(getUrl(), props);
-
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "S5");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S4");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertNull(rs.getString(2));
- assertEquals(rs.getString(3), "S3");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertNull(rs.getString(1));
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 0);
- assertNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 1000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 2000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "S1");
- assertEquals(rs.getInt(4), 3000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "S6");
- assertEquals(rs.getInt(4), 4000);
- assertNotNull(rs.getDate(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "S2");
- assertEquals(rs.getInt(4), 5000);
- assertNotNull(rs.getDate(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithWildcard() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName1 + " LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000001");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T1");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 100);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T1");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
- assertEquals(rs.getString("supp.name"), "S1");
- assertEquals(rs.getString("supp.phone"), "888-888-1111");
- assertEquals(rs.getString("supp.address"), "101 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10001");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000002");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T2");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 200);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 8);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T2");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
- assertEquals(rs.getString("supp.name"), "S1");
- assertEquals(rs.getString("supp.phone"), "888-888-1111");
- assertEquals(rs.getString("supp.address"), "101 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10001");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000003");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T3");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 300);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 12);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T3");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
- assertEquals(rs.getString("supp.name"), "S2");
- assertEquals(rs.getString("supp.phone"), "888-888-2222");
- assertEquals(rs.getString("supp.address"), "202 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10002");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000004");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T4");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 400);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 6);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T4");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
- assertEquals(rs.getString("supp.name"), "S2");
- assertEquals(rs.getString("supp.phone"), "888-888-2222");
- assertEquals(rs.getString("supp.address"), "202 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10002");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000005");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T5");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 500);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000005");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T5");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000005");
- assertEquals(rs.getString("supp.name"), "S5");
- assertEquals(rs.getString("supp.phone"), "888-888-5555");
- assertEquals(rs.getString("supp.address"), "505 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10005");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000006");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T6");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 600);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000006");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T6");
- assertEquals(rs.getString("SUPP.supplier_id"), "0000000006");
- assertEquals(rs.getString("supp.name"), "S6");
- assertEquals(rs.getString("supp.phone"), "888-888-6666");
- assertEquals(rs.getString("supp.address"), "606 YYY Street");
- assertEquals(rs.getString("supp.loc_id"), "10006");
- assertTrue (rs.next());
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "invalid001");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "INVALID-1");
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 0);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 0);
- assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 0);
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000000");
- assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Invalid item for join test");
- assertNull(rs.getString("SUPP.supplier_id"));
- assertNull(rs.getString("supp.name"));
- assertNull(rs.getString("supp.phone"));
- assertNull(rs.getString("supp.address"));
- assertNull(rs.getString("supp.loc_id"));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithTableWildcard() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ s.*, "+ tableName1 + ".*, \"order_id\" FROM " + tableName4 + " o RIGHT JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
- + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- ResultSetMetaData md = rs.getMetaData();
- assertEquals(md.getColumnCount(), 13);
-
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "S5");
- assertEquals(rs.getString(3), "888-888-5555");
- assertEquals(rs.getString(4), "505 YYY Street");
- assertEquals(rs.getString(5), "10005");
- assertEquals(rs.getString(6), "0000000005");
- assertEquals(rs.getString(7), "T5");
- assertEquals(rs.getInt(8), 500);
- assertEquals(rs.getInt(9), 8);
- assertEquals(rs.getInt(10), 15);
- assertEquals(rs.getString(11), "0000000005");
- assertEquals(rs.getString(12), "Item T5");
- assertNull(rs.getString(13));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "S4");
- assertEquals(rs.getString(3), "888-888-4444");
- assertEquals(rs.getString(4), "404 YYY Street");
- assertNull(rs.getString(5));
- assertNull(rs.getString(6));
- assertNull(rs.getString(7));
- assertEquals(rs.getInt(8), 0);
- assertEquals(rs.getInt(9), 0);
- assertEquals(rs.getInt(10), 0);
- assertNull(rs.getString(11));
- assertNull(rs.getString(12));
- assertNull(rs.getString(13));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "S3");
- assertEquals(rs.getString(3), "888-888-3333");
- assertEquals(rs.getString(4), "303 YYY Street");
- assertNull(rs.getString(5));
- assertNull(rs.getString(6));
- assertNull(rs.getString(7));
- assertEquals(rs.getInt(8), 0);
- assertEquals(rs.getInt(9), 0);
- assertEquals(rs.getInt(10), 0);
- assertNull(rs.getString(11));
- assertNull(rs.getString(12));
- assertNull(rs.getString(13));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S2");
- assertEquals(rs.getString(3), "888-888-2222");
- assertEquals(rs.getString(4), "202 YYY Street");
- assertEquals(rs.getString(5), "10002");
- assertEquals(rs.getString(6), "0000000004");
- assertEquals(rs.getString(7), "T4");
- assertEquals(rs.getInt(8), 400);
- assertEquals(rs.getInt(9), 6);
- assertEquals(rs.getInt(10), 10);
- assertEquals(rs.getString(11), "0000000002");
- assertEquals(rs.getString(12), "Item T4");
- assertNull(rs.getString(13));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "S1");
- assertEquals(rs.getString(3), "888-888-1111");
- assertEquals(rs.getString(4), "101 YYY Street");
- assertEquals(rs.getString(5), "10001");
- assertEquals(rs.getString(6), "0000000001");
- assertEquals(rs.getString(7), "T1");
- assertEquals(rs.getInt(8), 100);
- assertEquals(rs.getInt(9), 5);
- assertEquals(rs.getInt(10), 10);
- assertEquals(rs.getString(11), "0000000001");
- assertEquals(rs.getString(12), "Item T1");
- assertEquals(rs.getString(13), "000000000000001");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
- assertEquals(rs.getString(3), "888-888-6666");
- assertEquals(rs.getString(4), "606 YYY Street");
- assertEquals(rs.getString(5), "10006");
- assertEquals(rs.getString(6), "0000000006");
- assertEquals(rs.getString(7), "T6");
- assertEquals(rs.getInt(8), 600);
- assertEquals(rs.getInt(9), 8);
- assertEquals(rs.getInt(10), 15);
- assertEquals(rs.getString(11), "0000000006");
- assertEquals(rs.getString(12), "Item T6");
- assertEquals(rs.getString(13), "000000000000002");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "S1");
- assertEquals(rs.getString(3), "888-888-1111");
- assertEquals(rs.getString(4), "101 YYY Street");
- assertEquals(rs.getString(5), "10001");
- assertEquals(rs.getString(6), "0000000002");
- assertEquals(rs.getString(7), "T2");
- assertEquals(rs.getInt(8), 200);
- assertEquals(rs.getInt(9), 5);
- assertEquals(rs.getInt(10), 8);
- assertEquals(rs.getString(11), "0000000001");
- assertEquals(rs.getString(12), "Item T2");
- assertEquals(rs.getString(13), "000000000000003");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "S6");
- assertEquals(rs.getString(3), "888-888-6666");
- assertEquals(rs.getString(4), "606 YYY Street");
- assertEquals(rs.getString(5), "10006");
- assertEquals(rs.getString(6), "0000000006");
- assertEquals(rs.getString(7), "T6");
- assertEquals(rs.getInt(8), 600);
- assertEquals(rs.getInt(9), 8);
- assertEquals(rs.getInt(10), 15);
- assertEquals(rs.getString(11), "0000000006");
- assertEquals(rs.getString(12), "Item T6");
- assertEquals(rs.getString(13), "000000000000004");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "S2");
- assertEquals(rs.getString(3), "888-888-2222");
- assertEquals(rs.getString(4), "202 YYY Street");
- assertEquals(rs.getString(5), "10002");
- assertEquals(rs.getString(6), "0000000003");
- assertEquals(rs.getString(7), "T3");
- assertEquals(rs.getInt(8), 300);
- assertEquals(rs.getInt(9), 8);
- assertEquals(rs.getInt(10), 12);
- assertEquals(rs.getString(11), "0000000002");
- assertEquals(rs.getString(12), "Item T3");
- assertEquals(rs.getString(13), "000000000000005");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinMultiJoinKeys() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ c.name, s.name FROM " + tableName3 + " c LEFT JOIN " + tableName2 + " s ON \"customer_id\" = \"supplier_id\" AND c.loc_id = s.loc_id AND substr(s.name, 2, 1) = substr(c.name, 2, 1) ORDER BY \"customer_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C1");
- assertEquals(rs.getString(2), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C2");
- assertNull(rs.getString(2));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C3");
- assertEquals(rs.getString(2), "S3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C4");
- assertNull(rs.getString(2));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C5");
- assertEquals(rs.getString(2), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "C6");
- assertNull(rs.getString(2));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithDifferentNumericJoinKeyTypes() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, i.price, discount2, quantity FROM " + tableName4 + " o INNER JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" AND o.price = (i.price * (100 - discount2)) / 100.0 WHERE quantity < 5000";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000004");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getInt(3), 600);
- assertEquals(rs.getInt(4), 15);
- assertEquals(rs.getInt(5), 4000);
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithDifferentDateJoinKeyTypes() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, o.\"DATE\" FROM " + tableName4 + " o INNER JOIN "
- + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" AND o.\"DATE\" = c.\"DATE\" ORDER BY \"order_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000001");
- assertEquals(rs.getString(2), "C4");
- assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-22 14:22:56").getTime()));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000002");
- assertEquals(rs.getString(2), "C3");
- assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000003");
- assertEquals(rs.getString(2), "C2");
- assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 16:45:07").getTime()));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "000000000000005");
- assertEquals(rs.getString(2), "C5");
- assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-27 09:37:50").getTime()));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithIncomparableJoinKeyTypes() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, i.price, discount2, quantity FROM " + tableName4 + " o INNER JOIN "
- + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" AND o.price / 100 = substr(i.name, 2, 1)";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- statement.executeQuery();
- fail("Should have got SQLException.");
- } catch (SQLException e) {
- assertEquals(e.getErrorCode(), SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinPlanWithIndex() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON substr(item.name, 2, 1) = substr(supp.name, 2, 1) AND (supp.name BETWEEN 'S1' AND 'S5') WHERE item.name BETWEEN 'T1' AND 'T5' ORDER BY \"item_id\"";
- String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE (item.name = 'T1' OR item.name = 'T5') AND (supp.name = 'S1' OR supp.name = 'S5') ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000003");
- assertEquals(rs.getString(4), "S3");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000004");
- assertEquals(rs.getString(4), "S4");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testJoinWithSkipMergeOptimization() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
- String query = "SELECT /*+ USE
<TRUNCATED>
[14/25] phoenix git commit: PHOENIX-4245 Breakup IndexIT into several
integration tests so as not to create too many tables in one test
Posted by ja...@apache.org.
PHOENIX-4245 Breakup IndexIT into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/fd777640
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/fd777640
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/fd777640
Branch: refs/heads/master
Commit: fd7776407737cf6cc5cb95eb8c5b9380af4b560c
Parents: 527f786
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 13:24:20 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 17:51:57 2017 -0700
----------------------------------------------------------------------
.../index/GlobalImmutableNonTxIndexIT.java | 38 ++++++++++++++++++++
.../end2end/index/GlobalImmutableTxIndexIT.java | 38 ++++++++++++++++++++
.../index/GlobalMutableNonTxIndexIT.java | 38 ++++++++++++++++++++
.../end2end/index/GlobalMutableTxIndexIT.java | 38 ++++++++++++++++++++
.../apache/phoenix/end2end/index/IndexIT.java | 17 ++-------
.../index/LocalImmutableNonTxIndexIT.java | 38 ++++++++++++++++++++
.../end2end/index/LocalImmutableTxIndexIT.java | 38 ++++++++++++++++++++
.../end2end/index/LocalMutableNonTxIndexIT.java | 38 ++++++++++++++++++++
.../end2end/index/LocalMutableTxIndexIT.java | 37 +++++++++++++++++++
9 files changed, 305 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
new file mode 100644
index 0000000..52b219d
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableNonTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class GlobalImmutableNonTxIndexIT extends IndexIT {
+
+ public GlobalImmutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="GlobalImmutableNonTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { false, false, false, false }, { false, false, false, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
new file mode 100644
index 0000000..58eab8c
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalImmutableTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class GlobalImmutableTxIndexIT extends IndexIT {
+
+ public GlobalImmutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="GlobalImmutableTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { false, false, true, false }, { false, false, true, true },
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
new file mode 100644
index 0000000..9fe1938
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableNonTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class GlobalMutableNonTxIndexIT extends IndexIT {
+
+ public GlobalMutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="GlobalMutableNonTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { false, true, false, false }, { false, true, false, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
new file mode 100644
index 0000000..4536959
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/GlobalMutableTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class GlobalMutableTxIndexIT extends IndexIT {
+
+ public GlobalMutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="GlobalMutableTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { false, true, true, false }, { false, true, true, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
index f8856e3..b540ad1 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexIT.java
@@ -37,8 +37,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Properties;
import java.util.Random;
@@ -79,10 +77,9 @@ import org.apache.phoenix.util.TransactionUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public class IndexIT extends ParallelStatsDisabledIT {
+public abstract class IndexIT extends ParallelStatsDisabledIT {
private static final Random RAND = new Random();
private final boolean localIndex;
@@ -90,7 +87,7 @@ public class IndexIT extends ParallelStatsDisabledIT {
private final boolean mutable;
private final String tableDDLOptions;
- public IndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ protected IndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
this.localIndex = localIndex;
this.transactional = transactional;
this.mutable = mutable;
@@ -116,16 +113,6 @@ public class IndexIT extends ParallelStatsDisabledIT {
this.tableDDLOptions = optionBuilder.toString();
}
- @Parameters(name="IndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
- public static Collection<Boolean[]> data() {
- return Arrays.asList(new Boolean[][] {
- { false, false, false, false }, { false, false, false, true }, { false, false, true, false }, { false, false, true, true },
- { false, true, false, false }, { false, true, false, true }, { false, true, true, false }, { false, true, true, true },
- { true, false, false, false }, { true, false, false, true }, { true, false, true, false }, { true, false, true, true },
- { true, true, false, false }, { true, true, false, true }, { true, true, true, false }, { true, true, true, true }
- });
- }
-
@Test
public void testIndexWithNullableFixedWithCols() throws Exception {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
new file mode 100644
index 0000000..f2d18d2
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class LocalImmutableNonTxIndexIT extends IndexIT {
+
+ public LocalImmutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="LocalImmutableNonTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { true, false, false, false }, { true, false, false, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
new file mode 100644
index 0000000..9e6fd5f
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class LocalImmutableTxIndexIT extends IndexIT {
+
+ public LocalImmutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="LocalImmutableTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { true, false, true, false }, { true, false, true, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
new file mode 100644
index 0000000..9785d20
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class LocalMutableNonTxIndexIT extends IndexIT {
+
+ public LocalMutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="LocalMutableNonTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { true, true, false, false }, { true, true, false, true }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/fd777640/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
new file mode 100644
index 0000000..c09a8c0
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
@@ -0,0 +1,37 @@
+/*
+ * 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.end2end.index;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.runners.Parameterized.Parameters;
+
+public class LocalMutableTxIndexIT extends IndexIT {
+
+ public LocalMutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
+ super(localIndex, mutable, transactional, columnEncoded);
+ }
+
+ @Parameters(name="LocalMutableTxIndexIT_localIndex={0},mutable={1},transactional={2},columnEncoded={3}") // name is used by failsafe as file name in reports
+ public static Collection<Boolean[]> data() {
+ return Arrays.asList(new Boolean[][] {
+ { true, true, true, false }, { true, true, true, true }
+ });
+ }
+}
[04/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
new file mode 100644
index 0000000..8e7bfe2
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/SortMergeJoinIT.java
@@ -0,0 +1,2563 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+@RunWith(Parameterized.class)
+public class SortMergeJoinIT extends BaseJoinIT {
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {}, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY"
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.0:supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER Join.idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I2.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I1.:item_id\"]"
+ }});
+ testCases.add(new String[][] {
+ {
+ "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ "SORT-MERGE-JOIN (LEFT) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"S.:supplier_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " AND (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ " CLIENT SORTED BY [\"I.0:supplier_id\"]",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT",
+
+ "SORT-MERGE-JOIN (INNER) TABLES\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "AND\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I2.:item_id\"]\n" +
+ " CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [\"I1.:item_id\"]"
+ }});
+ return testCases;
+ }
+
+
+ public SortMergeJoinIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Test
+ public void testDefaultJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInnerJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertEquals(1, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertEquals(2, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertEquals(3, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertEquals(4, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertEquals(5, rs.getInt(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertEquals(6, rs.getInt(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query[] = new String[3];
+ query[0] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ query[1] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ " + tableName1 + ".\"item_id\", " + tableName1 + ".name, " + tableName2 + ".\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " LEFT JOIN " + tableName2 + " ON " + tableName1 + ".\"supplier_id\" = " + tableName2 + ".\"supplier_id\" ORDER BY \"item_id\"";
+ query[2] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", " + tableName1 + ".name, supp.\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ for (int i = 0; i < query.length; i++) {
+ PreparedStatement statement = conn.prepareStatement(query[i]);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ rs.close();
+ statement.close();
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRightJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName2 + " supp RIGHT JOIN " + tableName1 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "0000000006");
+ assertEquals(rs.getString(4), "S6");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInnerJoinWithPreFilters() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005' ORDER BY \"item_id\"";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005') ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoinWithPreFilters() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005') ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "T6");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "invalid001");
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertNull(rs.getString(4));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithPostFilters() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName2 + " supp RIGHT JOIN " + tableName1 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005' ORDER BY \"item_id\"";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005' ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testStarJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String[] query = new String[5];
+ query[0] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o JOIN "
+ + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
+ query[1] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o, "
+ + tableName3 + " c, "
+ + tableName1 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[2] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o JOIN "
+ + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\"";
+ query[3] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM (" + tableName4 + " o, "
+ + tableName3 + " c), "
+ + tableName1 + " i WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ query[4] = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, i.name iname, quantity, o.\"DATE\" FROM " + tableName4 + " o, ("
+ + tableName3 + " c, "
+ + tableName1 + " i) WHERE o.\"item_id\" = i.\"item_id\" AND o.\"customer_id\" = c.\"customer_id\" ORDER BY \"order_id\"";
+ try {
+ for (int i = 0; i < query.length; i++) {
+ PreparedStatement statement = conn.prepareStatement(query[i]);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString("\"order_id\""), "000000000000001");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getString("C.name"), "C4");
+ assertEquals(rs.getString(3), "T1");
+ assertEquals(rs.getString("iName"), "T1");
+ assertEquals(rs.getInt(4), 1000);
+ assertEquals(rs.getInt("Quantity"), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "C3");
+ assertEquals(rs.getString(3), "T6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "C2");
+ assertEquals(rs.getString(3), "T2");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getString(3), "T6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "C5");
+ assertEquals(rs.getString(3), "T3");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftJoinWithAggregation() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.name, sum(quantity) FROM " + tableName4 + " o LEFT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName4 + " o LEFT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC";
+ String query3 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName1 + " i LEFT JOIN "
+ + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getInt(2), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getInt(2), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getInt(2), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getInt(2), 6000);
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query3);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000004");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000005");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "invalid001");
+ assertEquals(rs.getInt("q"), 0);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRightJoinWithAggregation() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.name, sum(quantity) FROM " + tableName4 + " o RIGHT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.name ORDER BY i.name";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ i.\"item_id\" iid, sum(quantity) q FROM " + tableName4 + " o RIGHT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" GROUP BY i.\"item_id\" ORDER BY q DESC NULLS LAST, iid";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "INVALID-1");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T1");
+ assertEquals(rs.getInt(2), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T2");
+ assertEquals(rs.getInt(2), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T3");
+ assertEquals(rs.getInt(2), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T4");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T5");
+ assertEquals(rs.getInt(2), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "T6");
+ assertEquals(rs.getInt(2), 6000);
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000006");
+ assertEquals(rs.getInt("q"), 6000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000003");
+ assertEquals(rs.getInt("q"), 5000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000002");
+ assertEquals(rs.getInt("q"), 3000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000001");
+ assertEquals(rs.getInt("q"), 1000);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000004");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "0000000005");
+ assertEquals(rs.getInt("q"), 0);
+ assertTrue (rs.next());
+ assertEquals(rs.getString("iid"), "invalid001");
+ assertEquals(rs.getInt("q"), 0);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testLeftRightJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
+ + "(" + tableName1 + " i RIGHT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\")"
+ + " ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testRightLeftJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query1 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName1 + " i RIGHT JOIN "
+ + tableName4 + " o ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\"";
+ String query2 = "SELECT \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
+ + "(" + tableName1 + " i LEFT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\")"
+ + " ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "INVALID-1");
+ assertNull(rs.getString(3));
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testMultiLeftJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String[] queries = {
+ "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" LEFT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\"",
+ "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o LEFT JOIN "
+ + "(" + tableName1 + " i LEFT JOIN " + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\") "
+ + "ON o.\"item_id\" = i.\"item_id\" ORDER BY \"order_id\""};
+ try {
+ for (String query : queries) {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testMultiRightJoin() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ // Basically a copy of testMultiRightJoin, but with a very small result scan chunk size
+ // to test that repeated row keys within a single chunk are handled properly
+ @Test
+ public void testMultiRightJoin_SmallChunkSize() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(QueryServices.SCAN_RESULT_CHUNK_SIZE, "1");
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, s.name, quantity, \"DATE\" FROM " + tableName4 + " o RIGHT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "S5");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S4");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertNull(rs.getString(2));
+ assertEquals(rs.getString(3), "S3");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertNull(rs.getString(1));
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 0);
+ assertNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 1000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 2000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "S1");
+ assertEquals(rs.getInt(4), 3000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getString(3), "S6");
+ assertEquals(rs.getInt(4), 4000);
+ assertNotNull(rs.getDate(5));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "S2");
+ assertEquals(rs.getInt(4), 5000);
+ assertNotNull(rs.getDate(5));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithWildcard() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ * FROM " + tableName1 + " LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T1");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 100);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T1");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
+ assertEquals(rs.getString("supp.name"), "S1");
+ assertEquals(rs.getString("supp.phone"), "888-888-1111");
+ assertEquals(rs.getString("supp.address"), "101 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T2");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 200);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 5);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 8);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000001");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T2");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000001");
+ assertEquals(rs.getString("supp.name"), "S1");
+ assertEquals(rs.getString("supp.phone"), "888-888-1111");
+ assertEquals(rs.getString("supp.address"), "101 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000003");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T3");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 300);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 12);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T3");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
+ assertEquals(rs.getString("supp.name"), "S2");
+ assertEquals(rs.getString("supp.phone"), "888-888-2222");
+ assertEquals(rs.getString("supp.address"), "202 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000004");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T4");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 400);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 6);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 10);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000002");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T4");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000002");
+ assertEquals(rs.getString("supp.name"), "S2");
+ assertEquals(rs.getString("supp.phone"), "888-888-2222");
+ assertEquals(rs.getString("supp.address"), "202 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000005");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T5");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 500);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000005");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T5");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000005");
+ assertEquals(rs.getString("supp.name"), "S5");
+ assertEquals(rs.getString("supp.phone"), "888-888-5555");
+ assertEquals(rs.getString("supp.address"), "505 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10005");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "0000000006");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "T6");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 600);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 8);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 15);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000006");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Item T6");
+ assertEquals(rs.getString("SUPP.supplier_id"), "0000000006");
+ assertEquals(rs.getString("supp.name"), "S6");
+ assertEquals(rs.getString("supp.phone"), "888-888-6666");
+ assertEquals(rs.getString("supp.address"), "606 YYY Street");
+ assertEquals(rs.getString("supp.loc_id"), "10006");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".item_id"), "invalid001");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".NAME"), "INVALID-1");
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".PRICE"), 0);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT1"), 0);
+ assertEquals(rs.getInt(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DISCOUNT2"), 0);
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".supplier_id"), "0000000000");
+ assertEquals(rs.getString(getDisplayTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + ".DESCRIPTION"), "Invalid item for join test");
+ assertNull(rs.getString("SUPP.supplier_id"));
+ assertNull(rs.getString("supp.name"));
+ assertNull(rs.getString("supp.phone"));
+ assertNull(rs.getString("supp.address"));
+ assertNull(rs.getString("supp.loc_id"));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithTableWildcard() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ s.*, "+ tableName1 + ".*, \"order_id\" FROM " + tableName4 + " o RIGHT JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" RIGHT JOIN "
+ + tableName2 + " s ON i.\"supplier_id\" = s.\"supplier_id\" ORDER BY \"order_id\", s.\"supplier_id\" DESC";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ ResultSetMetaData md = rs.getMetaData();
+ assertEquals(md.getColumnCount(), 13);
+
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "S5");
+ assertEquals(rs.getString(3), "888-888-5555");
+ assertEquals(rs.getString(4), "505 YYY Street");
+ assertEquals(rs.getString(5), "10005");
+ assertEquals(rs.getString(6), "0000000005");
+ assertEquals(rs.getString(7), "T5");
+ assertEquals(rs.getInt(8), 500);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000005");
+ assertEquals(rs.getString(12), "Item T5");
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "S4");
+ assertEquals(rs.getString(3), "888-888-4444");
+ assertEquals(rs.getString(4), "404 YYY Street");
+ assertNull(rs.getString(5));
+ assertNull(rs.getString(6));
+ assertNull(rs.getString(7));
+ assertEquals(rs.getInt(8), 0);
+ assertEquals(rs.getInt(9), 0);
+ assertEquals(rs.getInt(10), 0);
+ assertNull(rs.getString(11));
+ assertNull(rs.getString(12));
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "S3");
+ assertEquals(rs.getString(3), "888-888-3333");
+ assertEquals(rs.getString(4), "303 YYY Street");
+ assertNull(rs.getString(5));
+ assertNull(rs.getString(6));
+ assertNull(rs.getString(7));
+ assertEquals(rs.getInt(8), 0);
+ assertEquals(rs.getInt(9), 0);
+ assertEquals(rs.getInt(10), 0);
+ assertNull(rs.getString(11));
+ assertNull(rs.getString(12));
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S2");
+ assertEquals(rs.getString(3), "888-888-2222");
+ assertEquals(rs.getString(4), "202 YYY Street");
+ assertEquals(rs.getString(5), "10002");
+ assertEquals(rs.getString(6), "0000000004");
+ assertEquals(rs.getString(7), "T4");
+ assertEquals(rs.getInt(8), 400);
+ assertEquals(rs.getInt(9), 6);
+ assertEquals(rs.getInt(10), 10);
+ assertEquals(rs.getString(11), "0000000002");
+ assertEquals(rs.getString(12), "Item T4");
+ assertNull(rs.getString(13));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertEquals(rs.getString(3), "888-888-1111");
+ assertEquals(rs.getString(4), "101 YYY Street");
+ assertEquals(rs.getString(5), "10001");
+ assertEquals(rs.getString(6), "0000000001");
+ assertEquals(rs.getString(7), "T1");
+ assertEquals(rs.getInt(8), 100);
+ assertEquals(rs.getInt(9), 5);
+ assertEquals(rs.getInt(10), 10);
+ assertEquals(rs.getString(11), "0000000001");
+ assertEquals(rs.getString(12), "Item T1");
+ assertEquals(rs.getString(13), "000000000000001");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+ assertEquals(rs.getString(3), "888-888-6666");
+ assertEquals(rs.getString(4), "606 YYY Street");
+ assertEquals(rs.getString(5), "10006");
+ assertEquals(rs.getString(6), "0000000006");
+ assertEquals(rs.getString(7), "T6");
+ assertEquals(rs.getInt(8), 600);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000006");
+ assertEquals(rs.getString(12), "Item T6");
+ assertEquals(rs.getString(13), "000000000000002");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "S1");
+ assertEquals(rs.getString(3), "888-888-1111");
+ assertEquals(rs.getString(4), "101 YYY Street");
+ assertEquals(rs.getString(5), "10001");
+ assertEquals(rs.getString(6), "0000000002");
+ assertEquals(rs.getString(7), "T2");
+ assertEquals(rs.getInt(8), 200);
+ assertEquals(rs.getInt(9), 5);
+ assertEquals(rs.getInt(10), 8);
+ assertEquals(rs.getString(11), "0000000001");
+ assertEquals(rs.getString(12), "Item T2");
+ assertEquals(rs.getString(13), "000000000000003");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000006");
+ assertEquals(rs.getString(2), "S6");
+ assertEquals(rs.getString(3), "888-888-6666");
+ assertEquals(rs.getString(4), "606 YYY Street");
+ assertEquals(rs.getString(5), "10006");
+ assertEquals(rs.getString(6), "0000000006");
+ assertEquals(rs.getString(7), "T6");
+ assertEquals(rs.getInt(8), 600);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 15);
+ assertEquals(rs.getString(11), "0000000006");
+ assertEquals(rs.getString(12), "Item T6");
+ assertEquals(rs.getString(13), "000000000000004");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "S2");
+ assertEquals(rs.getString(3), "888-888-2222");
+ assertEquals(rs.getString(4), "202 YYY Street");
+ assertEquals(rs.getString(5), "10002");
+ assertEquals(rs.getString(6), "0000000003");
+ assertEquals(rs.getString(7), "T3");
+ assertEquals(rs.getInt(8), 300);
+ assertEquals(rs.getInt(9), 8);
+ assertEquals(rs.getInt(10), 12);
+ assertEquals(rs.getString(11), "0000000002");
+ assertEquals(rs.getString(12), "Item T3");
+ assertEquals(rs.getString(13), "000000000000005");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinMultiJoinKeys() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ c.name, s.name FROM " + tableName3 + " c LEFT JOIN " + tableName2 + " s ON \"customer_id\" = \"supplier_id\" AND c.loc_id = s.loc_id AND substr(s.name, 2, 1) = substr(c.name, 2, 1) ORDER BY \"customer_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C1");
+ assertEquals(rs.getString(2), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C2");
+ assertNull(rs.getString(2));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C3");
+ assertEquals(rs.getString(2), "S3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C4");
+ assertNull(rs.getString(2));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C5");
+ assertEquals(rs.getString(2), "S5");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "C6");
+ assertNull(rs.getString(2));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithDifferentNumericJoinKeyTypes() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, i.price, discount2, quantity FROM " + tableName4 + " o INNER JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" AND o.price = (i.price * (100 - discount2)) / 100.0 WHERE quantity < 5000";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000004");
+ assertEquals(rs.getString(2), "T6");
+ assertEquals(rs.getInt(3), 600);
+ assertEquals(rs.getInt(4), 15);
+ assertEquals(rs.getInt(5), 4000);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithDifferentDateJoinKeyTypes() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName3 = getTableName(conn, JOIN_CUSTOMER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", c.name, o.\"DATE\" FROM " + tableName4 + " o INNER JOIN "
+ + tableName3 + " c ON o.\"customer_id\" = c.\"customer_id\" AND o.\"DATE\" = c.\"DATE\" ORDER BY \"order_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000001");
+ assertEquals(rs.getString(2), "C4");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-22 14:22:56").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000002");
+ assertEquals(rs.getString(2), "C3");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000003");
+ assertEquals(rs.getString(2), "C2");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-25 16:45:07").getTime()));
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "000000000000005");
+ assertEquals(rs.getString(2), "C5");
+ assertEquals(rs.getTimestamp(3), new Timestamp(format.parse("2013-11-27 09:37:50").getTime()));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithIncomparableJoinKeyTypes() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String query = "SELECT /*+ USE_SORT_MERGE_JOIN*/ \"order_id\", i.name, i.price, discount2, quantity FROM " + tableName4 + " o INNER JOIN "
+ + tableName1 + " i ON o.\"item_id\" = i.\"item_id\" AND o.price / 100 = substr(i.name, 2, 1)";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ statement.executeQuery();
+ fail("Should have got SQLException.");
+ } catch (SQLException e) {
+ assertEquals(e.getErrorCode(), SQLExceptionCode.TYPE_MISMATCH.getErrorCode());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinPlanWithIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String query1 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON substr(item.name, 2, 1) = substr(supp.name, 2, 1) AND (supp.name BETWEEN 'S1' AND 'S5') WHERE item.name BETWEEN 'T1' AND 'T5' ORDER BY \"item_id\"";
+ String query2 = "SELECT /*+ USE_SORT_MERGE_JOIN*/ item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" WHERE (item.name = 'T1' OR item.name = 'T5') AND (supp.name = 'S1' OR supp.name = 'S5') ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query1);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000002");
+ assertEquals(rs.getString(2), "T2");
+ assertEquals(rs.getString(3), "0000000002");
+ assertEquals(rs.getString(4), "S2");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000003");
+ assertEquals(rs.getString(2), "T3");
+ assertEquals(rs.getString(3), "0000000003");
+ assertEquals(rs.getString(4), "S3");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000004");
+ assertEquals(rs.getString(2), "T4");
+ assertEquals(rs.getString(3), "0000000004");
+ assertEquals(rs.getString(4), "S4");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+
+ statement = conn.prepareStatement(query2);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000001");
+ assertEquals(rs.getString(2), "T1");
+ assertEquals(rs.getString(3), "0000000001");
+ assertEquals(rs.getString(4), "S1");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "0000000005");
+ assertEquals(rs.getString(2), "T5");
+ assertEquals(rs.getString(3), "0000000005");
+ assertEquals(rs.getString(4), "S5");
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinWithSkipMergeOptimization() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName4 = getTableName(conn, JOIN_ORDER_TABLE_FULL_NAME);
+ String qu
<TRUNCATED>
[19/25] phoenix git commit: PHOENIX-4248 Breakup IndexExpressionIT
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexUsageIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexUsageIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexUsageIT.java
new file mode 100644
index 0000000..14b569a
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexUsageIT.java
@@ -0,0 +1,775 @@
+/*
+ * 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.end2end.index;
+
+import static org.apache.phoenix.query.QueryConstants.MILLIS_IN_DAY;
+import static org.apache.phoenix.util.TestUtil.INDEX_DATA_SCHEMA;
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.execute.CommitException;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+public class IndexUsageIT extends ParallelStatsDisabledIT {
+
+ /**
+ * Adds a row to the index data table
+ *
+ * @param i row number
+ */
+ private void insertRow(PreparedStatement stmt, int i) throws SQLException {
+ // insert row
+ stmt.setString(1, "varchar" + String.valueOf(i));
+ stmt.setString(2, "char" + String.valueOf(i));
+ stmt.setInt(3, i);
+ stmt.setLong(4, i);
+ stmt.setBigDecimal(5, new BigDecimal(i*0.5d));
+ Date date = new Date(DateUtil.parseDate("2015-01-01 00:00:00").getTime() + (i - 1) * MILLIS_IN_DAY);
+ stmt.setDate(6, date);
+ stmt.setString(7, "a.varchar" + String.valueOf(i));
+ stmt.setString(8, "a.char" + String.valueOf(i));
+ stmt.setInt(9, i);
+ stmt.setLong(10, i);
+ stmt.setBigDecimal(11, new BigDecimal(i*0.5d));
+ stmt.setDate(12, date);
+ stmt.setString(13, "b.varchar" + String.valueOf(i));
+ stmt.setString(14, "b.char" + String.valueOf(i));
+ stmt.setInt(15, i);
+ stmt.setLong(16, i);
+ stmt.setBigDecimal(17, new BigDecimal(i*0.5d));
+ stmt.setDate(18, date);
+ stmt.executeUpdate();
+ }
+
+ private void createDataTable(Connection conn, String dataTableName, String tableProps) throws SQLException {
+ String tableDDL = "create table " + dataTableName + TestUtil.TEST_TABLE_SCHEMA + tableProps;
+ conn.createStatement().execute(tableDDL);
+ }
+
+ private void populateDataTable(Connection conn, String dataTable) throws SQLException {
+ String upsert = "UPSERT INTO " + dataTable
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement stmt1 = conn.prepareStatement(upsert);
+ // insert two rows
+ insertRow(stmt1, 1);
+ insertRow(stmt1, 2);
+ conn.commit();
+ }
+
+ @Test
+ public void testGroupByCountImmutableIndex() throws Exception {
+ helpTestGroupByCount(false, false);
+ }
+
+ @Test
+ public void testGroupByCountImmutableLocalIndex() throws Exception {
+ helpTestGroupByCount(false, true);
+ }
+
+ @Test
+ public void testGroupByCountMutableIndex() throws Exception {
+ helpTestGroupByCount(true, false);
+ }
+
+ @Test
+ public void testGroupByCountMutableLocalIndex() throws Exception {
+ helpTestGroupByCount(true, true);
+ }
+
+ protected void helpTestGroupByCount(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (int_col1+int_col2)";
+ conn.createStatement().execute(ddl);
+
+ String groupBySql = "SELECT (int_col1+int_col2), COUNT(*) FROM " + fullDataTableName
+ + " GROUP BY (int_col1+int_col2)";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + groupBySql);
+ String expectedPlan = "CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER " + fullDataTableName + " [1]"
+ : "FULL SCAN OVER INDEX_TEST." + indexName)
+ + "\n SERVER FILTER BY FIRST KEY ONLY\n SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [TO_BIGINT(\"(A.INT_COL1 + B.INT_COL2)\")]"
+ + (localIndex ? "\nCLIENT MERGE SORT" : "");
+ assertEquals(expectedPlan, QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(groupBySql);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(2));
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectDistinctImmutableIndex() throws Exception {
+ helpTestSelectDistinct(false, false);
+ }
+
+ @Test
+ public void testSelectDistinctImmutableIndexLocal() throws Exception {
+ helpTestSelectDistinct(false, true);
+ }
+
+ @Test
+ public void testSelectDistinctMutableIndex() throws Exception {
+ helpTestSelectDistinct(true, false);
+ }
+
+ @Test
+ public void testSelectDistinctMutableLocalIndex() throws Exception {
+ helpTestSelectDistinct(true, true);
+ }
+
+ protected void helpTestSelectDistinct(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (int_col1+1)";
+ conn.createStatement().execute(ddl);
+ String sql = "SELECT distinct int_col1+1 FROM " + fullDataTableName + " where int_col1+1 > 0";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ String expectedPlan = "CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
+ + (localIndex ? fullDataTableName + " [1,0] - [1,*]"
+ : "INDEX_TEST." + indexName + " [0] - [*]")
+ + "\n SERVER FILTER BY FIRST KEY ONLY\n SERVER DISTINCT PREFIX FILTER OVER [TO_BIGINT(\"(A.INT_COL1 + 1)\")]\n SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [TO_BIGINT(\"(A.INT_COL1 + 1)\")]"
+ + (localIndex ? "\nCLIENT MERGE SORT" : "");
+ assertEquals(expectedPlan, QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInClauseWithImmutableIndex() throws Exception {
+ helpTestInClauseWithIndex(false, false);
+ }
+
+ @Test
+ public void testInClauseWithImmutableLocalIndex() throws Exception {
+ helpTestInClauseWithIndex(false, true);
+ }
+
+ @Test
+ public void testInClauseWithMutableIndex() throws Exception {
+ helpTestInClauseWithIndex(true, false);
+ }
+
+ @Test
+ public void testInClauseWithMutableLocalIndex() throws Exception {
+ helpTestInClauseWithIndex(true, false);
+ }
+
+ protected void helpTestInClauseWithIndex(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn.createStatement().execute(ddl);
+ String sql = "SELECT int_col1+1 FROM " + fullDataTableName + " where int_col1+1 IN (2)";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
+ + (localIndex ? fullDataTableName + " [1,2]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT"
+ : "INDEX_TEST." + indexName + " [2]\n SERVER FILTER BY FIRST KEY ONLY"), QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testOrderByWithImmutableIndex() throws Exception {
+ helpTestSelectAliasAndOrderByWithIndex(false, false);
+ }
+
+ @Test
+ public void testOrderByWithImmutableLocalIndex() throws Exception {
+ helpTestSelectAliasAndOrderByWithIndex(false, true);
+ }
+
+ @Test
+ public void testOrderByWithMutableIndex() throws Exception {
+ helpTestSelectAliasAndOrderByWithIndex(true, false);
+ }
+
+ @Test
+ public void testOrderByWithMutableLocalIndex() throws Exception {
+ helpTestSelectAliasAndOrderByWithIndex(true, false);
+ }
+
+ protected void helpTestSelectAliasAndOrderByWithIndex(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn.createStatement().execute(ddl);
+ String sql = "SELECT int_col1+1 AS foo FROM " + fullDataTableName + " ORDER BY foo";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER " + fullDataTableName
+ + " [1]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT"
+ : "FULL SCAN OVER INDEX_TEST." + indexName + "\n SERVER FILTER BY FIRST KEY ONLY"),
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(false, true);
+ }
+
+ @Test
+ public void testMutableIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(true, true);
+ }
+
+ protected void helpTestIndexWithCaseSensitiveCols(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + dataTableName + " (k VARCHAR NOT NULL PRIMARY KEY, \"cf1\".\"V1\" VARCHAR, \"CF2\".\"v2\" VARCHAR) "+ (mutable ? "IMMUTABLE_ROWS=true" : ""));
+ String query = "SELECT * FROM " + dataTableName;
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + dataTableName + " (\"cf1\".\"V1\" || '_' || \"CF2\".\"v2\") INCLUDE (\"V1\",\"v2\")";
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?,?)");
+ stmt.setString(1,"a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ stmt.setString(1,"b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT (\"V1\" || '_' || \"v2\"), k, \"V1\", \"v2\" FROM " + dataTableName + " WHERE (\"V1\" || '_' || \"v2\") = 'x_1'";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + dataTableName + " [1,'x_1']\n"
+ + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexName + " ['x_1']", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x_1",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("x",rs.getString(3));
+ assertEquals("1",rs.getString(4));
+ //TODO figure out why this " " is needed
+ assertEquals("x_1",rs.getString("\"('cf1'.'V1' || '_' || 'CF2'.'v2')\""));
+ assertEquals("a",rs.getString("k"));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("1",rs.getString("v2"));
+ assertFalse(rs.next());
+
+ query = "SELECT \"V1\", \"V1\" as foo1, (\"V1\" || '_' || \"v2\") as foo, (\"V1\" || '_' || \"v2\") as \"Foo1\", (\"V1\" || '_' || \"v2\") FROM " + dataTableName + " ORDER BY foo";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + dataTableName + " [1]\nCLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER " + indexName, QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("x",rs.getString(2));
+ assertEquals("x",rs.getString("foo1"));
+ assertEquals("x_1",rs.getString(3));
+ assertEquals("x_1",rs.getString("Foo"));
+ assertEquals("x_1",rs.getString(4));
+ assertEquals("x_1",rs.getString("Foo1"));
+ assertEquals("x_1",rs.getString(5));
+ assertEquals("x_1",rs.getString("\"('cf1'.'V1' || '_' || 'CF2'.'v2')\""));
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("y",rs.getString("V1"));
+ assertEquals("y",rs.getString(2));
+ assertEquals("y",rs.getString("foo1"));
+ assertEquals("y_2",rs.getString(3));
+ assertEquals("y_2",rs.getString("Foo"));
+ assertEquals("y_2",rs.getString(4));
+ assertEquals("y_2",rs.getString("Foo1"));
+ assertEquals("y_2",rs.getString(5));
+ assertEquals("y_2",rs.getString("\"('cf1'.'V1' || '_' || 'CF2'.'v2')\""));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableImmutableIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(false, false);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableImmutableLocalIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(false, true);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableMutableIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(true, false);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableMutableLocalIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(true, true);
+ }
+
+ protected void helpTestSelectColOnlyInDataTable(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = generateUniqueName();
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ createDataTable(conn, fullDataTableName, mutable ? "" : "IMMUTABLE_ROWS=true");
+ populateDataTable(conn, fullDataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX " + indexName + " ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ conn.createStatement().execute(ddl);
+ String sql = "SELECT int_col1+1, int_col2 FROM " + fullDataTableName + " WHERE int_col1+1=2";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER " + fullDataTableName
+ + " [1,2]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT" : "FULL SCAN OVER "
+ + fullDataTableName + "\n SERVER FILTER BY (A.INT_COL1 + 1) = 2"),
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testUpdatableViewWithIndex() throws Exception {
+ helpTestUpdatableViewIndex(false);
+ }
+
+ @Test
+ public void testUpdatableViewWithLocalIndex() throws Exception {
+ helpTestUpdatableViewIndex(true);
+ }
+
+ private void helpTestUpdatableViewIndex(boolean local) throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String dataTableName = generateUniqueName();
+ String indexName1 = generateUniqueName();
+ String viewName = generateUniqueName();
+ String indexName2 = generateUniqueName();
+ try {
+ String ddl = "CREATE TABLE " + dataTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, k3 DECIMAL, s1 VARCHAR, s2 VARCHAR CONSTRAINT pk PRIMARY KEY (k1, k2, k3))";
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE VIEW " + viewName + " AS SELECT * FROM " + dataTableName + " WHERE k1 = 1";
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute("UPSERT INTO " + viewName + "(k2,s1,s2,k3) VALUES(120,'foo0','bar0',50.0)");
+ conn.createStatement().execute("UPSERT INTO " + viewName + "(k2,s1,s2,k3) VALUES(121,'foo1','bar1',51.0)");
+ conn.commit();
+
+ ResultSet rs;
+ conn.createStatement().execute("CREATE " + (local ? "LOCAL" : "") + " INDEX " + indexName1 + " on " + viewName + "(k1+k2+k3) include (s1, s2)");
+ conn.createStatement().execute("UPSERT INTO " + viewName + "(k2,s1,s2,k3) VALUES(120,'foo2','bar2',50.0)");
+ conn.commit();
+
+ String query = "SELECT k1, k2, k3, s1, s2 FROM " + viewName + " WHERE k1+k2+k3 = 173.0";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ String queryPlan = QueryUtil.getExplainPlan(rs);
+ if (local) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + dataTableName + " [1,173]\n" + "CLIENT MERGE SORT",
+ queryPlan);
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_" + dataTableName + " [" + Short.MIN_VALUE + ",173]", queryPlan);
+ }
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertEquals(121, rs.getInt(2));
+ assertTrue(BigDecimal.valueOf(51.0).compareTo(rs.getBigDecimal(3))==0);
+ assertEquals("foo1", rs.getString(4));
+ assertEquals("bar1", rs.getString(5));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("CREATE " + (local ? "LOCAL" : "") + " INDEX " + indexName2 + " on " + viewName + "(s1||'_'||s2)");
+
+ query = "SELECT k1, k2, s1||'_'||s2 FROM " + viewName + " WHERE (s1||'_'||s2)='foo2_bar2'";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if (local) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + dataTableName + " [" + (2)
+ + ",'foo2_bar2']\n" + " SERVER FILTER BY FIRST KEY ONLY\n" + "CLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _IDX_" + dataTableName + " [" + (Short.MIN_VALUE + 1) + ",'foo2_bar2']\n"
+ + " SERVER FILTER BY FIRST KEY ONLY", QueryUtil.getExplainPlan(rs));
+ }
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertEquals(120, rs.getInt(2));
+ assertEquals("foo2_bar2", rs.getString(3));
+ assertFalse(rs.next());
+ }
+ finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testViewUsesMutableTableIndex() throws Exception {
+ helpTestViewUsesTableIndex(false);
+ }
+
+ @Test
+ public void testViewUsesImmutableTableIndex() throws Exception {
+ helpTestViewUsesTableIndex(true);
+ }
+
+ private void helpTestViewUsesTableIndex(boolean immutable) throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try
+ {
+ String dataTableName = generateUniqueName();
+ String indexName1 = generateUniqueName();
+ String viewName = generateUniqueName();
+ String indexName2 = generateUniqueName();
+ ResultSet rs;
+ String ddl = "CREATE TABLE " + dataTableName + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, s1 VARCHAR, s2 VARCHAR, s3 VARCHAR, s4 VARCHAR CONSTRAINT pk PRIMARY KEY (k1, k2)) " + (immutable ? "IMMUTABLE_ROWS = true" : "");
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute("CREATE INDEX " + indexName1 + " ON " + dataTableName + "(k2, s2, s3, s1)");
+ conn.createStatement().execute("CREATE INDEX " + indexName2 + " ON " + dataTableName + "(k2, s2||'_'||s3, s1, s4)");
+
+ ddl = "CREATE VIEW " + viewName + " AS SELECT * FROM " + dataTableName + " WHERE s1 = 'foo'";
+ conn.createStatement().execute(ddl);
+ conn.createStatement().execute("UPSERT INTO " + dataTableName + " VALUES(1,1,'foo','abc','cab')");
+ conn.createStatement().execute("UPSERT INTO " + dataTableName + " VALUES(2,2,'bar','xyz','zyx')");
+ conn.commit();
+
+ rs = conn.createStatement().executeQuery("SELECT count(*) FROM " + viewName);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getLong(1));
+ assertFalse(rs.next());
+
+ //i2 should be used since it contains s3||'_'||s4 i
+ String query = "SELECT s2||'_'||s3 FROM " + viewName + " WHERE k2=1 AND (s2||'_'||s3)='abc_cab'";
+ rs = conn.createStatement( ).executeQuery("EXPLAIN " + query);
+ String queryPlan = QueryUtil.getExplainPlan(rs);
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexName2 + " [1,'abc_cab','foo']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY", queryPlan);
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("abc_cab", rs.getString(1));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("ALTER VIEW " + viewName + " DROP COLUMN s4");
+ //i2 cannot be used since s4 has been dropped from the view, so i1 will be used
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ queryPlan = QueryUtil.getExplainPlan(rs);
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexName1 + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY AND ((\"S2\" || '_' || \"S3\") = 'abc_cab' AND \"S1\" = 'foo')", queryPlan);
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("abc_cab", rs.getString(1));
+ assertFalse(rs.next());
+ }
+ finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testExpressionThrowsException() throws Exception {
+ Connection conn = DriverManager.getConnection(getUrl());
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ try {
+ String ddl = "CREATE TABLE " + dataTableName + " (k1 INTEGER PRIMARY KEY, k2 INTEGER)";
+ conn.createStatement().execute(ddl);
+ ddl = "CREATE INDEX " + indexName + " on " + dataTableName + "(k1/k2)";
+ conn.createStatement().execute(ddl);
+ // upsert should succeed
+ conn.createStatement().execute("UPSERT INTO " + dataTableName + " VALUES(1,1)");
+ conn.commit();
+ // divide by zero should fail
+ conn.createStatement().execute("UPSERT INTO " + dataTableName + " VALUES(1,0)");
+ conn.commit();
+ fail();
+ } catch (CommitException e) {
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableCaseSensitiveFunctionIndex() throws Exception {
+ helpTestCaseSensitiveFunctionIndex(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalCaseSensitiveFunctionIndex() throws Exception {
+ helpTestCaseSensitiveFunctionIndex(false, true);
+ }
+
+ @Test
+ public void testMutableCaseSensitiveFunctionIndex() throws Exception {
+ helpTestCaseSensitiveFunctionIndex(true, false);
+ }
+
+ @Test
+ public void testMutableLocalCaseSensitiveFunctionIndex() throws Exception {
+ helpTestCaseSensitiveFunctionIndex(true, true);
+ }
+
+ protected void helpTestCaseSensitiveFunctionIndex(boolean mutable,
+ boolean localIndex) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableName + " (k VARCHAR NOT NULL PRIMARY KEY, v VARCHAR) "
+ + (!mutable ? "IMMUTABLE_ROWS=true" : ""));
+ String query = "SELECT * FROM " + dataTableName;
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "")
+ + " INDEX " + indexName + " ON " + dataTableName + " (REGEXP_SUBSTR(v,'id:\\\\w+'))";
+ conn.createStatement().execute(ddl);
+ query = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?)");
+ stmt.setString(1, "k1");
+ stmt.setString(2, "{id:id1}");
+ stmt.execute();
+ stmt.setString(1, "k2");
+ stmt.setString(2, "{id:id2}");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT k FROM " + dataTableName + " WHERE REGEXP_SUBSTR(v,'id:\\\\w+') = 'id:id1'";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if (localIndex) {
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + dataTableName + " [1,'id:id1']\n"
+ + " SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals(
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexName + " ['id:id1']\n"
+ + " SERVER FILTER BY FIRST KEY ONLY",
+ QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("k1", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableTableGlobalIndexExpressionWithJoin() throws Exception {
+ helpTestIndexExpressionWithJoin(false, false);
+ }
+
+ @Test
+ public void testImmutableTableLocalIndexExpressionWithJoin() throws Exception {
+ helpTestIndexExpressionWithJoin(false, true);
+ }
+
+ @Test
+ public void testMutableTableGlobalIndexExpressionWithJoin() throws Exception {
+ helpTestIndexExpressionWithJoin(true, false);
+ }
+
+ @Test
+ public void testMutableTableLocalIndexExpressionWithJoin() throws Exception {
+ helpTestIndexExpressionWithJoin(true, true);
+ }
+
+ public void helpTestIndexExpressionWithJoin(boolean mutable,
+ boolean localIndex) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String nameSuffix = "T" + (mutable ? "MUTABLE" : "_IMMUTABLE") + (localIndex ? "_LOCAL" : "_GLOBAL");
+ String tableName = "T" + nameSuffix;
+ String indexName = "IDX" + nameSuffix;
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE "
+ + tableName
+ + "( c_customer_sk varchar primary key, c_first_name varchar, c_last_name varchar )"
+ + (!mutable ? "IMMUTABLE_ROWS=true" : ""));
+ String query = "SELECT * FROM " + tableName;
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute(
+ "CREATE " + (localIndex ? "LOCAL" : "")
+ + " INDEX " + indexName + " ON " + tableName + " (c_customer_sk || c_first_name asc)");
+ query = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " VALUES(?,?,?)");
+ stmt.setString(1, "1");
+ stmt.setString(2, "David");
+ stmt.setString(3, "Smith");
+ stmt.execute();
+ conn.commit();
+
+ query = "select c.c_customer_sk from " + tableName + " c "
+ + "left outer join " + tableName + " c2 on c.c_customer_sk = c2.c_customer_sk "
+ + "where c.c_customer_sk || c.c_first_name = '1David'";
+ rs = conn.createStatement().executeQuery("EXPLAIN "+query);
+ String explainPlan = QueryUtil.getExplainPlan(rs);
+ if (localIndex) {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + tableName + " [1,'1David']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + tableName + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT", explainPlan);
+ }
+ else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + indexName + " ['1David']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + indexName + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY", explainPlan);
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("1", rs.getString(1));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
new file mode 100644
index 0000000..659866b
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexWithTableSchemaChangeIT.java
@@ -0,0 +1,375 @@
+/*
+ * 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.end2end.index;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.util.IndexUtil;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.junit.Test;
+
+public class IndexWithTableSchemaChangeIT extends ParallelStatsDisabledIT {
+
+ @Test
+ public void testImmutableIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(false, true);
+ }
+
+ @Test
+ public void testMutableIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(true, true);
+ }
+
+ public void helpTestDropIndexedColumn(boolean mutable, boolean local) throws Exception {
+ String query;
+ ResultSet rs;
+ PreparedStatement stmt;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+
+ try {
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)"
+ + (!mutable ? " IMMUTABLE_ROWS=true" : ""));
+ query = "SELECT * FROM " + dataTableName ;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ conn.createStatement().execute("CREATE " + ( local ? "LOCAL" : "") + " INDEX " + indexName + " ON " + dataTableName + " (v1 || '_' || v2)");
+
+ query = "SELECT * FROM " + dataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn, dataTableName, true);
+ conn.createStatement().execute("ALTER TABLE " + dataTableName + " DROP COLUMN v1");
+ assertIndexExists(conn, dataTableName, false);
+
+ query = "SELECT * FROM " + dataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("1",rs.getString(2));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM " + dataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("2",rs.getString(2));
+ assertFalse(rs.next());
+ }
+ finally {
+ conn.close();
+ }
+ }
+
+ private static void assertIndexExists(Connection conn, String tableName, boolean exists) throws SQLException {
+ ResultSet rs = conn.getMetaData().getIndexInfo(null, null, tableName, false, false);
+ assertEquals(exists, rs.next());
+ }
+
+ @Test
+ public void testImmutableIndexDropCoveredColumn() throws Exception {
+ helpTestDropCoveredColumn(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexDropCoveredColumn() throws Exception {
+ helpTestDropCoveredColumn(false, true);
+ }
+
+ @Test
+ public void testMutableIndexDropCoveredColumn() throws Exception {
+ helpTestDropCoveredColumn(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexDropCoveredColumn() throws Exception {
+ helpTestDropCoveredColumn(true, true);
+ }
+
+ public void helpTestDropCoveredColumn(boolean mutable, boolean local) throws Exception {
+ ResultSet rs;
+ PreparedStatement stmt;
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR, v3 VARCHAR)");
+ String dataTableQuery = "SELECT * FROM " + dataTableName;
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("CREATE " + ( local ? "LOCAL" : "") + " INDEX " + indexName + " ON " + dataTableName + " (k || '_' || v1) include (v2, v3)");
+ String indexTableQuery = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.setString(4, "j");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn, dataTableName, true);
+ conn.createStatement().execute("ALTER TABLE " + dataTableName + " DROP COLUMN v2");
+ assertIndexExists(conn, dataTableName, true);
+
+ // verify data table rows
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a_x",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertFalse(rs.next());
+
+ // add another row
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?,?)");
+ stmt.setString(1, "b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "k");
+ stmt.execute();
+ conn.commit();
+
+ // verify data table rows
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertEquals("y",rs.getString(2));
+ assertEquals("k",rs.getString(3));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a_x",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("j",rs.getString(3));
+ assertTrue(rs.next());
+ assertEquals("b_y",rs.getString(1));
+ assertEquals("b",rs.getString(2));
+ assertEquals("k",rs.getString(3));
+ assertFalse(rs.next());
+ }
+ finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableIndexAddPKColumnToTable() throws Exception {
+ helpTestAddPKColumnToTable(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexAddPKColumnToTable() throws Exception {
+ helpTestAddPKColumnToTable(false, true);
+ }
+
+ @Test
+ public void testMutableIndexAddPKColumnToTable() throws Exception {
+ helpTestAddPKColumnToTable(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexAddPKColumnToTable() throws Exception {
+ helpTestAddPKColumnToTable(true, true);
+ }
+
+ public void helpTestAddPKColumnToTable(boolean mutable, boolean local) throws Exception {
+ ResultSet rs;
+ PreparedStatement stmt;
+
+ String dataTableName = generateUniqueName();
+ String indexName = generateUniqueName();
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE " + dataTableName
+ + " (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)");
+ String dataTableQuery = "SELECT * FROM " + dataTableName;
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("CREATE " + ( local ? "LOCAL" : "") + " INDEX " + indexName + " ON " + dataTableName + " (v1 || '_' || v2)");
+ String indexTableQuery = "SELECT * FROM " + indexName;
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + " VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn, dataTableName, true);
+ conn.createStatement().execute("ALTER TABLE " + dataTableName + " ADD v3 VARCHAR, k2 DECIMAL PRIMARY KEY");
+ rs = conn.getMetaData().getPrimaryKeys("", "", dataTableName);
+ assertTrue(rs.next());
+ assertEquals("K",rs.getString("COLUMN_NAME"));
+ assertEquals(1, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals("K2",rs.getString("COLUMN_NAME"));
+ assertEquals(2, rs.getShort("KEY_SEQ"));
+
+ rs = conn.getMetaData().getPrimaryKeys("", "", indexName);
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "(V1 || '_' || V2)",rs.getString("COLUMN_NAME"));
+ int offset = local ? 1 : 0;
+ assertEquals(offset+1, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K",rs.getString("COLUMN_NAME"));
+ assertEquals(offset+2, rs.getShort("KEY_SEQ"));
+ assertTrue(rs.next());
+ assertEquals(IndexUtil.INDEX_COLUMN_NAME_SEP + "K2",rs.getString("COLUMN_NAME"));
+ assertEquals(offset+3, rs.getShort("KEY_SEQ"));
+
+ // verify data table rows
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("1",rs.getString(3));
+ assertNull(rs.getBigDecimal(4));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("x_1",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertNull(rs.getBigDecimal(3));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO " + dataTableName + "(K,K2,V1,V2) VALUES(?,?,?,?)");
+ stmt.setString(1, "b");
+ stmt.setBigDecimal(2, BigDecimal.valueOf(2));
+ stmt.setString(3, "y");
+ stmt.setString(4, "2");
+ stmt.execute();
+ conn.commit();
+
+ // verify data table rows
+ rs = conn.createStatement().executeQuery(dataTableQuery);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("x",rs.getString(2));
+ assertEquals("1",rs.getString(3));
+ assertNull(rs.getString(4));
+ assertNull(rs.getBigDecimal(5));
+ assertTrue(rs.next());
+ assertEquals("b",rs.getString(1));
+ assertEquals("y",rs.getString(2));
+ assertEquals("2",rs.getString(3));
+ assertNull(rs.getString(4));
+ assertEquals(BigDecimal.valueOf(2),rs.getBigDecimal(5));
+ assertFalse(rs.next());
+
+ // verify index table rows
+ rs = conn.createStatement().executeQuery(indexTableQuery);
+ assertTrue(rs.next());
+ assertEquals("x_1",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertNull(rs.getBigDecimal(3));
+ assertTrue(rs.next());
+ assertEquals("y_2",rs.getString(1));
+ assertEquals("b",rs.getString(2));
+ assertEquals(BigDecimal.valueOf(2),rs.getBigDecimal(3));
+ assertFalse(rs.next());
+ }
+ finally {
+ conn.close();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
index f2d18d2..7b7c6ad 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableNonTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class LocalImmutableNonTxIndexIT extends IndexIT {
+public class LocalImmutableNonTxIndexIT extends BaseIndexIT {
public LocalImmutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
index 9e6fd5f..5ff6d04 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalImmutableTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class LocalImmutableTxIndexIT extends IndexIT {
+public class LocalImmutableTxIndexIT extends BaseIndexIT {
public LocalImmutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
index 9785d20..4b9688b 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableNonTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class LocalMutableNonTxIndexIT extends IndexIT {
+public class LocalMutableNonTxIndexIT extends BaseIndexIT {
public LocalMutableNonTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3d9adc6f/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
index c09a8c0..5f5dd0f 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/LocalMutableTxIndexIT.java
@@ -22,7 +22,7 @@ import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
-public class LocalMutableTxIndexIT extends IndexIT {
+public class LocalMutableTxIndexIT extends BaseIndexIT {
public LocalMutableTxIndexIT(boolean localIndex, boolean mutable, boolean transactional, boolean columnEncoded) {
super(localIndex, mutable, transactional, columnEncoded);
[12/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
deleted file mode 100644
index edab319..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
+++ /dev/null
@@ -1,3448 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Random;
-
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.coprocessor.ObserverContext;
-import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
-import org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver;
-import org.apache.hadoop.hbase.regionserver.RegionScanner;
-import org.apache.phoenix.cache.GlobalCache;
-import org.apache.phoenix.cache.ServerCacheClient;
-import org.apache.phoenix.cache.TenantCache;
-import org.apache.phoenix.exception.SQLExceptionCode;
-import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
-import org.apache.phoenix.join.HashJoinInfo;
-import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.QueryUtil;
-import org.apache.phoenix.util.ReadOnlyProps;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-@RunWith(Parameterized.class)
-public class HashJoinIT extends BaseJoinIT {
-
-
- public HashJoinIT(String[] indexDDL, String[] plans) {
- super(indexDDL, plans);
- }
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC"
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testJoinWithWildcard()
- * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
- * ON joinItemTable.supplier_id = supp.supplier_id
- * ORDER BY item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
- * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
- * AND (supp.name BETWEEN 'S1' AND 'S5')
- * WHERE item.name BETWEEN 'T1' AND 'T5'
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME >= 'T1' AND NAME <= 'T5')\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME >= 'S1' AND NAME <= 'S5')",
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item INNER JOIN joinSupplierTable supp
- * ON item.supplier_id = supp.supplier_id
- * WHERE (item.name = 'T1' OR item.name = 'T5')
- * AND (supp.name = 'S1' OR supp.name = 'S5')
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME = 'T1' OR NAME = 'T5')\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME = 'S1' OR NAME = 'S5')",
- /*
- * testJoinWithSkipMergeOptimization()
- * SELECT s.name FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
- * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
- /*
- * testSelfJoin()
- * SELECT i2.item_id, i1.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
- * ORDER BY i1.item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.item_id\")",
- /*
- * testSelfJoin()
- * SELECT i1.name, i2.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
- * ORDER BY i1.name, i2.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [I1.NAME, I2.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.supplier_id\")",
- /*
- * testStarJoin()
- * SELECT order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testStarJoin()
- * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.order_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
- /*
- * testSubJoin()
- * SELECT * FROM joinCustomerTable c
- * INNER JOIN (joinOrderTable o
- * INNER JOIN (joinSupplierTable s
- * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
- * ON o.item_id = i.item_id)
- * ON c.customer_id = o.customer_id
- * WHERE c.customer_id <= '0000000005'
- * AND order_id != '000000000000003'
- * AND i.name != 'T3'
- * ORDER BY c.customer_id, i.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [\"C.customer_id\", I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY NAME != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
- * ON o.item_id = i.iid
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT o.iid, sum(o.quantity) q
- * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
- * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
- * ON o.iid = i.item_id
- * GROUP BY o.iid ORDER BY q DESC
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid FROM joinItemTable) AS i
- * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * ON o.iid = i.iid
- * ORDER BY o.q DESC NULLS LAST, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * JOIN (SELECT item_id iid FROM joinItemTable) AS i
- * ON o.iid = i.iid
- * ORDER BY o.q DESC, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testNestedSubqueries()
- * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
- * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
- * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
- * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
- * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
- * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
- * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
- * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
- * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
- * ON i.sid = s.sid) as qi
- * ON o.iid = qi.iiid) as qo
- * ON c.cid = qo.ocid
- * WHERE c.cid <= '0000000005'
- * AND qo.ooid != '000000000000003'
- * AND qo.iname != 'T3'
- * ORDER BY c.cid, qo.iname
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [C.CID, QO.INAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY NAME != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER 4 ROW LIMIT\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithSetMaxRows()
- * statement.setMaxRows(4);
- * SELECT order_id, i.name, quantity FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id;
- * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
- * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
- * ON o.item_id = i.item_id;
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- " SERVER 3 ROW LIMIT\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- }});
- testCases.add(new String[][] {
- {
- "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC"
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.:item_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testJoinWithWildcard()
- * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
- * ON joinItemTable.supplier_id = supp.supplier_id
- * ORDER BY item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
- * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
- * AND (supp.name BETWEEN 'S1' AND 'S5')
- * WHERE item.name BETWEEN 'T1' AND 'T5'
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SCHEMA + ".idx_item ['T1'] - ['T5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SCHEMA + ".idx_supplier ['S1'] - ['S5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item INNER JOIN joinSupplierTable supp
- * ON item.supplier_id = supp.supplier_id
- * WHERE (item.name = 'T1' OR item.name = 'T5')
- * AND (supp.name = 'S1' OR supp.name = 'S5')
- */
- "CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SCHEMA + ".idx_item ['T1'] - ['T5']\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SCHEMA + ".idx_supplier ['S1'] - ['S5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinWithSkipMergeOptimization()
- * SELECT s.name FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
- * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testSelfJoin()
- * SELECT i2.item_id, i1.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
- * ORDER BY i1.item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.:item_id\")",
- /*
- * testSelfJoin()
- * SELECT i1.name, i2.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
- * ORDER BY i1.name, i2.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.0:NAME\", \"I2.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item",
- /*
- * testStarJoin()
- * SELECT order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testStarJoin()
- * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"O.order_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testSubJoin()
- * SELECT * FROM joinCustomerTable c
- * INNER JOIN (joinOrderTable o
- * INNER JOIN (joinSupplierTable s
- * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
- * ON o.item_id = i.item_id)
- * ON c.customer_id = o.customer_id
- * WHERE c.customer_id <= '0000000005'
- * AND order_id != '000000000000003'
- * AND i.name != 'T3'
- * ORDER BY c.customer_id, i.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [\"C.customer_id\", \"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY \"NAME\" != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
- * ON o.item_id = i.iid
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT o.iid, sum(o.quantity) q
- * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
- * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
- * ON o.iid = i.item_id
- * GROUP BY o.iid ORDER BY q DESC
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid FROM joinItemTable) AS i
- * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * ON o.iid = i.iid
- * ORDER BY o.q DESC NULLS LAST, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * JOIN (SELECT item_id iid FROM joinItemTable) AS i
- * ON o.iid = i.iid
- * ORDER BY o.q DESC, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testNestedSubqueries()
- * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
- * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
- * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
- * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
- * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
- * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
- * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
- * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
- * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
- * ON i.sid = s.sid) as qi
- * ON o.iid = qi.iiid) as qo
- * ON c.cid = qo.ocid
- * WHERE c.cid <= '0000000005'
- * AND qo.ooid != '000000000000003'
- * AND qo.iname != 'T3'
- * ORDER BY c.cid, qo.iname
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [C.CID, QO.INAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY \"NAME\" != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER 4 ROW LIMIT\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithSetMaxRows()
- * statement.setMaxRows(4);
- * SELECT order_id, i.name, quantity FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id;
- * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
- * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
- * ON o.item_id = i.item_id;
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- " SERVER 3 ROW LIMIT\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- }});
- testCases.add(new String[][] {
- {
- "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
- "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
- "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
- }, {
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC"
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.:item_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME+" [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testJoinWithWildcard()
- * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
- * ON joinItemTable.supplier_id = supp.supplier_id
- * ORDER BY item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
- * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
- * AND (supp.name BETWEEN 'S1' AND 'S5')
- * WHERE item.name BETWEEN 'T1' AND 'T5'
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,'T1'] - [1,'T5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME +" [1,'S1'] - [1,'S5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item INNER JOIN joinSupplierTable supp
- * ON item.supplier_id = supp.supplier_id
- * WHERE (item.name = 'T1' OR item.name = 'T5')
- * AND (supp.name = 'S1' OR supp.name = 'S5')
- */
- "CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,'T1'] - [1,'T5']\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME +" [1,'S1'] - [1,'S5']\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSkipMergeOptimization()
- * SELECT s.name FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
- * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")",
- /*
- * testSelfJoin()
- * SELECT i2.item_id, i1.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
- * ORDER BY i1.item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.:item_id\")",
- /*
- * testSelfJoin()
- * SELECT i1.name, i2.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
- * ORDER BY i1.name, i2.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"I1.0:NAME\", \"I2.0:NAME\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I1.:item_id\" IN (\"I2.0:supplier_id\")",
- /*
- * testStarJoin()
- * SELECT order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testStarJoin()
- * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [\"O.order_id\"]\n"+
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME+" [1]\n"+
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")",
- /*
- * testSubJoin()
- * SELECT * FROM joinCustomerTable c
- * INNER JOIN (joinOrderTable o
- * INNER JOIN (joinSupplierTable s
- * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
- * ON o.item_id = i.item_id)
- * ON c.customer_id = o.customer_id
- * WHERE c.customer_id <= '0000000005'
- * AND order_id != '000000000000003'
- * AND i.name != 'T3'
- * ORDER BY c.customer_id, i.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [\"C.customer_id\", \"I.0:NAME\"]\n"+
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
- " SERVER FILTER BY \"NAME\" != 'T3'\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
- * ON o.item_id = i.iid
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME+" [1]\n"+
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT o.iid, sum(o.quantity) q
- * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
- * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
- * ON o.iid = i.item_id
- * GROUP BY o.iid ORDER BY q DESC
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid FROM joinItemTable) AS i
- * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * ON o.iid = i.iid
- * ORDER BY o.q DESC NULLS LAST, i.iid
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n"+
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * JOIN (SELECT item_id iid FROM joinItemTable) AS i
- * ON o.iid = i.iid
- * ORDER BY o.q DESC, i.iid
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC, I.IID]\n"+
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testNestedSubqueries()
- * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
- * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
- * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
- * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
- * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
- * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
- * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
- * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
- * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
- * ON i.sid = s.sid) as qi
- * ON o.iid = qi.iiid) as qo
- * ON c.cid = qo.ocid
- * WHERE c.cid <= '0000000005'
- * AND qo.ooid != '000000000000003'
- * AND qo.iname != 'T3'
- * ORDER BY c.cid, qo.iname
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [C.CID, QO.INAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY \"NAME\" != 'T3'\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER 4 ROW LIMIT\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithSetMaxRows()
- * statement.setMaxRows(4);
- * SELECT order_id, i.name, quantity FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id;
- * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
- * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
- * ON o.item_id = i.item_id;
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- " SERVER 3 ROW LIMIT\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
- " CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- }});
- return testCases;
- }
-
-
- @Test
- public void testDefaultJoin() throws Exception {
- Connection conn = getConnection();
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInnerJoin() throws Exception {
- Connection conn = getConnection();
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertEquals(1, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertEquals(2, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertEquals(3, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertEquals(4, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertEquals(5, rs.getInt(5));
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertEquals(6, rs.getInt(5));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testLeftJoin() throws Exception {
- Connection conn = getConnection();
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query[] = new String[3];
- query[0] = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- query[1] = "SELECT " + tableName1 + ".\"item_id\", " + tableName1 + ".name, " + tableName2 + ".\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " LEFT JOIN " + tableName2 + " ON " + tableName1 + ".\"supplier_id\" = " + tableName2 + ".\"supplier_id\" ORDER BY \"item_id\"";
- query[2] = "SELECT item.\"item_id\", " + tableName1 + ".name, supp.\"supplier_id\", " + tableName2 + ".name, next value for " + seqName + " FROM " + tableName1 + " item LEFT JOIN " + tableName2 + " supp ON " + tableName1 + ".\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- for (int i = 0; i < query.length; i++) {
- PreparedStatement statement = conn.prepareStatement(query[i]);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
-
- assertFalse(rs.next());
- rs.close();
- statement.close();
- }
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testRightJoin() throws Exception {
- Connection conn = getConnection();
- String tableName1 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " supp RIGHT JOIN " + tableName2 + " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000006");
- assertEquals(rs.getString(2), "T6");
- assertEquals(rs.getString(3), "0000000006");
- assertEquals(rs.getString(4), "S6");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "invalid001");
- assertEquals(rs.getString(2), "INVALID-1");
- assertNull(rs.getString(3));
- assertNull(rs.getString(4));
-
- assertFalse(rs.next());
- } finally {
- conn.close();
- }
- }
-
- @Test
- public void testInnerJoinWithPreFilters() throws Exception {
- Connection conn = getConnection();
- String tableName1 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String query1 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND supp.\"supplier_id\" BETWEEN '0000000001' AND '0000000005'";
- String query2 = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " + tableName1 + " item INNER JOIN " + tableName2 + " supp ON item.\"supplier_id\" = supp.\"supplier_id\" AND (supp.\"supplier_id\" = '0000000001' OR supp.\"supplier_id\" = '0000000005')";
- try {
- PreparedStatement statement = conn.prepareStatement(query1);
- ResultSet rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000003");
- assertEquals(rs.getString(2), "T3");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000004");
- assertEquals(rs.getString(2), "T4");
- assertEquals(rs.getString(3), "0000000002");
- assertEquals(rs.getString(4), "S2");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
- assertEquals(rs.getString(4), "S5");
-
- assertFalse(rs.next());
-
-
- statement = conn.prepareStatement(query2);
- rs = statement.executeQuery();
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000001");
- assertEquals(rs.getString(2), "T1");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000002");
- assertEquals(rs.getString(2), "T2");
- assertEquals(rs.getString(3), "0000000001");
- assertEquals(rs.getString(4), "S1");
- assertTrue (rs.next());
- assertEquals(rs.getString(1), "0000000005");
- assertEquals(rs.getString(2), "T5");
- assertEquals(rs.getString(3), "0000000005");
-
<TRUNCATED>
[13/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
PHOENIX-4246 Breakup join related tests into several integration tests so as not to create too many tables in one test
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/ee20a8c9
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/ee20a8c9
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/ee20a8c9
Branch: refs/heads/master
Commit: ee20a8c9ba8c7b491937eaf93a889010daebba98
Parents: fd77764
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 14:53:14 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 17:51:57 2017 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/BaseJoinIT.java | 470 ---
.../apache/phoenix/end2end/HashJoinCacheIT.java | 482 ---
.../org/apache/phoenix/end2end/HashJoinIT.java | 3448 ------------------
.../phoenix/end2end/HashJoinLocalIndexIT.java | 128 -
.../apache/phoenix/end2end/HashJoinMoreIT.java | 909 -----
.../apache/phoenix/end2end/SortMergeJoinIT.java | 2563 -------------
.../org/apache/phoenix/end2end/SubqueryIT.java | 788 ----
.../end2end/SubqueryUsingSortMergeJoinIT.java | 566 ---
.../apache/phoenix/end2end/join/BaseJoinIT.java | 473 +++
.../phoenix/end2end/join/HashJoinCacheIT.java | 101 +
.../end2end/join/HashJoinGlobalIndexIT.java | 399 ++
.../apache/phoenix/end2end/join/HashJoinIT.java | 2316 ++++++++++++
.../end2end/join/HashJoinLocalIndexIT.java | 528 +++
.../phoenix/end2end/join/HashJoinMoreIT.java | 910 +++++
.../phoenix/end2end/join/HashJoinNoIndexIT.java | 391 ++
.../phoenix/end2end/join/SortMergeJoinIT.java | 2563 +++++++++++++
.../apache/phoenix/end2end/join/SubqueryIT.java | 788 ++++
.../join/SubqueryUsingSortMergeJoinIT.java | 566 +++
18 files changed, 9035 insertions(+), 9354 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseJoinIT.java
deleted file mode 100644
index a823a72..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/BaseJoinIT.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * 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.end2end;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Pattern;
-
-import org.apache.hadoop.hbase.HConstants;
-import org.apache.phoenix.cache.ServerCacheClient;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.ReadOnlyProps;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.StringUtil;
-import org.junit.Before;
-import org.junit.BeforeClass;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
-public abstract class BaseJoinIT extends ParallelStatsDisabledIT {
-
- protected static final String JOIN_SCHEMA = "Join";
- protected static final String JOIN_ORDER_TABLE = "OrderTable";
- protected static final String JOIN_CUSTOMER_TABLE = "CustomerTable";
- protected static final String JOIN_ITEM_TABLE = "ItemTable";
- protected static final String JOIN_SUPPLIER_TABLE = "SupplierTable";
- protected static final String JOIN_COITEM_TABLE = "CoitemTable";
- protected static final String JOIN_ORDER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_ORDER_TABLE + '"';
- protected static final String JOIN_CUSTOMER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_CUSTOMER_TABLE + '"';
- protected static final String JOIN_ITEM_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_ITEM_TABLE + '"';
- protected static final String JOIN_SUPPLIER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_SUPPLIER_TABLE + '"';
- protected static final String JOIN_COITEM_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_COITEM_TABLE + '"';
-
- private static final Map<String,String> tableDDLMap;
-
- static {
- ImmutableMap.Builder<String,String> builder = ImmutableMap.builder();
- builder.put(JOIN_ORDER_TABLE_FULL_NAME, "create table " + JOIN_ORDER_TABLE_FULL_NAME +
- " (\"order_id\" varchar(15) not null primary key, " +
- " \"customer_id\" varchar(10), " +
- " \"item_id\" varchar(10), " +
- " price integer, " +
- " quantity integer, " +
- " date timestamp) IMMUTABLE_ROWS=true");
- builder.put(JOIN_CUSTOMER_TABLE_FULL_NAME, "create table " + JOIN_CUSTOMER_TABLE_FULL_NAME +
- " (\"customer_id\" varchar(10) not null primary key, " +
- " name varchar, " +
- " phone varchar(12), " +
- " address varchar, " +
- " loc_id varchar(5), " +
- " date date) IMMUTABLE_ROWS=true");
- builder.put(JOIN_ITEM_TABLE_FULL_NAME, "create table " + JOIN_ITEM_TABLE_FULL_NAME +
- " (\"item_id\" varchar(10) not null primary key, " +
- " name varchar, " +
- " price integer, " +
- " discount1 integer, " +
- " discount2 integer, " +
- " \"supplier_id\" varchar(10), " +
- " description varchar)");
- builder.put(JOIN_SUPPLIER_TABLE_FULL_NAME, "create table " + JOIN_SUPPLIER_TABLE_FULL_NAME +
- " (\"supplier_id\" varchar(10) not null primary key, " +
- " name varchar, " +
- " phone varchar(12), " +
- " address varchar, " +
- " loc_id varchar(5))");
- builder.put(JOIN_COITEM_TABLE_FULL_NAME, "create table " + JOIN_COITEM_TABLE_FULL_NAME +
- " (item_id varchar(10) NOT NULL, " +
- " item_name varchar NOT NULL, " +
- " co_item_id varchar(10), " +
- " co_item_name varchar " +
- " CONSTRAINT pk PRIMARY KEY (item_id, item_name)) " +
- " SALT_BUCKETS=4");
- tableDDLMap = builder.build();
- }
-
- protected String seqName;
- protected String schemaName;
- protected final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- protected final String[] plans;
- private final String[] indexDDL;
- private final Map<String,String> virtualNameToRealNameMap = Maps.newHashMap();
-
- public BaseJoinIT(String[] indexDDL, String[] plans) {
- this.indexDDL = indexDDL;
- this.plans = plans;
- }
-
- protected String getTableName(Connection conn, String virtualName) throws Exception {
- String realName = virtualNameToRealNameMap.get(virtualName);
- if (realName == null) {
- realName = SchemaUtil.getTableName(schemaName, generateUniqueName());
- virtualNameToRealNameMap.put(virtualName, realName);
- createTable(conn, virtualName, realName);
- initValues(conn, virtualName, realName);
- createIndexes(conn, virtualName, realName);
- }
- return realName;
- }
-
- protected String getDisplayTableName(Connection conn, String virtualName) throws Exception {
- return getTableName(conn, virtualName);
- }
-
- private void createTable(Connection conn, String virtualName, String realName) throws SQLException {
- String ddl = tableDDLMap.get(virtualName);
- if (ddl == null) {
- throw new IllegalStateException("Expected to find " + virtualName + " in " + tableDDLMap);
- }
- ddl = ddl.replace(virtualName, realName);
- conn.createStatement().execute(ddl);
- }
-
- @Before
- public void createSchema() throws SQLException {
- Connection conn = DriverManager.getConnection(getUrl());
- try {
- schemaName = "S_" + generateUniqueName();
- seqName = "SEQ_" + generateUniqueName();
- conn.createStatement().execute("CREATE SEQUENCE " + seqName);
- } finally {
- conn.close();
- }
- }
-
- private String translateToVirtualPlan(String actualPlan) {
- int size = virtualNameToRealNameMap.size();
- String[] virtualNames = new String[size+1];
- String[] realNames = new String[size+1];
- int count = 0;
- for (Map.Entry<String, String>entry : virtualNameToRealNameMap.entrySet()) {
- virtualNames[count] = entry.getKey();
- realNames[count] = entry.getValue();
- count++;
- }
- realNames[count] = schemaName;
- virtualNames[count]= JOIN_SCHEMA;
- String convertedPlan = StringUtil.replace(actualPlan, realNames, virtualNames);
- return convertedPlan;
- }
-
- protected void assertPlansMatch(String virtualPlanRegEx, String actualPlan) {
- String convertedPlan = translateToVirtualPlan(actualPlan);
- assertTrue("\"" + convertedPlan + "\" does not match \"" + virtualPlanRegEx + "\"", Pattern.matches(virtualPlanRegEx, convertedPlan));
- }
-
- protected void assertPlansEqual(String virtualPlan, String actualPlan) {
- String convertedPlan = translateToVirtualPlan(actualPlan);
- assertEquals(virtualPlan, convertedPlan);
- }
-
- private static void initValues(Connection conn, String virtualName, String realName) throws Exception {
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- if (virtualName.equals(JOIN_CUSTOMER_TABLE_FULL_NAME)) {
- // Insert into customer table
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + realName +
- " (\"customer_id\", " +
- " NAME, " +
- " PHONE, " +
- " ADDRESS, " +
- " LOC_ID, " +
- " DATE) " +
- "values (?, ?, ?, ?, ?, ?)");
- stmt.setString(1, "0000000001");
- stmt.setString(2, "C1");
- stmt.setString(3, "999-999-1111");
- stmt.setString(4, "101 XXX Street");
- stmt.setString(5, "10001");
- stmt.setDate(6, new Date(format.parse("2013-11-01 10:20:36").getTime()));
- stmt.execute();
-
- stmt.setString(1, "0000000002");
- stmt.setString(2, "C2");
- stmt.setString(3, "999-999-2222");
- stmt.setString(4, "202 XXX Street");
- stmt.setString(5, null);
- stmt.setDate(6, new Date(format.parse("2013-11-25 16:45:07").getTime()));
- stmt.execute();
-
- stmt.setString(1, "0000000003");
- stmt.setString(2, "C3");
- stmt.setString(3, "999-999-3333");
- stmt.setString(4, "303 XXX Street");
- stmt.setString(5, null);
- stmt.setDate(6, new Date(format.parse("2013-11-25 10:06:29").getTime()));
- stmt.execute();
-
- stmt.setString(1, "0000000004");
- stmt.setString(2, "C4");
- stmt.setString(3, "999-999-4444");
- stmt.setString(4, "404 XXX Street");
- stmt.setString(5, "10004");
- stmt.setDate(6, new Date(format.parse("2013-11-22 14:22:56").getTime()));
- stmt.execute();
-
- stmt.setString(1, "0000000005");
- stmt.setString(2, "C5");
- stmt.setString(3, "999-999-5555");
- stmt.setString(4, "505 XXX Street");
- stmt.setString(5, "10005");
- stmt.setDate(6, new Date(format.parse("2013-11-27 09:37:50").getTime()));
- stmt.execute();
-
- stmt.setString(1, "0000000006");
- stmt.setString(2, "C6");
- stmt.setString(3, "999-999-6666");
- stmt.setString(4, "606 XXX Street");
- stmt.setString(5, "10001");
- stmt.setDate(6, new Date(format.parse("2013-11-01 10:20:36").getTime()));
- stmt.execute();
- } else if (virtualName.equals(JOIN_ITEM_TABLE_FULL_NAME)) {
-
- // Insert into item table
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + realName +
- " (\"item_id\", " +
- " NAME, " +
- " PRICE, " +
- " DISCOUNT1, " +
- " DISCOUNT2, " +
- " \"supplier_id\", " +
- " DESCRIPTION) " +
- "values (?, ?, ?, ?, ?, ?, ?)");
- stmt.setString(1, "0000000001");
- stmt.setString(2, "T1");
- stmt.setInt(3, 100);
- stmt.setInt(4, 5);
- stmt.setInt(5, 10);
- stmt.setString(6, "0000000001");
- stmt.setString(7, "Item T1");
- stmt.execute();
-
- stmt.setString(1, "0000000002");
- stmt.setString(2, "T2");
- stmt.setInt(3, 200);
- stmt.setInt(4, 5);
- stmt.setInt(5, 8);
- stmt.setString(6, "0000000001");
- stmt.setString(7, "Item T2");
- stmt.execute();
-
- stmt.setString(1, "0000000003");
- stmt.setString(2, "T3");
- stmt.setInt(3, 300);
- stmt.setInt(4, 8);
- stmt.setInt(5, 12);
- stmt.setString(6, "0000000002");
- stmt.setString(7, "Item T3");
- stmt.execute();
-
- stmt.setString(1, "0000000004");
- stmt.setString(2, "T4");
- stmt.setInt(3, 400);
- stmt.setInt(4, 6);
- stmt.setInt(5, 10);
- stmt.setString(6, "0000000002");
- stmt.setString(7, "Item T4");
- stmt.execute();
-
- stmt.setString(1, "0000000005");
- stmt.setString(2, "T5");
- stmt.setInt(3, 500);
- stmt.setInt(4, 8);
- stmt.setInt(5, 15);
- stmt.setString(6, "0000000005");
- stmt.setString(7, "Item T5");
- stmt.execute();
-
- stmt.setString(1, "0000000006");
- stmt.setString(2, "T6");
- stmt.setInt(3, 600);
- stmt.setInt(4, 8);
- stmt.setInt(5, 15);
- stmt.setString(6, "0000000006");
- stmt.setString(7, "Item T6");
- stmt.execute();
-
- stmt.setString(1, "invalid001");
- stmt.setString(2, "INVALID-1");
- stmt.setInt(3, 0);
- stmt.setInt(4, 0);
- stmt.setInt(5, 0);
- stmt.setString(6, "0000000000");
- stmt.setString(7, "Invalid item for join test");
- stmt.execute();
- } else if (virtualName.equals(JOIN_SUPPLIER_TABLE_FULL_NAME)) {
-
- // Insert into supplier table
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + realName +
- " (\"supplier_id\", " +
- " NAME, " +
- " PHONE, " +
- " ADDRESS, " +
- " LOC_ID) " +
- "values (?, ?, ?, ?, ?)");
- stmt.setString(1, "0000000001");
- stmt.setString(2, "S1");
- stmt.setString(3, "888-888-1111");
- stmt.setString(4, "101 YYY Street");
- stmt.setString(5, "10001");
- stmt.execute();
-
- stmt.setString(1, "0000000002");
- stmt.setString(2, "S2");
- stmt.setString(3, "888-888-2222");
- stmt.setString(4, "202 YYY Street");
- stmt.setString(5, "10002");
- stmt.execute();
-
- stmt.setString(1, "0000000003");
- stmt.setString(2, "S3");
- stmt.setString(3, "888-888-3333");
- stmt.setString(4, "303 YYY Street");
- stmt.setString(5, null);
- stmt.execute();
-
- stmt.setString(1, "0000000004");
- stmt.setString(2, "S4");
- stmt.setString(3, "888-888-4444");
- stmt.setString(4, "404 YYY Street");
- stmt.setString(5, null);
- stmt.execute();
-
- stmt.setString(1, "0000000005");
- stmt.setString(2, "S5");
- stmt.setString(3, "888-888-5555");
- stmt.setString(4, "505 YYY Street");
- stmt.setString(5, "10005");
- stmt.execute();
-
- stmt.setString(1, "0000000006");
- stmt.setString(2, "S6");
- stmt.setString(3, "888-888-6666");
- stmt.setString(4, "606 YYY Street");
- stmt.setString(5, "10006");
- stmt.execute();
- } else if (virtualName.equals(JOIN_ORDER_TABLE_FULL_NAME)) {
-
- // Insert into order table
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + realName +
- " (\"order_id\", " +
- " \"customer_id\", " +
- " \"item_id\", " +
- " PRICE, " +
- " QUANTITY," +
- " DATE) " +
- "values (?, ?, ?, ?, ?, ?)");
- stmt.setString(1, "000000000000001");
- stmt.setString(2, "0000000004");
- stmt.setString(3, "0000000001");
- stmt.setInt(4, 100);
- stmt.setInt(5, 1000);
- stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-22 14:22:56").getTime()));
- stmt.execute();
-
- stmt.setString(1, "000000000000002");
- stmt.setString(2, "0000000003");
- stmt.setString(3, "0000000006");
- stmt.setInt(4, 552);
- stmt.setInt(5, 2000);
- stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
- stmt.execute();
-
- stmt.setString(1, "000000000000003");
- stmt.setString(2, "0000000002");
- stmt.setString(3, "0000000002");
- stmt.setInt(4, 190);
- stmt.setInt(5, 3000);
- stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-25 16:45:07").getTime()));
- stmt.execute();
-
- stmt.setString(1, "000000000000004");
- stmt.setString(2, "0000000004");
- stmt.setString(3, "0000000006");
- stmt.setInt(4, 510);
- stmt.setInt(5, 4000);
- stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-26 13:26:04").getTime()));
- stmt.execute();
-
- stmt.setString(1, "000000000000005");
- stmt.setString(2, "0000000005");
- stmt.setString(3, "0000000003");
- stmt.setInt(4, 264);
- stmt.setInt(5, 5000);
- stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-27 09:37:50").getTime()));
- stmt.execute();
- } else if (virtualName.equals(JOIN_COITEM_TABLE_FULL_NAME)) {
- // Insert into coitem table
- PreparedStatement stmt = conn.prepareStatement(
- "upsert into " + realName +
- " (item_id, " +
- " item_name, " +
- " co_item_id, " +
- " co_item_name) " +
- "values (?, ?, ?, ?)");
- stmt.setString(1, "0000000001");
- stmt.setString(2, "T1");
- stmt.setString(3, "0000000002");
- stmt.setString(4, "T3");
- stmt.execute();
-
- stmt.setString(1, "0000000004");
- stmt.setString(2, "T4");
- stmt.setString(3, "0000000003");
- stmt.setString(4, "T3");
- stmt.execute();
-
- stmt.setString(1, "0000000003");
- stmt.setString(2, "T4");
- stmt.setString(3, "0000000005");
- stmt.setString(4, "T5");
- stmt.execute();
-
- stmt.setString(1, "0000000006");
- stmt.setString(2, "T6");
- stmt.setString(3, "0000000001");
- stmt.setString(4, "T1");
- stmt.execute();
- }
-
- conn.commit();
- }
-
- protected Connection getConnection() throws SQLException {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- props.put(ServerCacheClient.HASH_JOIN_SERVER_CACHE_RESEND_PER_SERVER, "true");
- return DriverManager.getConnection(getUrl(), props);
- }
-
- protected void createIndexes(Connection conn, String virtualName, String realName) throws Exception {
- if (indexDDL != null && indexDDL.length > 0) {
- for (String ddl : indexDDL) {
- String newDDL = ddl.replace(virtualName, realName);
- if (!newDDL.equals(ddl)) {
- conn.createStatement().execute(newDDL);
- }
- }
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinCacheIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinCacheIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinCacheIT.java
deleted file mode 100644
index cebb9ad..0000000
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinCacheIT.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * 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.end2end;
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.coprocessor.ObserverContext;
-import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
-import org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver;
-import org.apache.hadoop.hbase.regionserver.RegionScanner;
-import org.apache.phoenix.cache.GlobalCache;
-import org.apache.phoenix.cache.TenantCache;
-import org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException;
-import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
-import org.apache.phoenix.join.HashJoinInfo;
-import org.apache.phoenix.query.QueryServices;
-import org.apache.phoenix.util.ByteUtil;
-import org.apache.phoenix.util.PropertiesUtil;
-import org.apache.phoenix.util.SchemaUtil;
-import org.apache.phoenix.util.TestUtil;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import com.google.common.collect.Lists;
-
-import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
-import static org.junit.Assert.fail;
-
-@RunWith(Parameterized.class)
-public class HashJoinCacheIT extends HashJoinIT {
-
- public HashJoinCacheIT(String[] indexDDL, String[] plans) throws Exception {
- super(indexDDL, plans);
- }
-
- protected String getTableName(Connection conn, String virtualName) throws Exception {
- String realName = super.getTableName(conn, virtualName);
- TestUtil.addCoprocessor(conn, SchemaUtil.normalizeFullTableName(realName), InvalidateHashCache.class);
- return realName;
- }
-
- @Parameters
- public static Collection<Object> data() {
- List<Object> testCases = Lists.newArrayList();
- testCases.add(new String[][] {
- {}, {
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC"
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testLeftJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testRightJoinWithAggregation()
- * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
- * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
- * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
- /*
- * testJoinWithWildcard()
- * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
- * ON joinItemTable.supplier_id = supp.supplier_id
- * ORDER BY item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
- * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
- * AND (supp.name BETWEEN 'S1' AND 'S5')
- * WHERE item.name BETWEEN 'T1' AND 'T5'
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME >= 'T1' AND NAME <= 'T5')\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME >= 'S1' AND NAME <= 'S5')",
- /*
- * testJoinPlanWithIndex()
- * SELECT item.item_id, item.name, supp.supplier_id, supp.name
- * FROM joinItemTable item INNER JOIN joinSupplierTable supp
- * ON item.supplier_id = supp.supplier_id
- * WHERE (item.name = 'T1' OR item.name = 'T5')
- * AND (supp.name = 'S1' OR supp.name = 'S5')
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME = 'T1' OR NAME = 'T5')\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY (NAME = 'S1' OR NAME = 'S5')",
- /*
- * testJoinWithSkipMergeOptimization()
- * SELECT s.name FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
- * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY QUANTITY < 5000\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
- /*
- * testSelfJoin()
- * SELECT i2.item_id, i1.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
- * ORDER BY i1.item_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.item_id\")",
- /*
- * testSelfJoin()
- * SELECT i1.name, i2.name FROM joinItemTable i1
- * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
- * ORDER BY i1.name, i2.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [I1.NAME, I2.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.supplier_id\")",
- /*
- * testStarJoin()
- * SELECT order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testStarJoin()
- * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
- * FROM joinOrderTable o
- * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
- * JOIN joinItemTable i ON o.item_id = i.item_id
- * ORDER BY order_id
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER SORTED BY [\"O.order_id\"]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
- /*
- * testSubJoin()
- * SELECT * FROM joinCustomerTable c
- * INNER JOIN (joinOrderTable o
- * INNER JOIN (joinSupplierTable s
- * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
- * ON o.item_id = i.item_id)
- * ON c.customer_id = o.customer_id
- * WHERE c.customer_id <= '0000000005'
- * AND order_id != '000000000000003'
- * AND i.name != 'T3'
- * ORDER BY c.customer_id, i.name
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [\"C.customer_id\", I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY NAME != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.name, sum(quantity) FROM joinOrderTable o
- * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
- * ON o.item_id = i.iid
- * GROUP BY i.name ORDER BY i.name
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT o.iid, sum(o.quantity) q
- * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
- * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
- * ON o.iid = i.item_id
- * GROUP BY o.iid ORDER BY q DESC
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
- "CLIENT MERGE SORT\n" +
- "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
- " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid FROM joinItemTable) AS i
- * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * ON o.iid = i.iid
- * ORDER BY o.q DESC NULLS LAST, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testJoinWithSubqueryAndAggregation()
- * SELECT i.iid, o.q
- * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
- * JOIN (SELECT item_id iid FROM joinItemTable) AS i
- * ON o.iid = i.iid
- * ORDER BY o.q DESC, i.iid
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY FIRST KEY ONLY\n" +
- " SERVER SORTED BY [O.Q DESC, I.IID]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
- " CLIENT MERGE SORT",
- /*
- * testNestedSubqueries()
- * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
- * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
- * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
- * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
- * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
- * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
- * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
- * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
- * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
- * ON i.sid = s.sid) as qi
- * ON o.iid = qi.iiid) as qo
- * ON c.cid = qo.ocid
- * WHERE c.cid <= '0000000005'
- * AND qo.ooid != '000000000000003'
- * AND qo.iname != 'T3'
- * ORDER BY c.cid, qo.iname
- */
- "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
- " SERVER SORTED BY [C.CID, QO.INAME]\n" +
- "CLIENT MERGE SORT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " SERVER FILTER BY NAME != 'T3'\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER 4 ROW LIMIT\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithLimit()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithSetMaxRows()
- * statement.setMaxRows(4);
- * SELECT order_id, i.name, quantity FROM joinItemTable i
- * JOIN joinOrderTable o ON o.item_id = i.item_id;
- * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
- * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
- * ON o.item_id = i.item_id;
- */
- "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- "CLIENT 4 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")\n" +
- " JOIN-SCANNER 4 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- " SERVER 3 ROW LIMIT\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL LEFT-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- /*
- * testJoinWithOffset()
- * SELECT order_id, i.name, s.name, s.address, quantity
- * FROM joinSupplierTable s
- * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
- * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
- */
- "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
- " SERVER OFFSET 2\n" +
- "CLIENT 1 ROW LIMIT\n" +
- " PARALLEL INNER-JOIN TABLE 0\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
- " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
- " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
- " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
- " JOIN-SCANNER 3 ROW LIMIT",
- }});
- return testCases;
- }
-
- @Test
- public void testInnerJoin() throws Exception {
- // it involves sequences which may be incremented on re-try when hash
- // cache is removed so this test may flap sometimes, so we don't need to
- // test it for this case.
- }
-
- @Test
- public void testUpsertWithJoin() throws Exception {
- // TODO: We will enable this test once PHOENIX-3163
- }
-
- @Test
- public void testExpiredCache() throws Exception {
- Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
- props.setProperty(QueryServices.MAX_SERVER_CACHE_TIME_TO_LIVE_MS_ATTRIB, "1");
- Connection conn = DriverManager.getConnection(getUrl(), props);
- String tableName1 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
- String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
- String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " +
- tableName1 + " supp RIGHT JOIN " + tableName2 +
- " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
- try {
- PreparedStatement statement = conn.prepareStatement(query);
- ResultSet rs = statement.executeQuery();
- rs.next();
- fail("HashJoinCacheNotFoundException was not thrown or incorrectly handled");
- } catch (HashJoinCacheNotFoundException e) {
- //Expected exception
- }
- }
-
- public static class InvalidateHashCache extends SimpleRegionObserver {
- public static Random rand= new Random();
- public static List<ImmutableBytesPtr> lastRemovedJoinIds=new ArrayList<ImmutableBytesPtr>();
- @Override
- public RegionScanner preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c, final Scan scan,
- final RegionScanner s) throws IOException {
- final HashJoinInfo joinInfo = HashJoinInfo.deserializeHashJoinFromScan(scan);
- if (joinInfo != null) {
- TenantCache cache = GlobalCache.getTenantCache(c.getEnvironment(), null);
- int count = joinInfo.getJoinIds().length;
- for (int i = 0; i < count; i++) {
- ImmutableBytesPtr joinId = joinInfo.getJoinIds()[i];
- if (!ByteUtil.contains(lastRemovedJoinIds,joinId)) {
- lastRemovedJoinIds.add(joinId);
- cache.removeServerCache(joinId);
- }
- }
- }
- return s;
- }
-
- }
-}
[22/25] phoenix git commit: PHOENIX-4249 Decrease unique name
allocation for SequenceIT
Posted by ja...@apache.org.
PHOENIX-4249 Decrease unique name allocation for SequenceIT
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/3593ec8b
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/3593ec8b
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/3593ec8b
Branch: refs/heads/master
Commit: 3593ec8bc0042388f119652dc8177efc05f39d80
Parents: 3d9adc6
Author: James Taylor <jt...@salesforce.com>
Authored: Thu Sep 28 17:17:24 2017 -0700
Committer: James Taylor <jt...@salesforce.com>
Committed: Thu Sep 28 18:23:44 2017 -0700
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/SequenceIT.java | 191 ++++++++++---------
.../java/org/apache/phoenix/query/BaseTest.java | 14 ++
2 files changed, 112 insertions(+), 93 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3593ec8b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
index e226491..bcb3a40 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/SequenceIT.java
@@ -61,11 +61,16 @@ import com.google.common.collect.Maps;
public class SequenceIT extends ParallelStatsDisabledIT {
private static final String SELECT_NEXT_VALUE_SQL = "SELECT NEXT VALUE FOR %s";
private static final long BATCH_SIZE = 3;
+ private static final String SCHEMA_NAME = "S";
private Connection conn;
- private static String generateNameWithSchema() {
- return SchemaUtil.getTableName(generateUniqueName(), generateUniqueName());
+ private static String generateTableNameWithSchema() {
+ return SchemaUtil.getTableName(SCHEMA_NAME, generateUniqueName());
+ }
+
+ private static String generateSequenceNameWithSchema() {
+ return SchemaUtil.getTableName(SCHEMA_NAME, generateUniqueSequenceName());
}
@BeforeClass
@@ -91,7 +96,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSystemTable() throws Exception {
- conn.createStatement().execute("CREATE SEQUENCE " + generateNameWithSchema());
+ conn.createStatement().execute("CREATE SEQUENCE " + generateSequenceNameWithSchema());
String query = "SELECT sequence_schema, sequence_name, current_value, increment_by FROM \"SYSTEM\".\"SEQUENCE\"";
ResultSet rs = conn.prepareStatement(query).executeQuery();
assertTrue(rs.next());
@@ -99,7 +104,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testDuplicateSequences() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 2 INCREMENT BY 4\n");
@@ -114,7 +119,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceNotFound() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String query = "SELECT NEXT value FOR " + sequenceName ;
@@ -132,7 +137,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
props.setProperty(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, Boolean.toString(true));
Connection nsConn = DriverManager.getConnection(getUrl(), props);
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceSchemaName = getSchemaName(sequenceName);
try {
@@ -169,7 +174,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testCreateSequence() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
String schemaName = getSchemaName(sequenceName);
@@ -186,7 +191,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testCurrentValueFor() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
ResultSet rs;
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 2 INCREMENT BY 4");
@@ -210,7 +215,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testDropSequence() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
String schemaName = getSchemaName(sequenceName);
@@ -238,15 +243,15 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueFor() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 3 INCREMENT BY 2");
assertSequenceValuesForSingleRow(sequenceName, 3, 5, 7);
}
@Test
public void testInsertNextValueFor() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 2 INCREMENT BY 1");
conn.createStatement().execute("CREATE TABLE " + tableName + " ( id INTEGER NOT NULL PRIMARY KEY)");
@@ -263,7 +268,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceCreation() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
String schemaName = getSchemaName(sequenceName);
@@ -307,7 +312,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSameMultipleSequenceValues() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 4 INCREMENT BY 7");
String query = "SELECT NEXT VALUE FOR " + sequenceName + ", NEXT VALUE FOR " + sequenceName ;
@@ -321,8 +326,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testMultipleSequenceValues() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 4 INCREMENT BY 7");
conn.createStatement().execute("CREATE SEQUENCE " + alternateSequenceName + " START WITH 9 INCREMENT BY 2");
@@ -352,7 +357,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testMultipleSequencesNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
String schemaName = getSchemaName(sequenceName);
String alternateSequenceName = sequenceName + "_ALT";
@@ -394,8 +399,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testMultipleSequencesCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute(
"CREATE SEQUENCE " + sequenceName + " START WITH 4 INCREMENT BY 7 MINVALUE 4 MAXVALUE 19 CYCLE");
@@ -424,8 +429,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testCompilerOptimization() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 3 INCREMENT BY 2");
conn.createStatement().execute("CREATE TABLE " + tableName + " (k INTEGER NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR) IMMUTABLE_ROWS=true");
@@ -438,8 +443,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectRowAndSequence() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 1 INCREMENT BY 4");
conn.createStatement().execute("CREATE TABLE " + tableName + " ( id INTEGER NOT NULL PRIMARY KEY)");
@@ -456,8 +461,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueForOverMultipleBatches() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY)");
@@ -476,15 +481,15 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueForGroupBy() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
- String SECOND_tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName1 = generateTableNameWithSchema();
+ String tableName2 = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
- conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY, v VARCHAR)");
- conn.createStatement().execute("CREATE TABLE "+ SECOND_tableName + " (k BIGINT NOT NULL PRIMARY KEY, v VARCHAR)");
+ conn.createStatement().execute("CREATE TABLE " + tableName1 + " (k BIGINT NOT NULL PRIMARY KEY, v VARCHAR)");
+ conn.createStatement().execute("CREATE TABLE "+ tableName2 + " (k BIGINT NOT NULL PRIMARY KEY, v VARCHAR)");
- PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " VALUES(NEXT VALUE FOR " + sequenceName + ", ?)");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName1 + " VALUES(NEXT VALUE FOR " + sequenceName + ", ?)");
stmt.setString(1, "a");
stmt.execute();
stmt.setString(1, "a");
@@ -497,7 +502,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
stmt.execute();
conn.commit();
- ResultSet rs = conn.createStatement().executeQuery("SELECT k from " + tableName );
+ ResultSet rs = conn.createStatement().executeQuery("SELECT k from " + tableName1 );
assertTrue(rs.next());
assertEquals(1, rs.getInt(1));
assertTrue(rs.next());
@@ -512,9 +517,9 @@ public class SequenceIT extends ParallelStatsDisabledIT {
conn.setAutoCommit(true);;
- conn.createStatement().execute("UPSERT INTO " + SECOND_tableName + " SELECT NEXT VALUE FOR " + sequenceName + ",v FROM " + tableName + " GROUP BY v");
+ conn.createStatement().execute("UPSERT INTO " + tableName2 + " SELECT NEXT VALUE FOR " + sequenceName + ",v FROM " + tableName1 + " GROUP BY v");
- rs = conn.createStatement().executeQuery("SELECT * from " + SECOND_tableName);
+ rs = conn.createStatement().executeQuery("SELECT * from " + tableName2);
assertTrue(rs.next());
assertEquals(6, rs.getInt(1));
assertEquals("a", rs.getString(2));
@@ -529,8 +534,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueForMultipleConn() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY)");
@@ -563,8 +568,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueForMultipleConnWithStmtClose() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY)");
@@ -593,8 +598,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSelectNextValueForMultipleConnWithConnClose() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY)");
@@ -632,9 +637,9 @@ public class SequenceIT extends ParallelStatsDisabledIT {
}
private void testDropCachedSeq(boolean detectDeleteSeqInEval) throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE SEQUENCE " + alternateSequenceName + " START WITH 101");
@@ -690,9 +695,9 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testExplainPlanValidatesSequences() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
- String tableName = generateNameWithSchema();
+ String tableName = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement().execute("CREATE TABLE " + tableName + " (k BIGINT NOT NULL PRIMARY KEY)");
@@ -731,12 +736,12 @@ public class SequenceIT extends ParallelStatsDisabledIT {
}
private String generateSequenceName() {
- return generateUniqueName();
+ return generateUniqueSequenceName();
}
@Test
public void testSelectNextValueInArithmetic() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 3 INCREMENT BY 2");
@@ -753,7 +758,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDefault() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
@@ -787,8 +792,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateStartValue() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
try {
conn.createStatement().execute(
@@ -813,7 +818,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateMinValue() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
try {
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " MINVALUE abc");
@@ -827,7 +832,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateMaxValue() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
try {
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " MAXVALUE null");
@@ -841,7 +846,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateMinValueLessThanOrEqualToMaxValue() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
try {
@@ -857,7 +862,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateIncrementConstant() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
try {
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " INCREMENT null");
@@ -871,7 +876,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceValidateIncrementNotEqualToZero() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
try {
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " INCREMENT 0");
@@ -885,7 +890,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceStartWithMinMaxSameValueIncreasingCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
@@ -896,7 +901,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceStartWithMinMaxSameValueDecreasingCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
@@ -907,7 +912,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceStartWithMinMaxSameValueIncreasingNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
@@ -928,7 +933,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceStartWithMinMaxSameValueDecreasingNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
@@ -948,7 +953,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceIncreasingCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
@@ -958,7 +963,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDecreasingCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
@@ -968,7 +973,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceIncreasingNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// client throws exception
@@ -988,7 +993,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceIncreasingUsingMaxValueNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// server throws exception
conn.createStatement().execute(
@@ -1007,7 +1012,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDecreasingNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// client will throw exception
conn.createStatement()
@@ -1027,7 +1032,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDecreasingUsingMinValueNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// server will throw exception
conn.createStatement().execute(
@@ -1046,7 +1051,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceIncreasingOverflowNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// start with Long.MAX_VALUE
conn.createStatement().execute(
@@ -1066,7 +1071,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceIncreasingOverflowCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// start with Long.MAX_VALUE
conn.createStatement()
@@ -1078,7 +1083,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDecreasingOverflowNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// start with Long.MIN_VALUE + 1
conn.createStatement().execute(
@@ -1097,7 +1102,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testSequenceDecreasingOverflowCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// start with Long.MIN_VALUE + 1
conn.createStatement()
@@ -1109,8 +1114,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testMultipleSequenceValuesNoCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
conn.createStatement().execute(
"CREATE SEQUENCE " + sequenceName + " START WITH 1 INCREMENT BY 2 MINVALUE 1 MAXVALUE 10 CACHE 2");
@@ -1144,8 +1149,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testMultipleSequenceValuesCycle() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
conn.createStatement()
.execute(
"CREATE SEQUENCE " + sequenceName + " START WITH 1 INCREMENT BY 2 MINVALUE 1 MAXVALUE 10 CYCLE CACHE 2");
@@ -1161,36 +1166,36 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testUpsertSelectGroupByWithSequence() throws Exception {
- String sequenceName = generateNameWithSchema();
- String tableName = generateNameWithSchema();
- String SECOND_tableName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String tableName1 = generateTableNameWithSchema();
+ String tableName2 = generateTableNameWithSchema();
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName);
conn.createStatement()
.execute(
- "CREATE TABLE " + tableName + "(event_id BIGINT NOT NULL PRIMARY KEY, user_id char(15), val BIGINT )");
+ "CREATE TABLE " + tableName1 + "(event_id BIGINT NOT NULL PRIMARY KEY, user_id char(15), val BIGINT )");
conn.createStatement()
.execute(
- "CREATE TABLE " + SECOND_tableName + " (metric_id char(15) NOT NULL PRIMARY KEY, agg_id char(15), metric_val INTEGER )");
+ "CREATE TABLE " + tableName2 + " (metric_id char(15) NOT NULL PRIMARY KEY, agg_id char(15), metric_val INTEGER )");
// 2 rows for user1, 3 rows for user2 and 1 row for user3
- insertEvent(tableName, 1, "user1", 1);
- insertEvent(tableName, 2, "user2", 1);
- insertEvent(tableName, 3, "user1", 1);
- insertEvent(tableName, 4, "user2", 1);
- insertEvent(tableName, 5, "user2", 1);
- insertEvent(tableName, 6, "user3", 1);
+ insertEvent(tableName1, 1, "user1", 1);
+ insertEvent(tableName1, 2, "user2", 1);
+ insertEvent(tableName1, 3, "user1", 1);
+ insertEvent(tableName1, 4, "user2", 1);
+ insertEvent(tableName1, 5, "user2", 1);
+ insertEvent(tableName1, 6, "user3", 1);
conn.commit();
conn.createStatement()
.execute(
- "UPSERT INTO " + SECOND_tableName + " SELECT 'METRIC_'||(LPAD(ENCODE(NEXT VALUE FOR " + sequenceName + ",'base62'),5,'0')), user_id, sum(val) FROM " + tableName + " GROUP BY user_id ORDER BY user_id");
+ "UPSERT INTO " + tableName2 + " SELECT 'METRIC_'||(LPAD(ENCODE(NEXT VALUE FOR " + sequenceName + ",'base62'),5,'0')), user_id, sum(val) FROM " + tableName1 + " GROUP BY user_id ORDER BY user_id");
conn.commit();
PreparedStatement stmt =
- conn.prepareStatement("SELECT metric_id, agg_id, metric_val FROM " + SECOND_tableName);
+ conn.prepareStatement("SELECT metric_id, agg_id, metric_val FROM " + tableName2);
ResultSet rs = stmt.executeQuery();
assertTrue(rs.next());
assertEquals("METRIC_00001", rs.getString("metric_id"));
@@ -1215,7 +1220,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
* value was being unset from true to false.
*/
public void testNextValuesForSequenceClosingConnections() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
// Create Sequence
conn.createStatement().execute("CREATE SEQUENCE " + sequenceName + " START WITH 4990 MINVALUE 4990 MAXVALUE 5000 CACHE 10");
@@ -1295,8 +1300,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testValidateBeforeReserve() throws Exception {
- String tableName = generateNameWithSchema();
- String seqName = generateNameWithSchema();
+ String tableName = generateTableNameWithSchema();
+ String seqName = generateSequenceNameWithSchema();
conn.createStatement().execute(
"CREATE TABLE " + tableName + " (k VARCHAR PRIMARY KEY, l BIGINT)");
@@ -1335,8 +1340,8 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testNoFromClause() throws Exception {
- String sequenceName = generateNameWithSchema();
- String alternateSequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
+ String alternateSequenceName = generateSequenceNameWithSchema();
ResultSet rs;
@@ -1367,7 +1372,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testReturnAllSequencesNotCalledForNoOpenConnections() throws Exception {
- String sequenceName = generateNameWithSchema();
+ String sequenceName = generateSequenceNameWithSchema();
String sequenceNameWithoutSchema = getNameWithoutSchema(sequenceName);
String schemaName = getSchemaName(sequenceName);
@@ -1404,7 +1409,7 @@ public class SequenceIT extends ParallelStatsDisabledIT {
@Test
public void testPointInTimeSequence() throws Exception {
- String seqName = generateNameWithSchema();
+ String seqName = generateSequenceNameWithSchema();
Properties scnProps = PropertiesUtil.deepCopy(TEST_PROPERTIES);
scnProps.put(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(EnvironmentEdgeManager.currentTimeMillis()));
Connection beforeSeqConn = DriverManager.getConnection(getUrl(), scnProps);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/3593ec8b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
index a77305c..2c85bb2 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
@@ -726,6 +726,20 @@ public abstract class BaseTest {
return "T" + Integer.toString(MAX_SUFFIX_VALUE + nextName).substring(1);
}
+ private static AtomicInteger SEQ_NAME_SUFFIX = new AtomicInteger(0);
+ private static final int MAX_SEQ_SUFFIX_VALUE = 1000000;
+
+ private static final AtomicInteger SEQ_COUNTER = new AtomicInteger(0);
+
+ public static String generateUniqueSequenceName() {
+ int nextName = SEQ_NAME_SUFFIX.incrementAndGet();
+ if (nextName >= MAX_SEQ_SUFFIX_VALUE) {
+ throw new IllegalStateException("Used up all unique sequence names");
+ }
+ SEQ_COUNTER.incrementAndGet();
+ return "S" + Integer.toString(MAX_SEQ_SUFFIX_VALUE + nextName).substring(1);
+ }
+
public static void tearDownMiniClusterIfBeyondThreshold() throws Exception {
if (TABLE_COUNTER.get() > TEARDOWN_THRESHOLD) {
int numTables = TABLE_COUNTER.get();
[05/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
new file mode 100644
index 0000000..7f8528d
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinNoIndexIT.java
@@ -0,0 +1,391 @@
+/*
+ * 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.end2end.join;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+public class HashJoinNoIndexIT extends HashJoinIT {
+
+ public HashJoinNoIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {}, {
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC"
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithWildcard()
+ * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
+ * ON joinItemTable.supplier_id = supp.supplier_id
+ * ORDER BY item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
+ * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
+ * AND (supp.name BETWEEN 'S1' AND 'S5')
+ * WHERE item.name BETWEEN 'T1' AND 'T5'
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY (NAME >= 'T1' AND NAME <= 'T5')\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY (NAME >= 'S1' AND NAME <= 'S5')",
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item INNER JOIN joinSupplierTable supp
+ * ON item.supplier_id = supp.supplier_id
+ * WHERE (item.name = 'T1' OR item.name = 'T5')
+ * AND (supp.name = 'S1' OR supp.name = 'S5')
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY (NAME = 'T1' OR NAME = 'T5')\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY (NAME = 'S1' OR NAME = 'S5')",
+ /*
+ * testJoinWithSkipMergeOptimization()
+ * SELECT s.name FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
+ * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
+ /*
+ * testSelfJoin()
+ * SELECT i2.item_id, i1.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
+ * ORDER BY i1.item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.item_id\")",
+ /*
+ * testSelfJoin()
+ * SELECT i1.name, i2.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
+ * ORDER BY i1.name, i2.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [I1.NAME, I2.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.supplier_id\")",
+ /*
+ * testStarJoin()
+ * SELECT order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
+ /*
+ * testStarJoin()
+ * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER SORTED BY [\"O.order_id\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")",
+ /*
+ * testSubJoin()
+ * SELECT * FROM joinCustomerTable c
+ * INNER JOIN (joinOrderTable o
+ * INNER JOIN (joinSupplierTable s
+ * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
+ * ON o.item_id = i.item_id)
+ * ON c.customer_id = o.customer_id
+ * WHERE c.customer_id <= '0000000005'
+ * AND order_id != '000000000000003'
+ * AND i.name != 'T3'
+ * ORDER BY c.customer_id, i.name
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [\"C.customer_id\", I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY NAME != 'T3'\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
+ * ON o.item_id = i.iid
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME,
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT o.iid, sum(o.quantity) q
+ * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
+ * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
+ * ON o.iid = i.item_id
+ * GROUP BY o.iid ORDER BY q DESC
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid FROM joinItemTable) AS i
+ * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC NULLS LAST, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * JOIN (SELECT item_id iid FROM joinItemTable) AS i
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC, I.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testNestedSubqueries()
+ * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
+ * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
+ * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
+ * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
+ * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
+ * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
+ * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
+ * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
+ * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
+ * ON i.sid = s.sid) as qi
+ * ON o.iid = qi.iiid) as qo
+ * ON c.cid = qo.ocid
+ * WHERE c.cid <= '0000000005'
+ * AND qo.ooid != '000000000000003'
+ * AND qo.iname != 'T3'
+ * ORDER BY c.cid, qo.iname
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [C.CID, QO.INAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY NAME != 'T3'\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER 4 ROW LIMIT\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithSetMaxRows()
+ * statement.setMaxRows(4);
+ * SELECT order_id, i.name, quantity FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id;
+ * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
+ * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
+ * ON o.item_id = i.item_id;
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"I.item_id\" IN (\"O.item_id\")\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithOffset()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ " SERVER 3 ROW LIMIT\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ /*
+ * testJoinWithOffset()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.supplier_id\")\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ }});
+ return testCases;
+ }
+}
[06/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
new file mode 100644
index 0000000..dcc454f
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinLocalIndexIT.java
@@ -0,0 +1,528 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+@RunWith(Parameterized.class)
+public class HashJoinLocalIndexIT extends HashJoinIT {
+
+ public HashJoinLocalIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {
+ "CREATE LOCAL INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE LOCAL INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE LOCAL INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC"
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.:item_id\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME+" [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithWildcard()
+ * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
+ * ON joinItemTable.supplier_id = supp.supplier_id
+ * ORDER BY item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
+ * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
+ * AND (supp.name BETWEEN 'S1' AND 'S5')
+ * WHERE item.name BETWEEN 'T1' AND 'T5'
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,'T1'] - [1,'T5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME +" [1,'S1'] - [1,'S5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item INNER JOIN joinSupplierTable supp
+ * ON item.supplier_id = supp.supplier_id
+ * WHERE (item.name = 'T1' OR item.name = 'T5')
+ * AND (supp.name = 'S1' OR supp.name = 'S5')
+ */
+ "CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,'T1'] - [1,'T5']\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME +" [1,'S1'] - [1,'S5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSkipMergeOptimization()
+ * SELECT s.name FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
+ * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")",
+ /*
+ * testSelfJoin()
+ * SELECT i2.item_id, i1.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
+ * ORDER BY i1.item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.:item_id\")",
+ /*
+ * testSelfJoin()
+ * SELECT i1.name, i2.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
+ * ORDER BY i1.name, i2.name
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.0:NAME\", \"I2.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I1.:item_id\" IN (\"I2.0:supplier_id\")",
+ /*
+ * testStarJoin()
+ * SELECT order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testStarJoin()
+ * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"O.order_id\"]\n"+
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME+" [1]\n"+
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")",
+ /*
+ * testSubJoin()
+ * SELECT * FROM joinCustomerTable c
+ * INNER JOIN (joinOrderTable o
+ * INNER JOIN (joinSupplierTable s
+ * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
+ * ON o.item_id = i.item_id)
+ * ON c.customer_id = o.customer_id
+ * WHERE c.customer_id <= '0000000005'
+ * AND order_id != '000000000000003'
+ * AND i.name != 'T3'
+ * ORDER BY c.customer_id, i.name
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [\"C.customer_id\", \"I.0:NAME\"]\n"+
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME +" [1]\n" +
+ " SERVER FILTER BY \"NAME\" != 'T3'\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
+ * ON o.item_id = i.iid
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME+" [1]\n"+
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT o.iid, sum(o.quantity) q
+ * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
+ * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
+ * ON o.iid = i.item_id
+ * GROUP BY o.iid ORDER BY q DESC
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " +JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid FROM joinItemTable) AS i
+ * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC NULLS LAST, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n"+
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * JOIN (SELECT item_id iid FROM joinItemTable) AS i
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC, I.IID]\n"+
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testNestedSubqueries()
+ * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
+ * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
+ * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
+ * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
+ * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
+ * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
+ * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
+ * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
+ * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
+ * ON i.sid = s.sid) as qi
+ * ON o.iid = qi.iiid) as qo
+ * ON c.cid = qo.ocid
+ * WHERE c.cid <= '0000000005'
+ * AND qo.ooid != '000000000000003'
+ * AND qo.iname != 'T3'
+ * ORDER BY c.cid, qo.iname
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [C.CID, QO.INAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY \"NAME\" != 'T3'\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER 4 ROW LIMIT\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithSetMaxRows()
+ * statement.setMaxRows(4);
+ * SELECT order_id, i.name, quantity FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id;
+ * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
+ * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
+ * ON o.item_id = i.item_id;
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"I.:item_id\" IN (\"O.item_id\")\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithOffset()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ " SERVER 3 ROW LIMIT\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ /*
+ * testJoinWithOffset()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER "+ JOIN_ITEM_TABLE_FULL_NAME + " [1]\n" +
+ " CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ /*
+ * testJoinWithLocalIndex()
+ * SELECT phone, i.name
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON s.supplier_id = i.supplier_id
+ * WHERE s.name = 'S1' AND i.name < 'T6'
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,'S1']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"S.:supplier_id\" IN (\"I.0:supplier_id\")",
+
+ /*
+ * testJoinWithLocalIndex()
+ * SELECT phone, max(i.name)
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON s."supplier_id" = i."supplier_id"
+ * WHERE s.name = 'S1' AND i.name < 'T6'
+ * GROUP BY phone
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,'S1']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"S.PHONE\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY \"S.:supplier_id\" IN (\"I.0:supplier_id\")",
+
+ /*
+ * testJoinWithLocalIndex()
+ * SELECT max(phone), max(i.name)
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON s."supplier_id" = i."supplier_id" AND i.name < 'T6'
+ * WHERE s.name <= 'S3'
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + " [1,*] - [1,'S3']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO SINGLE ROW\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + " [1,*] - [1,'T6']\n" +
+ " CLIENT MERGE SORT",
+ }});
+ return testCases;
+ }
+
+ @Test
+ public void testJoinWithLocalIndex() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ String query = "select phone, i.name from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" where s.name = 'S1' and i.name < 'T6'";
+ System.out.println("1)\n" + query);
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "888-888-1111");
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "888-888-1111");
+ assertFalse(rs.next());
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[24], QueryUtil.getExplainPlan(rs));
+
+ query = "select phone, max(i.name) from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" where s.name = 'S1' and i.name < 'T6' group by phone";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "888-888-1111");
+ assertEquals(rs.getString(2), "T2");
+ assertFalse(rs.next());
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[25], QueryUtil.getExplainPlan(rs));
+
+ query = "select max(phone), max(i.name) from " + getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME) + " s left join " + getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME) + " i on s.\"supplier_id\" = i.\"supplier_id\" and i.name < 'T6' where s.name <= 'S3'";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue (rs.next());
+ assertEquals(rs.getString(1), "888-888-3333");
+ assertEquals(rs.getString(2), "T4");
+ assertFalse(rs.next());
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertPlansEqual(plans[26], QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinMoreIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinMoreIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinMoreIT.java
new file mode 100644
index 0000000..37ffd02
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinMoreIT.java
@@ -0,0 +1,910 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Array;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Properties;
+
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+
+public class HashJoinMoreIT extends ParallelStatsDisabledIT {
+ private final String[] plans = new String[] {
+ /*
+ * testJoinWithKeyRangeOptimization()
+ * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
+ * FROM TEMP_TABLE_COMPOSITE_PK lhs
+ * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col1 = rhs.col2
+ */
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithKeyRangeOptimization()
+ * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
+ * FROM TEMP_TABLE_COMPOSITE_PK lhs
+ * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col2
+ */
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY LHS.COL0 IN (RHS.COL2)",
+ /*
+ * testJoinWithKeyRangeOptimization()
+ * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
+ * FROM TEMP_TABLE_COMPOSITE_PK lhs
+ * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col1 AND lhs.col1 = rhs.col2
+ */
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY (LHS.COL0, LHS.COL1) IN ((RHS.COL1, RHS.COL2))",
+ /*
+ * testJoinWithKeyRangeOptimization()
+ * SELECT lhs.col0, lhs.col1, lhs.col2, rhs.col0, rhs.col1, rhs.col2
+ * FROM TEMP_TABLE_COMPOSITE_PK lhs
+ * JOIN TEMP_TABLE_COMPOSITE_PK rhs ON lhs.col0 = rhs.col1 AND lhs.col2 = rhs.col3 - 1 AND lhs.col1 = rhs.col2
+ */
+ "CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 4-WAY FULL SCAN OVER %s\n" +
+ " CLIENT MERGE SORT\n" +
+ " DYNAMIC SERVER FILTER BY (LHS.COL0, LHS.COL1, LHS.COL2) IN ((RHS.COL1, RHS.COL2, TO_INTEGER((RHS.COL3 - 1))))",
+ };
+
+ @Test
+ public void testJoinOverSaltedTables() throws Exception {
+ String tempTableNoSalting = generateUniqueName();
+ String tempTableWithSalting = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTableNoSalting
+ + " (mypk INTEGER NOT NULL PRIMARY KEY, "
+ + " col1 INTEGER)");
+ conn.createStatement().execute("CREATE TABLE " + tempTableWithSalting
+ + " (mypk INTEGER NOT NULL PRIMARY KEY, "
+ + " col1 INTEGER) SALT_BUCKETS=4");
+
+ PreparedStatement upsertStmt = conn.prepareStatement(
+ "upsert into " + tempTableNoSalting + "(mypk, col1) " + "values (?, ?)");
+ for (int i = 0; i < 3; i++) {
+ upsertStmt.setInt(1, i + 1);
+ upsertStmt.setInt(2, 3 - i);
+ upsertStmt.execute();
+ }
+ conn.commit();
+
+ upsertStmt = conn.prepareStatement(
+ "upsert into " + tempTableWithSalting + "(mypk, col1) " + "values (?, ?)");
+ for (int i = 0; i < 6; i++) {
+ upsertStmt.setInt(1, i + 1);
+ upsertStmt.setInt(2, 3 - (i % 3));
+ upsertStmt.execute();
+ }
+ conn.commit();
+
+ // LHS=unsalted JOIN RHS=salted
+ String query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
+ + tempTableNoSalting + " lhs JOIN "
+ + tempTableWithSalting + " rhs ON rhs.mypk = lhs.col1";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 1);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 3);
+ assertEquals(rs.getInt(4), 1);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 2);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 1);
+ assertEquals(rs.getInt(4), 3);
+
+ assertFalse(rs.next());
+
+ // LHS=salted JOIN RHS=salted
+ query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
+ + tempTableWithSalting + " lhs JOIN "
+ + tempTableNoSalting + " rhs ON rhs.mypk = lhs.col1";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 1);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 3);
+ assertEquals(rs.getInt(4), 1);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 2);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 1);
+ assertEquals(rs.getInt(4), 3);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 4);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 3);
+ assertEquals(rs.getInt(4), 1);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 5);
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 2);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 6);
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 1);
+ assertEquals(rs.getInt(4), 3);
+
+ assertFalse(rs.next());
+
+ // LHS=salted JOIN RHS=salted
+ query = "SELECT lhs.mypk, lhs.col1, rhs.mypk, rhs.col1 FROM "
+ + tempTableWithSalting + " lhs JOIN "
+ + tempTableWithSalting + " rhs ON rhs.mypk = (lhs.col1 + 3)";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 1);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 6);
+ assertEquals(rs.getInt(4), 1);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 4);
+ assertEquals(rs.getInt(4), 3);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 4);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 6);
+ assertEquals(rs.getInt(4), 1);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 5);
+ assertEquals(rs.getInt(2), 2);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 2);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 6);
+ assertEquals(rs.getInt(2), 1);
+ assertEquals(rs.getInt(3), 4);
+ assertEquals(rs.getInt(4), 3);
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testJoinOnDynamicColumns() throws Exception {
+ String tableA = generateUniqueName();
+ String tableB = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ try {
+ conn = DriverManager.getConnection(getUrl(), props);
+ String ddlA = "CREATE TABLE " + tableA + " (pkA INTEGER NOT NULL, " + " colA1 INTEGER, "
+ + " colA2 VARCHAR " + "CONSTRAINT PK PRIMARY KEY" + "(pkA)" + ")";
+
+ String ddlB = "CREATE TABLE " + tableB + " (pkB INTEGER NOT NULL PRIMARY KEY, " + " colB INTEGER)";
+ conn.createStatement().execute(ddlA);
+ conn.createStatement().execute(ddlB);
+
+ String upsertA = "UPSERT INTO " + tableA + " (pkA, colA1, colA2) VALUES(?, ?, ?)";
+ stmt = conn.prepareStatement(upsertA);
+ int i = 0;
+ for (i = 0; i < 5; i++) {
+ stmt.setInt(1, i);
+ stmt.setInt(2, i + 10);
+ stmt.setString(3, "00" + i);
+ stmt.executeUpdate();
+ }
+ conn.commit();
+ stmt.close();
+
+ String sequenceB = generateUniqueName();
+ // upsert select dynamic columns in tableB
+ conn.createStatement().execute("CREATE SEQUENCE " + sequenceB );
+ String upsertBSelectA = "UPSERT INTO " + tableB + " (pkB, pkA INTEGER)"
+ + "SELECT NEXT VALUE FOR " + sequenceB + ", pkA FROM " + tableA ;
+ stmt = conn.prepareStatement(upsertBSelectA);
+ stmt.executeUpdate();
+ stmt.close();
+ conn.commit();
+ conn.createStatement().execute("DROP SEQUENCE " + sequenceB );
+
+ // perform a join between tableB and tableA by joining on the dynamic column that we upserted in
+ // tableB. This join should return all the rows from table A.
+ String joinSql = "SELECT A.pkA, A.COLA1, A.colA2 FROM " + tableB + " B(pkA INTEGER) JOIN " + tableA + " A ON a.pkA = b.pkA";
+ stmt = conn.prepareStatement(joinSql);
+ ResultSet rs = stmt.executeQuery();
+ i = 0;
+ while (rs.next()) {
+ // check that we get back all the rows that we upserted for tableA above.
+ assertEquals(rs.getInt(1), i);
+ assertEquals(rs.getInt(2), i + 10);
+ assertEquals(rs.getString(3), "00" + i);
+ i++;
+ }
+ assertEquals(5,i);
+ } finally {
+ if (stmt != null) {
+ stmt.close();
+ }
+ if (conn != null) {
+ conn.close();
+ }
+
+ }
+
+ }
+
+ @Test
+ public void testJoinWithKeyRangeOptimization() throws Exception {
+ String tempTableWithCompositePK = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE " + tempTableWithCompositePK
+ + " (col0 INTEGER NOT NULL, "
+ + " col1 INTEGER NOT NULL, "
+ + " col2 INTEGER NOT NULL, "
+ + " col3 INTEGER "
+ + " CONSTRAINT pk PRIMARY KEY (col0, col1, col2)) "
+ + " SALT_BUCKETS=4");
+
+ PreparedStatement upsertStmt = conn.prepareStatement(
+ "upsert into " + tempTableWithCompositePK + "(col0, col1, col2, col3) " + "values (?, ?, ?, ?)");
+ for (int i = 0; i < 3; i++) {
+ upsertStmt.setInt(1, i + 1);
+ upsertStmt.setInt(2, i + 2);
+ upsertStmt.setInt(3, i + 3);
+ upsertStmt.setInt(4, i + 5);
+ upsertStmt.execute();
+ }
+ conn.commit();
+
+ // No leading part of PK
+ String query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
+ + tempTableWithCompositePK + " lhs JOIN "
+ + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2";
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 4);
+ assertEquals(rs.getInt(4), 6);
+ assertEquals(rs.getInt(5), 1);
+ assertEquals(rs.getInt(6), 2);
+ assertEquals(rs.getInt(7), 3);
+ assertEquals(rs.getInt(8), 5);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 4);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 7);
+ assertEquals(rs.getInt(5), 2);
+ assertEquals(rs.getInt(6), 3);
+ assertEquals(rs.getInt(7), 4);
+ assertEquals(rs.getInt(8), 6);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(String.format(plans[0],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
+
+ // Two parts of PK but only one leading part
+ query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
+ + tempTableWithCompositePK + " lhs JOIN "
+ + tempTableWithCompositePK + " rhs ON lhs.col2 = rhs.col3 AND lhs.col0 = rhs.col2";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 4);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 7);
+ assertEquals(rs.getInt(5), 1);
+ assertEquals(rs.getInt(6), 2);
+ assertEquals(rs.getInt(7), 3);
+ assertEquals(rs.getInt(8), 5);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(String.format(plans[1],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
+
+ // Two leading parts of PK
+ query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
+ + tempTableWithCompositePK + " lhs JOIN "
+ + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2 AND lhs.col0 = rhs.col1";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 4);
+ assertEquals(rs.getInt(4), 6);
+ assertEquals(rs.getInt(5), 1);
+ assertEquals(rs.getInt(6), 2);
+ assertEquals(rs.getInt(7), 3);
+ assertEquals(rs.getInt(8), 5);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 4);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 7);
+ assertEquals(rs.getInt(5), 2);
+ assertEquals(rs.getInt(6), 3);
+ assertEquals(rs.getInt(7), 4);
+ assertEquals(rs.getInt(8), 6);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(String.format(plans[2],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
+
+ // All parts of PK
+ query = "SELECT lhs.col0, lhs.col1, lhs.col2, lhs.col3, rhs.col0, rhs.col1, rhs.col2, rhs.col3 FROM "
+ + tempTableWithCompositePK + " lhs JOIN "
+ + tempTableWithCompositePK + " rhs ON lhs.col1 = rhs.col2 AND lhs.col2 = rhs.col3 - 1 AND lhs.col0 = rhs.col1";
+ statement = conn.prepareStatement(query);
+ rs = statement.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 2);
+ assertEquals(rs.getInt(2), 3);
+ assertEquals(rs.getInt(3), 4);
+ assertEquals(rs.getInt(4), 6);
+ assertEquals(rs.getInt(5), 1);
+ assertEquals(rs.getInt(6), 2);
+ assertEquals(rs.getInt(7), 3);
+ assertEquals(rs.getInt(8), 5);
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 3);
+ assertEquals(rs.getInt(2), 4);
+ assertEquals(rs.getInt(3), 5);
+ assertEquals(rs.getInt(4), 7);
+ assertEquals(rs.getInt(5), 2);
+ assertEquals(rs.getInt(6), 3);
+ assertEquals(rs.getInt(7), 4);
+ assertEquals(rs.getInt(8), 6);
+
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ assertEquals(String.format(plans[3],tempTableWithCompositePK,tempTableWithCompositePK), QueryUtil.getExplainPlan(rs));
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSubqueryWithoutData() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ try {
+ String GRAMMAR_TABLE = "CREATE TABLE IF NOT EXISTS GRAMMAR_TABLE (ID INTEGER PRIMARY KEY, " +
+ "unsig_id UNSIGNED_INT, big_id BIGINT, unsig_long_id UNSIGNED_LONG, tiny_id TINYINT," +
+ "unsig_tiny_id UNSIGNED_TINYINT, small_id SMALLINT, unsig_small_id UNSIGNED_SMALLINT," +
+ "float_id FLOAT, unsig_float_id UNSIGNED_FLOAT, double_id DOUBLE, unsig_double_id UNSIGNED_DOUBLE," +
+ "decimal_id DECIMAL, boolean_id BOOLEAN, time_id TIME, date_id DATE, timestamp_id TIMESTAMP," +
+ "unsig_time_id TIME, unsig_date_id DATE, unsig_timestamp_id TIMESTAMP, varchar_id VARCHAR (30)," +
+ "char_id CHAR (30), binary_id BINARY (100), varbinary_id VARBINARY (100))";
+
+ String LARGE_TABLE = "CREATE TABLE IF NOT EXISTS LARGE_TABLE (ID INTEGER PRIMARY KEY, " +
+ "unsig_id UNSIGNED_INT, big_id BIGINT, unsig_long_id UNSIGNED_LONG, tiny_id TINYINT," +
+ "unsig_tiny_id UNSIGNED_TINYINT, small_id SMALLINT, unsig_small_id UNSIGNED_SMALLINT," +
+ "float_id FLOAT, unsig_float_id UNSIGNED_FLOAT, double_id DOUBLE, unsig_double_id UNSIGNED_DOUBLE," +
+ "decimal_id DECIMAL, boolean_id BOOLEAN, time_id TIME, date_id DATE, timestamp_id TIMESTAMP," +
+ "unsig_time_id TIME, unsig_date_id DATE, unsig_timestamp_id TIMESTAMP, varchar_id VARCHAR (30)," +
+ "char_id CHAR (30), binary_id BINARY (100), varbinary_id VARBINARY (100))";
+
+ String SECONDARY_LARGE_TABLE = "CREATE TABLE IF NOT EXISTS SECONDARY_LARGE_TABLE (SEC_ID INTEGER PRIMARY KEY," +
+ "sec_unsig_id UNSIGNED_INT, sec_big_id BIGINT, sec_usnig_long_id UNSIGNED_LONG, sec_tiny_id TINYINT," +
+ "sec_unsig_tiny_id UNSIGNED_TINYINT, sec_small_id SMALLINT, sec_unsig_small_id UNSIGNED_SMALLINT," +
+ "sec_float_id FLOAT, sec_unsig_float_id UNSIGNED_FLOAT, sec_double_id DOUBLE, sec_unsig_double_id UNSIGNED_DOUBLE," +
+ "sec_decimal_id DECIMAL, sec_boolean_id BOOLEAN, sec_time_id TIME, sec_date_id DATE," +
+ "sec_timestamp_id TIMESTAMP, sec_unsig_time_id TIME, sec_unsig_date_id DATE, sec_unsig_timestamp_id TIMESTAMP," +
+ "sec_varchar_id VARCHAR (30), sec_char_id CHAR (30), sec_binary_id BINARY (100), sec_varbinary_id VARBINARY (100))";
+ createTestTable(getUrl(), GRAMMAR_TABLE);
+ createTestTable(getUrl(), LARGE_TABLE);
+ createTestTable(getUrl(), SECONDARY_LARGE_TABLE);
+
+ String ddl = "SELECT * FROM (SELECT ID, BIG_ID, DATE_ID FROM LARGE_TABLE AS A WHERE (A.ID % 5) = 0) AS A " +
+ "INNER JOIN (SELECT SEC_ID, SEC_TINY_ID, SEC_UNSIG_FLOAT_ID FROM SECONDARY_LARGE_TABLE AS B WHERE (B.SEC_ID % 5) = 0) AS B " +
+ "ON A.ID=B.SEC_ID WHERE A.DATE_ID > ALL (SELECT SEC_DATE_ID FROM SECONDARY_LARGE_TABLE LIMIT 100) " +
+ "AND B.SEC_UNSIG_FLOAT_ID = ANY (SELECT sec_unsig_float_id FROM SECONDARY_LARGE_TABLE " +
+ "WHERE SEC_ID > ALL (SELECT MIN (ID) FROM GRAMMAR_TABLE WHERE UNSIG_ID IS NULL) AND " +
+ "SEC_UNSIG_ID < ANY (SELECT DISTINCT(UNSIG_ID) FROM LARGE_TABLE WHERE UNSIG_ID<2500) LIMIT 1000) " +
+ "AND A.ID < 10000";
+ ResultSet rs = conn.createStatement().executeQuery(ddl);
+ assertFalse(rs.next());
+ } finally {
+ Statement statement = conn.createStatement();
+ String query = "drop table GRAMMAR_TABLE";
+ statement.executeUpdate(query);
+ query = "drop table LARGE_TABLE";
+ statement.executeUpdate(query);
+ query = "drop table SECONDARY_LARGE_TABLE";
+ statement.executeUpdate(query);
+ conn.close();
+ }
+ }
+
+ // PHOENIX-2381
+ @Test
+ public void testJoinWithMultiTenancy() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE INVENTORY (" +
+ " TENANTID UNSIGNED_INT NOT NULL" +
+ ",ID UNSIGNED_INT NOT NULL" +
+ ",FOO UNSIGNED_INT NOT NULL" +
+ ",\"TIMESTAMP\" UNSIGNED_LONG NOT NULL" +
+ ",CODES INTEGER ARRAY[] NOT NULL" +
+ ",V UNSIGNED_LONG" +
+ " CONSTRAINT pk PRIMARY KEY (TENANTID, ID, FOO, \"TIMESTAMP\" , CODES))" +
+ " DEFAULT_COLUMN_FAMILY ='E'," +
+ " MULTI_TENANT=true");
+ PreparedStatement upsertStmt = conn.prepareStatement(
+ "upsert into INVENTORY "
+ + "(tenantid, id, foo, \"TIMESTAMP\" , codes) "
+ + "values (?, ?, ?, ?, ?)");
+ upsertStmt.setInt(1, 15);
+ upsertStmt.setInt(2, 5);
+ upsertStmt.setInt(3, 0);
+ upsertStmt.setLong(4, 6);
+ Array array = conn.createArrayOf("INTEGER", new Object[] {1, 2});
+ upsertStmt.setArray(5, array);
+ upsertStmt.executeUpdate();
+ conn.commit();
+
+ conn.createStatement().execute("CREATE TABLE PRODUCT_IDS (" +
+ " PRODUCT_ID UNSIGNED_INT NOT NULL" +
+ ",PRODUCT_NAME VARCHAR" +
+ " CONSTRAINT pk PRIMARY KEY (PRODUCT_ID))" +
+ " DEFAULT_COLUMN_FAMILY ='NAME'");
+ upsertStmt = conn.prepareStatement(
+ "upsert into PRODUCT_IDS "
+ + "(product_id, product_name) "
+ + "values (?, ?)");
+ upsertStmt.setInt(1, 5);
+ upsertStmt.setString(2, "DUMMY");
+ upsertStmt.executeUpdate();
+ conn.commit();
+ conn.close();
+
+ // Create a tenant-specific connection.
+ props.setProperty("TenantId", "15");
+ conn = DriverManager.getConnection(getUrl(), props);
+ ResultSet rs = conn.createStatement().executeQuery(
+ "SELECT * FROM INVENTORY INNER JOIN PRODUCT_IDS ON (PRODUCT_ID = INVENTORY.ID)");
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 5);
+ assertFalse(rs.next());
+ rs.close();
+ rs = conn.createStatement().executeQuery(
+ "SELECT * FROM INVENTORY RIGHT JOIN PRODUCT_IDS ON (PRODUCT_ID = INVENTORY.ID)");
+ assertTrue(rs.next());
+ assertEquals(rs.getInt(1), 5);
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testBug2480() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE master_businessunit ("
+ + "code varchar(255) PRIMARY KEY, name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE master_company ("
+ + "code varchar(255) PRIMARY KEY, name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE master_costcenter ("
+ + "code varchar(255) PRIMARY KEY, name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE master_location ("
+ + "code varchar(255) PRIMARY KEY, name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE master_product ("
+ + "id integer PRIMARY KEY, product_name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE master_purchaseorder ("
+ + "purchaseOrderNumber varchar(255), "
+ + "companyCode varchar(255), "
+ + "businessUnitCode varchar(255), "
+ + "locationCode varchar(255), "
+ + "purchaseOrderId varchar(255) PRIMARY KEY, "
+ + "releasedOn date, name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE trans_purchaseorderitem ("
+ + "purchaseOrderItemId varchar(255) PRIMARY KEY, "
+ + "purchaseOrderId varchar(255), "
+ + "lineNo varchar(255), name varchar(255))");
+ conn.createStatement().execute(
+ "CREATE TABLE trans_purchaseorderitem_costing ("
+ + "purchaseorderItem_costing_id varchar(255) primary key, "
+ + "purchaseorderItemId varchar(255), "
+ + "purchaseorderId varchar(255), "
+ + "costcenterCode varchar(255))");
+
+ conn.createStatement().execute("upsert into master_businessunit(code,name) values ('1','BU1')");
+ conn.createStatement().execute("upsert into master_businessunit(code,name) values ('2','BU2')");
+ conn.createStatement().execute("upsert into master_company(code,name) values ('1','Company1')");
+ conn.createStatement().execute("upsert into master_company(code,name) values ('2','Company2')");
+ conn.createStatement().execute("upsert into master_costcenter(code,name) values ('1','CC1')");
+ conn.createStatement().execute("upsert into master_costcenter(code,name) values ('2','CC2')");
+ conn.createStatement().execute("upsert into master_location(code,name) values ('1','Location1')");
+ conn.createStatement().execute("upsert into master_location(code,name) values ('2','Location2')");
+ conn.createStatement().execute("upsert into master_product(id,product_name) values (1,'ProductName1')");
+ conn.createStatement().execute("upsert into master_product(id,product_name) values (2,'Product2')");
+ conn.createStatement().execute("upsert into master_purchaseorder(purchaseOrderNumber,companyCode,businessUnitCode,locationCode,purchaseOrderId,releasedOn,name) values ('1','1','1','1','1','2015-12-01','1')");
+ conn.createStatement().execute("upsert into master_purchaseorder(purchaseOrderNumber,companyCode,businessUnitCode,locationCode,purchaseOrderId,releasedOn,name) values ('2','2','2','2','2','2015-12-02','2')");
+ conn.createStatement().execute("upsert into trans_purchaseorderitem(purchaseOrderItemId,purchaseOrderId,lineNo,name) values ('1','1','1','1')");
+ conn.createStatement().execute("upsert into trans_purchaseorderitem(purchaseOrderItemId,purchaseOrderId,lineNo,name) values ('2','2','2','2')");
+ conn.createStatement().execute("upsert into trans_purchaseorderitem_costing(purchaseorderItem_costing_id,purchaseorderItemId,purchaseorderId,costcenterCode) values ('1','1','1','1')");
+ conn.createStatement().execute("upsert into trans_purchaseorderitem_costing(purchaseorderItem_costing_id,purchaseorderItemId,purchaseorderId,costcenterCode) values ('2','2','2','2')");
+
+ ResultSet rs = conn.createStatement().executeQuery(
+ "SELECT DISTINCT "
+ + "COALESCE( a1.name, 'N.A.'), "
+ + "COALESCE( a2.name, 'N.A.'), "
+ + "COALESCE( a3.name, 'N.A.'), "
+ + "COALESCE( a4.purchaseOrderNumber, 'N.A.'), "
+ + "COALESCE( a1.name, 'N.A.'), "
+ + "COALESCE( a4.name, 'N.A.'), "
+ + "COALESCE( a5.lineNo, 'N.A.'), "
+ + "COALESCE( a5.name, 'N.A.'), "
+ + "COALESCE( a7.name,'N.A.') "
+ + "FROM (master_purchaseorder a4 "
+ + "LEFT OUTER JOIN master_company a1 "
+ + "ON a4.companyCode = a1.code "
+ + "LEFT OUTER JOIN master_businessunit a2 "
+ + "ON a4.businessUnitCode = a2.code "
+ + "LEFT OUTER JOIN master_location a3 "
+ + "ON a4.locationCode = a3.code "
+ + "LEFT OUTER JOIN trans_purchaseorderitem a5 "
+ + "ON a5.purchaseOrderId = a4.purchaseOrderId "
+ + "LEFT OUTER JOIN trans_purchaseorderitem_costing a6 "
+ + "ON a6.purchaseOrderItemId = a5.purchaseOrderItemId "
+ + "AND a6.purchaseOrderId = a5.purchaseOrderId "
+ + "LEFT OUTER JOIN master_costcenter a7 "
+ + "ON a6.costCenterCode = a7.code)");
+
+ assertTrue(rs.next());
+ assertEquals("Company1", rs.getString(1));
+ assertEquals("BU1", rs.getString(2));
+ assertEquals("Location1", rs.getString(3));
+ assertEquals("1", rs.getString(4));
+ assertEquals("Company1", rs.getString(5));
+ assertEquals("1", rs.getString(6));
+ assertEquals("1", rs.getString(7));
+ assertEquals("1", rs.getString(8));
+ assertEquals("CC1", rs.getString(9));
+ assertTrue(rs.next());
+ assertEquals("Company2", rs.getString(1));
+ assertEquals("BU2", rs.getString(2));
+ assertEquals("Location2", rs.getString(3));
+ assertEquals("2", rs.getString(4));
+ assertEquals("Company2", rs.getString(5));
+ assertEquals("2", rs.getString(6));
+ assertEquals("2", rs.getString(7));
+ assertEquals("2", rs.getString(8));
+ assertEquals("CC2", rs.getString(9));
+
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testBug2894() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ try {
+ conn.createStatement().execute(
+ "CREATE TABLE IF NOT EXISTS EVENT_COUNT (\n" +
+ " BUCKET VARCHAR,\n" +
+ " TIMESTAMP_DATE TIMESTAMP,\n" +
+ " \"TIMESTAMP\" UNSIGNED_LONG NOT NULL,\n" +
+ " LOCATION VARCHAR,\n" +
+ " A VARCHAR,\n" +
+ " B VARCHAR,\n" +
+ " C VARCHAR,\n" +
+ " D UNSIGNED_LONG,\n" +
+ " E FLOAT\n" +
+ " CONSTRAINT pk PRIMARY KEY (BUCKET, \"TIMESTAMP\" DESC, LOCATION, A, B, C)\n" +
+ ") SALT_BUCKETS=2, COMPRESSION='GZ', TTL=31622400");
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO EVENT_COUNT(BUCKET, \"TIMESTAMP\", LOCATION, A, B, C) VALUES(?,?,?,?,?,?)");
+ stmt.setString(1, "5SEC");
+ stmt.setString(3, "Tr/Bal");
+ stmt.setString(4, "A1");
+ stmt.setString(5, "B1");
+ stmt.setString(6, "C1");
+ stmt.setLong(2, 1462993520000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993515000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993510000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993505000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993500000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993495000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993490000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993485000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993480000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993475000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993470000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993465000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993460000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993455000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993450000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993445000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993440000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993430000000000L);
+ stmt.execute();
+
+ // We'll test the original version of the user table as well as a slightly modified
+ // version, in order to verify that hash join works for columns both having DESC
+ // sort order as well as one having ASC order and the other having DESC order.
+ String[] t = new String[] {"EVENT_LATENCY", "EVENT_LATENCY_2"};
+ for (int i = 0; i < 2; i++) {
+ conn.createStatement().execute(
+ "CREATE TABLE IF NOT EXISTS " + t[i] + " (\n" +
+ " BUCKET VARCHAR,\n" +
+ " TIMESTAMP_DATE TIMESTAMP,\n" +
+ " \"TIMESTAMP\" UNSIGNED_LONG NOT NULL,\n" +
+ " SRC_LOCATION VARCHAR,\n" +
+ " DST_LOCATION VARCHAR,\n" +
+ " B VARCHAR,\n" +
+ " C VARCHAR,\n" +
+ " F UNSIGNED_LONG,\n" +
+ " G UNSIGNED_LONG,\n" +
+ " H UNSIGNED_LONG,\n" +
+ " I UNSIGNED_LONG\n" +
+ " CONSTRAINT pk PRIMARY KEY (BUCKET, \"TIMESTAMP\"" + (i == 0 ? " DESC" : "") + ", SRC_LOCATION, DST_LOCATION, B, C)\n" +
+ ") SALT_BUCKETS=2, COMPRESSION='GZ', TTL=31622400");
+ stmt = conn.prepareStatement("UPSERT INTO " + t[i] + "(BUCKET, \"TIMESTAMP\", SRC_LOCATION, DST_LOCATION, B, C) VALUES(?,?,?,?,?,?)");
+ stmt.setString(1, "5SEC");
+ stmt.setString(3, "Tr/Bal");
+ stmt.setString(4, "Tr/Bal");
+ stmt.setString(5, "B1");
+ stmt.setString(6, "C1");
+ stmt.setLong(2, 1462993520000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993515000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993510000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993505000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993490000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993485000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993480000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993475000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993470000000000L);
+ stmt.execute();
+ stmt.setLong(2, 1462993430000000000L);
+ stmt.execute();
+
+ String q =
+ "SELECT C.BUCKET, C.\"TIMESTAMP\" FROM (\n" +
+ " SELECT E.BUCKET as BUCKET, L.BUCKET as LBUCKET, E.\"TIMESTAMP\" as TIMESTAMP, L.\"TIMESTAMP\" as LTIMESTAMP FROM\n" +
+ " (SELECT BUCKET, \"TIMESTAMP\" FROM EVENT_COUNT\n" +
+ " WHERE BUCKET = '5SEC' AND LOCATION = 'Tr/Bal'\n" +
+ " AND \"TIMESTAMP\" <= 1462993520000000000 AND \"TIMESTAMP\" > 1462993420000000000\n" +
+ " ) E\n" +
+ " JOIN\n" +
+ " (SELECT BUCKET, \"TIMESTAMP\" FROM "+ t[i] +"\n" +
+ " WHERE BUCKET = '5SEC' AND SRC_LOCATION = 'Tr/Bal' AND SRC_LOCATION = DST_LOCATION\n" +
+ " AND \"TIMESTAMP\" <= 1462993520000000000 AND \"TIMESTAMP\" > 1462993420000000000\n" +
+ " ) L\n" +
+ " ON L.BUCKET = E.BUCKET AND L.\"TIMESTAMP\" = E.\"TIMESTAMP\"\n" +
+ " ) C\n" +
+ " GROUP BY C.BUCKET, C.\"TIMESTAMP\"";
+
+ String p = i == 0 ?
+ "CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER EVENT_COUNT [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [E.BUCKET, \"E.TIMESTAMP\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER " + t[i] + " [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY AND SRC_LOCATION = DST_LOCATION\n" +
+ " CLIENT MERGE SORT"
+ :
+ "CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER EVENT_COUNT [0,'5SEC',~1462993520000000000,'Tr/Bal'] - [1,'5SEC',~1462993420000000000,'Tr/Bal']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [E.BUCKET, \"E.TIMESTAMP\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 2-WAY SKIP SCAN ON 2 RANGES OVER " + t[i] + " [0,'5SEC',1462993420000000001,'Tr/Bal'] - [1,'5SEC',1462993520000000000,'Tr/Bal']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY AND SRC_LOCATION = DST_LOCATION\n" +
+ " CLIENT MERGE SORT";
+
+ ResultSet rs = conn.createStatement().executeQuery("explain " + q);
+ assertEquals(p, QueryUtil.getExplainPlan(rs));
+
+ rs = conn.createStatement().executeQuery(q);
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993520000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993515000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993510000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993505000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993490000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993485000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993480000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993475000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993470000000000L, rs.getLong(2));
+ assertTrue(rs.next());
+ assertEquals("5SEC", rs.getString(1));
+ assertEquals(1462993430000000000L, rs.getLong(2));
+ assertFalse(rs.next());
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testBug2961() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(true);
+ try {
+ conn.createStatement().execute("CREATE TABLE test2961 (\n" +
+ "ACCOUNT_ID VARCHAR NOT NULL,\n" +
+ "BUCKET_ID VARCHAR NOT NULL,\n" +
+ "OBJECT_ID VARCHAR NOT NULL,\n" +
+ "OBJECT_VERSION VARCHAR NOT NULL,\n" +
+ "LOC VARCHAR,\n" +
+ "CONSTRAINT PK PRIMARY KEY (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION DESC))");
+ conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj1', '1111', 'loc1')");
+ ResultSet rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_VERSION = '1111'");
+ assertTrue(rs.next());
+ rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_ID = 'obj1'");
+ assertTrue(rs.next());
+ rs = conn.createStatement().executeQuery("select ACCOUNT_ID, BUCKET_ID, OBJECT_VERSION from test2961 WHERE ACCOUNT_ID = 'acct1' and BUCKET_ID = 'bucket1' and OBJECT_VERSION = '1111' and OBJECT_ID = 'obj1'");
+ assertTrue(rs.next());
+
+ conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj1', '2222', 'loc1')");
+ rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
+ + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER"
+ + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
+ + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
+ assertTrue(rs.next());
+ assertEquals("2222", rs.getString(4));
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
+ + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
+ + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
+ + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
+ assertTrue(rs.next());
+ assertEquals("2222", rs.getString(4));
+ assertFalse(rs.next());
+
+ rs = conn.createStatement().executeQuery("SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
+ + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
+ + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
+ + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.MAXVER = OBJ.OBJECT_VERSION");
+ assertTrue(rs.next());
+ assertEquals("2222", rs.getString(4));
+ assertFalse(rs.next());
+
+ conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj2', '1111', 'loc1')");
+ conn.createStatement().execute("UPSERT INTO test2961 (ACCOUNT_ID, BUCKET_ID, OBJECT_ID, OBJECT_VERSION, LOC) VALUES ('acct1', 'bucket1', 'obj3', '1111', 'loc1')");
+ String q = "SELECT OBJ.ACCOUNT_ID, OBJ.BUCKET_ID, OBJ.OBJECT_ID, OBJ.OBJECT_VERSION, OBJ.LOC "
+ + "FROM ( SELECT ACCOUNT_ID, BUCKET_ID, OBJECT_ID, MAX(OBJECT_VERSION) AS MAXVER "
+ + " FROM test2961 GROUP BY ACCOUNT_ID, BUCKET_ID, OBJECT_ID) AS X "
+ + " INNER JOIN test2961 AS OBJ ON X.ACCOUNT_ID = OBJ.ACCOUNT_ID AND X.BUCKET_ID = OBJ.BUCKET_ID AND X.OBJECT_ID = OBJ.OBJECT_ID AND X.MAXVER = OBJ.OBJECT_VERSION";
+ rs = conn.createStatement().executeQuery(q);
+ assertTrue(rs.next());
+ assertEquals("2222", rs.getString(4));
+ assertTrue(rs.next());
+ assertEquals("1111", rs.getString(4));
+ assertTrue(rs.next());
+ assertEquals("1111", rs.getString(4));
+ assertFalse(rs.next());
+ } finally {
+ conn.close();
+ }
+ }
+}
[08/25] phoenix git commit: PHOENIX-4246 Breakup join related tests
into several integration tests so as not to create too many tables in one
test
Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/BaseJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/BaseJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/BaseJoinIT.java
new file mode 100644
index 0000000..6e03a37
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/BaseJoinIT.java
@@ -0,0 +1,473 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import org.apache.phoenix.cache.ServerCacheClient;
+import org.apache.phoenix.end2end.ParallelStatsDisabledIT;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.StringUtil;
+import org.junit.Before;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+public abstract class BaseJoinIT extends ParallelStatsDisabledIT {
+
+ protected static final String JOIN_SCHEMA = "Join";
+ protected static final String JOIN_ORDER_TABLE = "OrderTable";
+ protected static final String JOIN_CUSTOMER_TABLE = "CustomerTable";
+ protected static final String JOIN_ITEM_TABLE = "ItemTable";
+ protected static final String JOIN_SUPPLIER_TABLE = "SupplierTable";
+ protected static final String JOIN_COITEM_TABLE = "CoitemTable";
+ protected static final String JOIN_ORDER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_ORDER_TABLE + '"';
+ protected static final String JOIN_CUSTOMER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_CUSTOMER_TABLE + '"';
+ protected static final String JOIN_ITEM_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_ITEM_TABLE + '"';
+ protected static final String JOIN_SUPPLIER_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_SUPPLIER_TABLE + '"';
+ protected static final String JOIN_COITEM_TABLE_FULL_NAME = '"' + JOIN_SCHEMA + "\".\"" + JOIN_COITEM_TABLE + '"';
+
+ private static final Map<String,String> tableDDLMap;
+
+ static {
+ ImmutableMap.Builder<String,String> builder = ImmutableMap.builder();
+ builder.put(JOIN_ORDER_TABLE_FULL_NAME, "create table " + JOIN_ORDER_TABLE_FULL_NAME +
+ " (\"order_id\" varchar(15) not null primary key, " +
+ " \"customer_id\" varchar(10), " +
+ " \"item_id\" varchar(10), " +
+ " price integer, " +
+ " quantity integer, " +
+ " date timestamp) IMMUTABLE_ROWS=true");
+ builder.put(JOIN_CUSTOMER_TABLE_FULL_NAME, "create table " + JOIN_CUSTOMER_TABLE_FULL_NAME +
+ " (\"customer_id\" varchar(10) not null primary key, " +
+ " name varchar, " +
+ " phone varchar(12), " +
+ " address varchar, " +
+ " loc_id varchar(5), " +
+ " date date) IMMUTABLE_ROWS=true");
+ builder.put(JOIN_ITEM_TABLE_FULL_NAME, "create table " + JOIN_ITEM_TABLE_FULL_NAME +
+ " (\"item_id\" varchar(10) not null primary key, " +
+ " name varchar, " +
+ " price integer, " +
+ " discount1 integer, " +
+ " discount2 integer, " +
+ " \"supplier_id\" varchar(10), " +
+ " description varchar)");
+ builder.put(JOIN_SUPPLIER_TABLE_FULL_NAME, "create table " + JOIN_SUPPLIER_TABLE_FULL_NAME +
+ " (\"supplier_id\" varchar(10) not null primary key, " +
+ " name varchar, " +
+ " phone varchar(12), " +
+ " address varchar, " +
+ " loc_id varchar(5))");
+ builder.put(JOIN_COITEM_TABLE_FULL_NAME, "create table " + JOIN_COITEM_TABLE_FULL_NAME +
+ " (item_id varchar(10) NOT NULL, " +
+ " item_name varchar NOT NULL, " +
+ " co_item_id varchar(10), " +
+ " co_item_name varchar " +
+ " CONSTRAINT pk PRIMARY KEY (item_id, item_name)) " +
+ " SALT_BUCKETS=4");
+ tableDDLMap = builder.build();
+ }
+
+ protected String seqName;
+ protected String schemaName;
+ protected final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ protected final String[] plans;
+ private final String[] indexDDL;
+ private final Map<String,String> virtualNameToRealNameMap = Maps.newHashMap();
+
+ public BaseJoinIT(String[] indexDDL, String[] plans) {
+ this.indexDDL = indexDDL;
+ this.plans = plans;
+ }
+
+ public BaseJoinIT() {
+ this.indexDDL = new String[0];
+ this.plans = new String[0];
+ }
+
+ protected String getTableName(Connection conn, String virtualName) throws Exception {
+ String realName = virtualNameToRealNameMap.get(virtualName);
+ if (realName == null) {
+ realName = SchemaUtil.getTableName(schemaName, generateUniqueName());
+ virtualNameToRealNameMap.put(virtualName, realName);
+ createTable(conn, virtualName, realName);
+ initValues(conn, virtualName, realName);
+ createIndexes(conn, virtualName, realName);
+ }
+ return realName;
+ }
+
+ protected String getDisplayTableName(Connection conn, String virtualName) throws Exception {
+ return getTableName(conn, virtualName);
+ }
+
+ private void createTable(Connection conn, String virtualName, String realName) throws SQLException {
+ String ddl = tableDDLMap.get(virtualName);
+ if (ddl == null) {
+ throw new IllegalStateException("Expected to find " + virtualName + " in " + tableDDLMap);
+ }
+ ddl = ddl.replace(virtualName, realName);
+ conn.createStatement().execute(ddl);
+ }
+
+ @Before
+ public void createSchema() throws SQLException {
+ Connection conn = DriverManager.getConnection(getUrl());
+ try {
+ schemaName = "S_" + generateUniqueName();
+ seqName = "SEQ_" + generateUniqueName();
+ conn.createStatement().execute("CREATE SEQUENCE " + seqName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ private String translateToVirtualPlan(String actualPlan) {
+ int size = virtualNameToRealNameMap.size();
+ String[] virtualNames = new String[size+1];
+ String[] realNames = new String[size+1];
+ int count = 0;
+ for (Map.Entry<String, String>entry : virtualNameToRealNameMap.entrySet()) {
+ virtualNames[count] = entry.getKey();
+ realNames[count] = entry.getValue();
+ count++;
+ }
+ realNames[count] = schemaName;
+ virtualNames[count]= JOIN_SCHEMA;
+ String convertedPlan = StringUtil.replace(actualPlan, realNames, virtualNames);
+ return convertedPlan;
+ }
+
+ protected void assertPlansMatch(String virtualPlanRegEx, String actualPlan) {
+ String convertedPlan = translateToVirtualPlan(actualPlan);
+ assertTrue("\"" + convertedPlan + "\" does not match \"" + virtualPlanRegEx + "\"", Pattern.matches(virtualPlanRegEx, convertedPlan));
+ }
+
+ protected void assertPlansEqual(String virtualPlan, String actualPlan) {
+ String convertedPlan = translateToVirtualPlan(actualPlan);
+ assertEquals(virtualPlan, convertedPlan);
+ }
+
+ private static void initValues(Connection conn, String virtualName, String realName) throws Exception {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ if (virtualName.equals(JOIN_CUSTOMER_TABLE_FULL_NAME)) {
+ // Insert into customer table
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + realName +
+ " (\"customer_id\", " +
+ " NAME, " +
+ " PHONE, " +
+ " ADDRESS, " +
+ " LOC_ID, " +
+ " DATE) " +
+ "values (?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, "0000000001");
+ stmt.setString(2, "C1");
+ stmt.setString(3, "999-999-1111");
+ stmt.setString(4, "101 XXX Street");
+ stmt.setString(5, "10001");
+ stmt.setDate(6, new Date(format.parse("2013-11-01 10:20:36").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "0000000002");
+ stmt.setString(2, "C2");
+ stmt.setString(3, "999-999-2222");
+ stmt.setString(4, "202 XXX Street");
+ stmt.setString(5, null);
+ stmt.setDate(6, new Date(format.parse("2013-11-25 16:45:07").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "0000000003");
+ stmt.setString(2, "C3");
+ stmt.setString(3, "999-999-3333");
+ stmt.setString(4, "303 XXX Street");
+ stmt.setString(5, null);
+ stmt.setDate(6, new Date(format.parse("2013-11-25 10:06:29").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "0000000004");
+ stmt.setString(2, "C4");
+ stmt.setString(3, "999-999-4444");
+ stmt.setString(4, "404 XXX Street");
+ stmt.setString(5, "10004");
+ stmt.setDate(6, new Date(format.parse("2013-11-22 14:22:56").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "0000000005");
+ stmt.setString(2, "C5");
+ stmt.setString(3, "999-999-5555");
+ stmt.setString(4, "505 XXX Street");
+ stmt.setString(5, "10005");
+ stmt.setDate(6, new Date(format.parse("2013-11-27 09:37:50").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "0000000006");
+ stmt.setString(2, "C6");
+ stmt.setString(3, "999-999-6666");
+ stmt.setString(4, "606 XXX Street");
+ stmt.setString(5, "10001");
+ stmt.setDate(6, new Date(format.parse("2013-11-01 10:20:36").getTime()));
+ stmt.execute();
+ } else if (virtualName.equals(JOIN_ITEM_TABLE_FULL_NAME)) {
+
+ // Insert into item table
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + realName +
+ " (\"item_id\", " +
+ " NAME, " +
+ " PRICE, " +
+ " DISCOUNT1, " +
+ " DISCOUNT2, " +
+ " \"supplier_id\", " +
+ " DESCRIPTION) " +
+ "values (?, ?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, "0000000001");
+ stmt.setString(2, "T1");
+ stmt.setInt(3, 100);
+ stmt.setInt(4, 5);
+ stmt.setInt(5, 10);
+ stmt.setString(6, "0000000001");
+ stmt.setString(7, "Item T1");
+ stmt.execute();
+
+ stmt.setString(1, "0000000002");
+ stmt.setString(2, "T2");
+ stmt.setInt(3, 200);
+ stmt.setInt(4, 5);
+ stmt.setInt(5, 8);
+ stmt.setString(6, "0000000001");
+ stmt.setString(7, "Item T2");
+ stmt.execute();
+
+ stmt.setString(1, "0000000003");
+ stmt.setString(2, "T3");
+ stmt.setInt(3, 300);
+ stmt.setInt(4, 8);
+ stmt.setInt(5, 12);
+ stmt.setString(6, "0000000002");
+ stmt.setString(7, "Item T3");
+ stmt.execute();
+
+ stmt.setString(1, "0000000004");
+ stmt.setString(2, "T4");
+ stmt.setInt(3, 400);
+ stmt.setInt(4, 6);
+ stmt.setInt(5, 10);
+ stmt.setString(6, "0000000002");
+ stmt.setString(7, "Item T4");
+ stmt.execute();
+
+ stmt.setString(1, "0000000005");
+ stmt.setString(2, "T5");
+ stmt.setInt(3, 500);
+ stmt.setInt(4, 8);
+ stmt.setInt(5, 15);
+ stmt.setString(6, "0000000005");
+ stmt.setString(7, "Item T5");
+ stmt.execute();
+
+ stmt.setString(1, "0000000006");
+ stmt.setString(2, "T6");
+ stmt.setInt(3, 600);
+ stmt.setInt(4, 8);
+ stmt.setInt(5, 15);
+ stmt.setString(6, "0000000006");
+ stmt.setString(7, "Item T6");
+ stmt.execute();
+
+ stmt.setString(1, "invalid001");
+ stmt.setString(2, "INVALID-1");
+ stmt.setInt(3, 0);
+ stmt.setInt(4, 0);
+ stmt.setInt(5, 0);
+ stmt.setString(6, "0000000000");
+ stmt.setString(7, "Invalid item for join test");
+ stmt.execute();
+ } else if (virtualName.equals(JOIN_SUPPLIER_TABLE_FULL_NAME)) {
+
+ // Insert into supplier table
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + realName +
+ " (\"supplier_id\", " +
+ " NAME, " +
+ " PHONE, " +
+ " ADDRESS, " +
+ " LOC_ID) " +
+ "values (?, ?, ?, ?, ?)");
+ stmt.setString(1, "0000000001");
+ stmt.setString(2, "S1");
+ stmt.setString(3, "888-888-1111");
+ stmt.setString(4, "101 YYY Street");
+ stmt.setString(5, "10001");
+ stmt.execute();
+
+ stmt.setString(1, "0000000002");
+ stmt.setString(2, "S2");
+ stmt.setString(3, "888-888-2222");
+ stmt.setString(4, "202 YYY Street");
+ stmt.setString(5, "10002");
+ stmt.execute();
+
+ stmt.setString(1, "0000000003");
+ stmt.setString(2, "S3");
+ stmt.setString(3, "888-888-3333");
+ stmt.setString(4, "303 YYY Street");
+ stmt.setString(5, null);
+ stmt.execute();
+
+ stmt.setString(1, "0000000004");
+ stmt.setString(2, "S4");
+ stmt.setString(3, "888-888-4444");
+ stmt.setString(4, "404 YYY Street");
+ stmt.setString(5, null);
+ stmt.execute();
+
+ stmt.setString(1, "0000000005");
+ stmt.setString(2, "S5");
+ stmt.setString(3, "888-888-5555");
+ stmt.setString(4, "505 YYY Street");
+ stmt.setString(5, "10005");
+ stmt.execute();
+
+ stmt.setString(1, "0000000006");
+ stmt.setString(2, "S6");
+ stmt.setString(3, "888-888-6666");
+ stmt.setString(4, "606 YYY Street");
+ stmt.setString(5, "10006");
+ stmt.execute();
+ } else if (virtualName.equals(JOIN_ORDER_TABLE_FULL_NAME)) {
+
+ // Insert into order table
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + realName +
+ " (\"order_id\", " +
+ " \"customer_id\", " +
+ " \"item_id\", " +
+ " PRICE, " +
+ " QUANTITY," +
+ " DATE) " +
+ "values (?, ?, ?, ?, ?, ?)");
+ stmt.setString(1, "000000000000001");
+ stmt.setString(2, "0000000004");
+ stmt.setString(3, "0000000001");
+ stmt.setInt(4, 100);
+ stmt.setInt(5, 1000);
+ stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-22 14:22:56").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "000000000000002");
+ stmt.setString(2, "0000000003");
+ stmt.setString(3, "0000000006");
+ stmt.setInt(4, 552);
+ stmt.setInt(5, 2000);
+ stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-25 10:06:29").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "000000000000003");
+ stmt.setString(2, "0000000002");
+ stmt.setString(3, "0000000002");
+ stmt.setInt(4, 190);
+ stmt.setInt(5, 3000);
+ stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-25 16:45:07").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "000000000000004");
+ stmt.setString(2, "0000000004");
+ stmt.setString(3, "0000000006");
+ stmt.setInt(4, 510);
+ stmt.setInt(5, 4000);
+ stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-26 13:26:04").getTime()));
+ stmt.execute();
+
+ stmt.setString(1, "000000000000005");
+ stmt.setString(2, "0000000005");
+ stmt.setString(3, "0000000003");
+ stmt.setInt(4, 264);
+ stmt.setInt(5, 5000);
+ stmt.setTimestamp(6, new Timestamp(format.parse("2013-11-27 09:37:50").getTime()));
+ stmt.execute();
+ } else if (virtualName.equals(JOIN_COITEM_TABLE_FULL_NAME)) {
+ // Insert into coitem table
+ PreparedStatement stmt = conn.prepareStatement(
+ "upsert into " + realName +
+ " (item_id, " +
+ " item_name, " +
+ " co_item_id, " +
+ " co_item_name) " +
+ "values (?, ?, ?, ?)");
+ stmt.setString(1, "0000000001");
+ stmt.setString(2, "T1");
+ stmt.setString(3, "0000000002");
+ stmt.setString(4, "T3");
+ stmt.execute();
+
+ stmt.setString(1, "0000000004");
+ stmt.setString(2, "T4");
+ stmt.setString(3, "0000000003");
+ stmt.setString(4, "T3");
+ stmt.execute();
+
+ stmt.setString(1, "0000000003");
+ stmt.setString(2, "T4");
+ stmt.setString(3, "0000000005");
+ stmt.setString(4, "T5");
+ stmt.execute();
+
+ stmt.setString(1, "0000000006");
+ stmt.setString(2, "T6");
+ stmt.setString(3, "0000000001");
+ stmt.setString(4, "T1");
+ stmt.execute();
+ }
+
+ conn.commit();
+ }
+
+ protected Connection getConnection() throws SQLException {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.put(ServerCacheClient.HASH_JOIN_SERVER_CACHE_RESEND_PER_SERVER, "true");
+ return DriverManager.getConnection(getUrl(), props);
+ }
+
+ protected void createIndexes(Connection conn, String virtualName, String realName) throws Exception {
+ if (indexDDL != null && indexDDL.length > 0) {
+ for (String ddl : indexDDL) {
+ String newDDL = ddl.replace(virtualName, realName);
+ if (!newDDL.equals(ddl)) {
+ conn.createStatement().execute(newDDL);
+ }
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinCacheIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinCacheIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinCacheIT.java
new file mode 100644
index 0000000..c49c61f
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinCacheIT.java
@@ -0,0 +1,101 @@
+/*
+ * 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.end2end.join;
+
+import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.coprocessor.ObserverContext;
+import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
+import org.apache.hadoop.hbase.coprocessor.SimpleRegionObserver;
+import org.apache.hadoop.hbase.regionserver.RegionScanner;
+import org.apache.phoenix.cache.GlobalCache;
+import org.apache.phoenix.cache.TenantCache;
+import org.apache.phoenix.coprocessor.HashJoinCacheNotFoundException;
+import org.apache.phoenix.hbase.index.util.ImmutableBytesPtr;
+import org.apache.phoenix.join.HashJoinInfo;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Test;
+
+public class HashJoinCacheIT extends BaseJoinIT {
+
+ @Override
+ protected String getTableName(Connection conn, String virtualName) throws Exception {
+ String realName = super.getTableName(conn, virtualName);
+ TestUtil.addCoprocessor(conn, SchemaUtil.normalizeFullTableName(realName), InvalidateHashCache.class);
+ return realName;
+ }
+
+ @Test
+ public void testExpiredCache() throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ props.setProperty(QueryServices.MAX_SERVER_CACHE_TIME_TO_LIVE_MS_ATTRIB, "1");
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ String tableName1 = getTableName(conn, JOIN_SUPPLIER_TABLE_FULL_NAME);
+ String tableName2 = getTableName(conn, JOIN_ITEM_TABLE_FULL_NAME);
+ String query = "SELECT item.\"item_id\", item.name, supp.\"supplier_id\", supp.name FROM " +
+ tableName1 + " supp RIGHT JOIN " + tableName2 +
+ " item ON item.\"supplier_id\" = supp.\"supplier_id\" ORDER BY \"item_id\"";
+ try {
+ PreparedStatement statement = conn.prepareStatement(query);
+ ResultSet rs = statement.executeQuery();
+ rs.next();
+ fail("HashJoinCacheNotFoundException was not thrown or incorrectly handled");
+ } catch (HashJoinCacheNotFoundException e) {
+ //Expected exception
+ }
+ }
+
+ public static class InvalidateHashCache extends SimpleRegionObserver {
+ public static Random rand= new Random();
+ public static List<ImmutableBytesPtr> lastRemovedJoinIds=new ArrayList<ImmutableBytesPtr>();
+ @Override
+ public RegionScanner preScannerOpen(final ObserverContext<RegionCoprocessorEnvironment> c, final Scan scan,
+ final RegionScanner s) throws IOException {
+ final HashJoinInfo joinInfo = HashJoinInfo.deserializeHashJoinFromScan(scan);
+ if (joinInfo != null) {
+ TenantCache cache = GlobalCache.getTenantCache(c.getEnvironment(), null);
+ int count = joinInfo.getJoinIds().length;
+ for (int i = 0; i < count; i++) {
+ ImmutableBytesPtr joinId = joinInfo.getJoinIds()[i];
+ if (!ByteUtil.contains(lastRemovedJoinIds,joinId)) {
+ lastRemovedJoinIds.add(joinId);
+ cache.removeServerCache(joinId);
+ }
+ }
+ }
+ return s;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/ee20a8c9/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
new file mode 100644
index 0000000..76944a6
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/join/HashJoinGlobalIndexIT.java
@@ -0,0 +1,399 @@
+/*
+ * 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.end2end.join;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.collect.Lists;
+
+public class HashJoinGlobalIndexIT extends HashJoinIT {
+
+ public HashJoinGlobalIndexIT(String[] indexDDL, String[] plans) {
+ super(indexDDL, plans);
+ }
+
+ @Parameters
+ public static Collection<Object> data() {
+ List<Object> testCases = Lists.newArrayList();
+ testCases.add(new String[][] {
+ {
+ "CREATE INDEX \"idx_customer\" ON " + JOIN_CUSTOMER_TABLE_FULL_NAME + " (name)",
+ "CREATE INDEX \"idx_item\" ON " + JOIN_ITEM_TABLE_FULL_NAME + " (name) INCLUDE (price, discount1, discount2, \"supplier_id\", description)",
+ "CREATE INDEX \"idx_supplier\" ON " + JOIN_SUPPLIER_TABLE_FULL_NAME + " (name)"
+ }, {
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * LEFT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC"
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"I.:item_id\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testLeftJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinItemTable i
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.0:NAME\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testRightJoinWithAggregation()
+ * SELECT i.item_id iid, sum(quantity) q FROM joinOrderTable o
+ * RIGHT JOIN joinItemTable i ON o.item_id = i.item_id
+ * GROUP BY i.item_id ORDER BY q DESC NULLS LAST, iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [\"I.item_id\"]\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC NULLS LAST, \"I.item_id\"]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithWildcard()
+ * SELECT * FROM joinItemTable LEFT JOIN joinSupplierTable supp
+ * ON joinItemTable.supplier_id = supp.supplier_id
+ * ORDER BY item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item LEFT JOIN joinSupplierTable supp
+ * ON substr(item.name, 2, 1) = substr(supp.name, 2, 1)
+ * AND (supp.name BETWEEN 'S1' AND 'S5')
+ * WHERE item.name BETWEEN 'T1' AND 'T5'
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SCHEMA + ".idx_item ['T1'] - ['T5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_SCHEMA + ".idx_supplier ['S1'] - ['S5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testJoinPlanWithIndex()
+ * SELECT item.item_id, item.name, supp.supplier_id, supp.name
+ * FROM joinItemTable item INNER JOIN joinSupplierTable supp
+ * ON item.supplier_id = supp.supplier_id
+ * WHERE (item.name = 'T1' OR item.name = 'T5')
+ * AND (supp.name = 'S1' OR supp.name = 'S5')
+ */
+ "CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SCHEMA + ".idx_item ['T1'] - ['T5']\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY SKIP SCAN ON 2 KEYS OVER " + JOIN_SCHEMA + ".idx_supplier ['S1'] - ['S5']\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testJoinWithSkipMergeOptimization()
+ * SELECT s.name FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id AND quantity < 5000
+ * JOIN joinSupplierTable s ON i.supplier_id = s.supplier_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL INNER-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY QUANTITY < 5000\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_supplier\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testSelfJoin()
+ * SELECT i2.item_id, i1.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.item_id
+ * ORDER BY i1.item_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " DYNAMIC SERVER FILTER BY \"I1.item_id\" IN (\"I2.:item_id\")",
+ /*
+ * testSelfJoin()
+ * SELECT i1.name, i2.name FROM joinItemTable i1
+ * JOIN joinItemTable i2 ON i1.item_id = i2.supplier_id
+ * ORDER BY i1.name, i2.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"I1.0:NAME\", \"I2.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item",
+ /*
+ * testStarJoin()
+ * SELECT order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " PARALLEL INNER-JOIN TABLE 1\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testStarJoin()
+ * SELECT (*NO_STAR_JOIN*) order_id, c.name, i.name iname, quantity, o.date
+ * FROM joinOrderTable o
+ * JOIN joinCustomerTable c ON o.customer_id = c.customer_id
+ * JOIN joinItemTable i ON o.item_id = i.item_id
+ * ORDER BY order_id
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [\"O.order_id\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_customer\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testSubJoin()
+ * SELECT * FROM joinCustomerTable c
+ * INNER JOIN (joinOrderTable o
+ * INNER JOIN (joinSupplierTable s
+ * RIGHT JOIN joinItemTable i ON i.supplier_id = s.supplier_id)
+ * ON o.item_id = i.item_id)
+ * ON c.customer_id = o.customer_id
+ * WHERE c.customer_id <= '0000000005'
+ * AND order_id != '000000000000003'
+ * AND i.name != 'T3'
+ * ORDER BY c.customer_id, i.name
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [\"C.customer_id\", \"I.0:NAME\"]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY \"NAME\" != 'T3'\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"C.customer_id\" IN (\"O.customer_id\")",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.name, sum(quantity) FROM joinOrderTable o
+ * LEFT JOIN (SELECT name, item_id iid FROM joinItemTable) AS i
+ * ON o.item_id = i.iid
+ * GROUP BY i.name ORDER BY i.name
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [I.NAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT o.iid, sum(o.quantity) q
+ * FROM (SELECT item_id iid, quantity FROM joinOrderTable) AS o
+ * LEFT JOIN (SELECT item_id FROM joinItemTable) AS i
+ * ON o.iid = i.item_id
+ * GROUP BY o.iid ORDER BY q DESC
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [O.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ "CLIENT SORTED BY [SUM(O.QUANTITY) DESC]\n" +
+ " PARALLEL LEFT-JOIN TABLE 0 (SKIP MERGE)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid FROM joinItemTable) AS i
+ * LEFT JOIN (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC NULLS LAST, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC NULLS LAST, I.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testJoinWithSubqueryAndAggregation()
+ * SELECT i.iid, o.q
+ * FROM (SELECT item_id iid, sum(quantity) q FROM joinOrderTable GROUP BY item_id) AS o
+ * JOIN (SELECT item_id iid FROM joinItemTable) AS i
+ * ON o.iid = i.iid
+ * ORDER BY o.q DESC, i.iid
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ " SERVER SORTED BY [O.Q DESC, I.IID]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER AGGREGATE INTO DISTINCT ROWS BY [\"item_id\"]\n" +
+ " CLIENT MERGE SORT",
+ /*
+ * testNestedSubqueries()
+ * SELECT * FROM (SELECT customer_id cid, name, phone, address, loc_id, date FROM joinCustomerTable) AS c
+ * INNER JOIN (SELECT o.oid ooid, o.cid ocid, o.iid oiid, o.price * o.quantity, o.date odate,
+ * qi.iiid iiid, qi.iname iname, qi.iprice iprice, qi.idiscount1 idiscount1, qi.idiscount2 idiscount2, qi.isid isid, qi.idescription idescription,
+ * qi.ssid ssid, qi.sname sname, qi.sphone sphone, qi.saddress saddress, qi.sloc_id sloc_id
+ * FROM (SELECT item_id iid, customer_id cid, order_id oid, price, quantity, date FROM joinOrderTable) AS o
+ * INNER JOIN (SELECT i.iid iiid, i.name iname, i.price iprice, i.discount1 idiscount1, i.discount2 idiscount2, i.sid isid, i.description idescription,
+ * s.sid ssid, s.name sname, s.phone sphone, s.address saddress, s.loc_id sloc_id
+ * FROM (SELECT supplier_id sid, name, phone, address, loc_id FROM joinSupplierTable) AS s
+ * RIGHT JOIN (SELECT item_id iid, name, price, discount1, discount2, supplier_id sid, description FROM joinItemTable) AS i
+ * ON i.sid = s.sid) as qi
+ * ON o.iid = qi.iiid) as qo
+ * ON c.cid = qo.ocid
+ * WHERE c.cid <= '0000000005'
+ * AND qo.ooid != '000000000000003'
+ * AND qo.iname != 'T3'
+ * ORDER BY c.cid, qo.iname
+ */
+ "CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + JOIN_CUSTOMER_TABLE_FULL_NAME + " [*] - ['0000000005']\n" +
+ " SERVER SORTED BY [C.CID, QO.INAME]\n" +
+ "CLIENT MERGE SORT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY \"NAME\" != 'T3'\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME,
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER 4 ROW LIMIT\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 4
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithSetMaxRows()
+ * statement.setMaxRows(4);
+ * SELECT order_id, i.name, quantity FROM joinItemTable i
+ * JOIN joinOrderTable o ON o.item_id = i.item_id;
+ * SELECT o.order_id, i.name, o.quantity FROM joinItemTable i
+ * JOIN (SELECT order_id, item_id, quantity FROM joinOrderTable) o
+ * ON o.item_id = i.item_id;
+ */
+ "CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
+ " SERVER FILTER BY FIRST KEY ONLY\n" +
+ "CLIENT 4 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 4 ROW LIMIT",
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * LEFT JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * LEFT JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ " SERVER 3 ROW LIMIT\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL LEFT-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL LEFT-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ /*
+ * testJoinWithLimit()
+ * SELECT order_id, i.name, s.name, s.address, quantity
+ * FROM joinSupplierTable s
+ * JOIN joinItemTable i ON i.supplier_id = s.supplier_id
+ * JOIN joinOrderTable o ON o.item_id = i.item_id LIMIT 1 OFFSET 2
+ */
+ "CLIENT SERIAL 1-WAY FULL SCAN OVER " + JOIN_SUPPLIER_TABLE_FULL_NAME + "\n" +
+ " SERVER OFFSET 2\n" +
+ "CLIENT 1 ROW LIMIT\n" +
+ " PARALLEL INNER-JOIN TABLE 0\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_SCHEMA + ".idx_item\n" +
+ " PARALLEL INNER-JOIN TABLE 1(DELAYED EVALUATION)\n" +
+ " CLIENT PARALLEL 1-WAY FULL SCAN OVER "+ JOIN_ORDER_TABLE_FULL_NAME + "\n" +
+ " DYNAMIC SERVER FILTER BY \"S.supplier_id\" IN (\"I.0:supplier_id\")\n" +
+ " JOIN-SCANNER 3 ROW LIMIT",
+ }});
+ return testCases;
+ }
+}